From 23560bb1fcffe22f25447b53e404fd8237fb8a39 Mon Sep 17 00:00:00 2001 From: anon Date: Sat, 26 Oct 2024 12:25:43 +0200 Subject: [PATCH] added stuff to manage a top album ranking --- album-scores.php | 286 +++++++++++++++++++++++++++++++++++++++++++++++ js/asm-admin.js | 49 ++++++++ plugin.php | 2 + 3 files changed, 337 insertions(+) create mode 100644 album-scores.php create mode 100644 js/asm-admin.js diff --git a/album-scores.php b/album-scores.php new file mode 100644 index 0000000..a4e19e4 --- /dev/null +++ b/album-scores.php @@ -0,0 +1,286 @@ +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 ); + + ?> +
+

Album Score Manager

+ + + + + + + + + + + + + + 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; + ?> + + + + + + + + + + + + + + + +
Album NameAuthorCoverTotal PlaysScoreStatus
+ + + + + + +
No albums found.
+
+ 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(); + } + +} \ No newline at end of file diff --git a/js/asm-admin.js b/js/asm-admin.js new file mode 100644 index 0000000..0679ffa --- /dev/null +++ b/js/asm-admin.js @@ -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('No score selected.'); + return; + } + + // Show loading message + statusCell.html('Updating...'); + + // 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('' + response.data + ''); + } else { + statusCell.html('' + response.data + ''); + } + }, + error: function() { + statusCell.html('AJAX error.'); + } + }); + }); +}); diff --git a/plugin.php b/plugin.php index f2dad10..53f83cf 100644 --- a/plugin.php +++ b/plugin.php @@ -13,8 +13,10 @@ if (!defined('ABSPATH')) { // Include the separate plugins 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'); // Initialize both classes new AlbumCollageGenerator(); new ScrobbleHandler(); +new AlbumScoreManager();