Commit 284b41a3 authored by Rob Myers's avatar Rob Myers

Add user interface to delete scrobbles using the Library function. Accessible from the Edit page.

parent aa1424a3
\ No newline at end of file
......@@ -42,7 +42,7 @@ class Library {
$delete_query = 'DELETE FROM Scrobbles WHERE userid=? AND time=? AND artist=? AND track=?';
$delete_params = array((int)$userid, (int)$timestamp, $artist, $track);
// TODO Should we have a db trigger for this?
- // TODO Should we have a db trigger for this?
$update_stats_query = 'UPDATE User_Stats SET scrobble_count=scrobble_count-1 WHERE userid=?';
$update_stats_params = array((int)$userid);
......@@ -51,6 +51,10 @@ class Library {
$adodb->Execute($delete_query, $delete_params);
$delete_count = $adodb->Affected_Rows();
if($delete_count) {
// This clears the *entire* cache, but we don't know which
// cached queries will reference the deleted scrobbles so
// we can't clear the cache for only those specific queries.
$adodb->Execute($update_stats_query, $update_stats_params);
} catch (Exception $e) {
{include file='header.tpl' subheader='user-header.tpl'}
<center><h3><a href='{$base_url}/user-edit.php'>{t}Edit your profile{/t}</a> | {t}Connections to other services{/t}</h3></center>
<center><h3><a href='{$base_url}/user-edit.php'>{t}Edit your profile{/t}</a> | {t}Connections to other services{/t} | <a href='{$base_url}/user-delete-tracks.php'>{t}Delete plays{/t}</a></h3></center>
{if isset($errors)}
<div id="errors">
{include file='header.tpl' subheader='user-header.tpl'}
<center><h3><a href='{$base_url}/user-edit.php'>{t}Edit your profile{/t}</a> | <a href='{$base_url}/user-connections.php'>{t}Connections to other services{/t}</a> | {t}Delete plays{/t}</h3></center>
{if isset($errors)}
<div id="errors">
{section loop=$errors name=error}
<div id="user-delete-tracks">
<p id="next-and-previous">
{if $prevOffset >= 0}
<a href="{$base_url}/user-delete-tracks.php?offset={$prevOffset}&amp;count={$scrobbleCount}">{t}Previous{/t} {$scrobbleCount}</a>
{t}Previous{/t} {$scrobbleCount}
{if $nextOffset >= 0}
<a href="{$base_url}/user-delete-tracks.php?offset={$nextOffset}&amp;count={$scrobbleCount}">{t}Next{/t} {$scrobbleCount}</a>
{t}Next{/t} {$scrobbleCount}
<form action='{$base_url}/user-delete-tracks.php' method='post' onkeypress='return event.keyCode != 13;'>
{section name=i loop=$scrobbles}
<label><input type="checkbox" name="scrobble[]" value="{$scrobbles[i].time|escape:'html':'UTF-8'} {$scrobbles[i].artist|escape:'html':'UTF-8'} {$scrobbles[i].track|escape:'html':'UTF-8'}" />
{$scrobbles[i].track|escape:'html':'UTF-8'} by {$scrobbles[i].artist|escape:'html':'UTF-8'}
{if $scrobbles[i].albumurl} on the album, {$scrobbles[i].album|escape:'html':'UTF-8'}{/if}
&mdash; {$scrobbles[i].timehuman}
</label><br />
<input type='submit' value='{t}Delete{/t}' />
<input name='submit' value='1' type='hidden' />
<input name='offset' value='{$scrobbleOffset}' type='hidden' />
<input name='count' value='{$scrobbleCount}' type='hidden' />
<p>{t}Select the checkboxes of the plays that you want to delete then click the Delete button.{/t}</p>
<p>{t}Once you delete a play, it's gone permanently. We cannot recover deleted plays for you. So pleas be careful!{/t}</p>
{include file='footer.tpl'}
{include file='header.tpl' subheader='user-header.tpl'}
<center><h3>Edit your profile | <a href='{$base_url}/user-connections.php'>Connections to other services</a></h3></center>
<center><h3>{t}Edit your profile{/t} | <a href='{$base_url}/user-connections.php'>{t}Connections to other services{/t}</a> | <a href='{$base_url}/user-delete-tracks.php'>{t}Delete plays{/t}</a></h3></center>
{if isset($errors)}
<div id="errors">
/* GNU FM -- a free network service for sharing your music listening habits
Copyright (C) 2009,2014 Free Software Foundation, Inc
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <>.
if ($logged_in == false) {
displayError("Error", "Not logged in. You shouldn't be here.");
// For some bizarre reason $this_user->getScrobbles() fails,
// so make a new user object to use instead until this is fixed.
$user = new User($this_user->name);
$errors = array();
// The user submitted zero or more scrobbles to delete. Delete them
if ($_POST['submit']) {
$deletions = $_POST['scrobble'];
array_map(function($scrob) {
global $user, $errors;
// html_entity_decode defaults to utf8
list($timestamp,$artist,$track) = array_map('html_entity_decode',
explode("\t", $scrob));
// The user id (and SQL ? string in the function's query) mean that
// you can't delete other users' scrobbles or inject SQL.
$ok = Library::removeScrobble($user->uniqueid, $timestamp, $artist,
if($ok) {
$errors[] = "Deleted " . $track . " by " . $artist . " from "
. human_timestamp($timestamp);
} else {
$errors[] = " Couldn't delete " . $track . " by " . $artist
. " from " . human_timestamp($timestamp);
}, $deletions);
// Whether post or get, we've a UI to render. Get and calculate scrobble paging.
$scrobbleCount = (int)$_REQUEST['count'];
if ($scobbleCount >= 1200) {
$scrobbleCount = 1200;
} else if (!$scrobbleCount) {
$scrobbleCount = 100;
$scrobbleOffset = (int)$_REQUEST['offset'];
$scrobbleOffsetNext = ($scrobbleOffset + $scrobbleCount
> $user->getTotalTracks())
? -1 : $scrobbleOffset + $scrobbleCount;
$scrobbleOffsetPrev = ($scrobbleOffset > 0)
? ($scrobbleOffset - $scrobbleCount) : -1;
// Get the current page of scrobbles
try {
$aUserScrobbles = $user->getScrobbles($scrobbleCount, $scrobbleOffset);
$smarty->assign('scrobbles', $aUserScrobbles);
} catch (Exception $e) {}
// Assign and render
$smarty->assign('geo', Server::getLocationDetails($user->location_uri));
$smarty->assign('me', $user);
$smarty->assign('pagetitle', $user->name . '\'s tracks for deletion');
$smarty->assign('errors', $errors);
$smarty->assign('scrobbleCount', $scrobbleCount);
$smarty->assign('scrobbleOffset', $scrobbleOffset);
$smarty->assign('nextOffset', $scrobbleOffsetNext);
$smarty->assign('prevOffset', $scrobbleOffsetPrev);
$submenu = user_menu($user, 'Delete Tracks');
$smarty->assign('submenu', $submenu);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment