From 6e8a9b34c64ab22abf64e6d926a323f0e2023309 Mon Sep 17 00:00:00 2001 From: Peter Deltchev Date: Sun, 26 Jun 2016 19:20:10 -0700 Subject: [PATCH] #86: Modified a bunch of queries to work in PostgreSQL. --- app/Commands/ParseTrackTagsCommand.php | 2 +- .../Controllers/Api/Web/AlbumsController.php | 6 +- .../Controllers/Api/Web/ArtistsController.php | 9 +- .../Api/Web/PlaylistsController.php | 16 ++- .../Controllers/Api/Web/TracksController.php | 24 +++- app/Models/Track.php | 17 +-- .../2016_06_26_225535_create_users_table.php | 2 +- .../2016_06_27_014855_insert_static_data.php | 116 ++++++++++++++++++ 8 files changed, 170 insertions(+), 22 deletions(-) create mode 100644 database/migrations/2016_06_27_014855_insert_static_data.php diff --git a/app/Commands/ParseTrackTagsCommand.php b/app/Commands/ParseTrackTagsCommand.php index e6428441..6e3c1fe9 100644 --- a/app/Commands/ParseTrackTagsCommand.php +++ b/app/Commands/ParseTrackTagsCommand.php @@ -340,7 +340,7 @@ class ParseTrackTagsCommand extends CommandBase } elseif (isset($tags['creation_date'])) { $releaseDate = $this->parseDateString($tags['creation_date'][0]); } else { - $releaseDate = 0; + $releaseDate = null; } return [ diff --git a/app/Http/Controllers/Api/Web/AlbumsController.php b/app/Http/Controllers/Api/Web/AlbumsController.php index 4d3533a2..cbc42e93 100644 --- a/app/Http/Controllers/Api/Web/AlbumsController.php +++ b/app/Http/Controllers/Api/Web/AlbumsController.php @@ -128,14 +128,16 @@ class AlbumsController extends ApiControllerBase $query = Album::summary() ->with('user', 'user.avatar', 'cover') ->userDetails() - ->orderBy('title', 'asc') // An album with only one track is not really an album. ->where('track_count', '>', 1); $count = $query->count(); $perPage = 40; - $query->skip(($page - 1) * $perPage)->take($perPage); + $query + ->orderBy('title', 'asc') + ->skip(($page - 1) * $perPage) + ->take($perPage); $albums = []; foreach ($query->get() as $album) { diff --git a/app/Http/Controllers/Api/Web/ArtistsController.php b/app/Http/Controllers/Api/Web/ArtistsController.php index 03946b11..7c91c2ec 100644 --- a/app/Http/Controllers/Api/Web/ArtistsController.php +++ b/app/Http/Controllers/Api/Web/ArtistsController.php @@ -213,12 +213,13 @@ class ArtistsController extends ApiControllerBase $page = Input::get('page'); } - $query = User::orderBy('display_name', 'asc') - ->where('track_count', '>', 0); - + $query = User::where('track_count', '>', 0); $count = $query->count(); - $perPage = 40; + // The query results are ordered after they're counted + // due to Postgres's behaviour when combining those two operations. + $query->orderBy('display_name', 'asc'); + $perPage = 40; $query->skip(($page - 1) * $perPage)->take($perPage); $users = []; diff --git a/app/Http/Controllers/Api/Web/PlaylistsController.php b/app/Http/Controllers/Api/Web/PlaylistsController.php index c4164dbd..1451beac 100644 --- a/app/Http/Controllers/Api/Web/PlaylistsController.php +++ b/app/Http/Controllers/Api/Web/PlaylistsController.php @@ -81,11 +81,10 @@ class PlaylistsController extends ApiControllerBase ->where('track_count', '>', 1) ->whereIsPublic(true); - $this->applyFilters($query); - $count = $query->count(); - $perPage = 40; + $this->applyOrdering($query); + $perPage = 40; $query->skip(($page - 1) * $perPage)->take($perPage); $playlists = []; @@ -211,7 +210,16 @@ class PlaylistsController extends ApiControllerBase return Response::json($playlists, 200); } - private function applyFilters($query) + + /** + * This function should not deal with anything other than applying order, + * which is done after the query's total possible results are counted due + * to Postgres not allowing "ORDER BY" to be combined with "COUNT()". + * + * @param $query + * @return mixed + */ + private function applyOrdering($query) { if (Input::has('order')) { $order = \Input::get('order'); diff --git a/app/Http/Controllers/Api/Web/TracksController.php b/app/Http/Controllers/Api/Web/TracksController.php index ccc5e388..d0bfdb5e 100644 --- a/app/Http/Controllers/Api/Web/TracksController.php +++ b/app/Http/Controllers/Api/Web/TracksController.php @@ -156,8 +156,9 @@ class TracksController extends ApiControllerBase } $this->applyFilters($query); - $totalCount = $query->count(); + $this->applyOrdering($query); + $query->take($perPage)->skip($perPage * ($page - 1)); $tracks = []; @@ -205,7 +206,15 @@ class TracksController extends ApiControllerBase return Response::json(Track::mapPrivateTrackShow($track), 200); } - private function applyFilters($query) + /** + * To be run after aggregating the total number of tracks for a given query. + * This is separated from applyFilters() because Postgres doesn't allow + * ORDER BY statements in a COUNT(*) query that returns a single value. + * + * @param $query + * @return mixed + */ + private function applyOrdering($query) { if (Input::has('order')) { $order = \Input::get('order'); @@ -213,6 +222,17 @@ class TracksController extends ApiControllerBase $query->orderBy($parts[0], $parts[1]); } + return $query; + } + + /** + * This should be run before count()'ing a query's results. + * + * @param $query + * @return mixed + */ + private function applyFilters($query) + { if (Input::has('is_vocal')) { $isVocal = \Input::get('is_vocal'); if ($isVocal == 'true') { diff --git a/app/Models/Track.php b/app/Models/Track.php index da9ff545..e08e3a5e 100644 --- a/app/Models/Track.php +++ b/app/Models/Track.php @@ -272,18 +272,18 @@ class Track extends Model implements Searchable, Commentable, Favouritable $query = static ::published() ->listed() - ->join(DB::raw(' - ( SELECT `track_id`, `created_at` - FROM `resource_log_items` - WHERE track_id IS NOT NULL AND log_type = 3 AND `created_at` > now() - INTERVAL 1 DAY - ) AS ranged_plays'), + ->join(DB::raw('( + SELECT "track_id" + FROM "resource_log_items" + WHERE track_id IS NOT NULL AND log_type = 3 AND "created_at" > now() - INTERVAL \'1\' DAY + ) ranged_plays'), 'tracks.id', '=', 'ranged_plays.track_id') - ->groupBy('id') + ->groupBy(['id', 'track_id']) ->orderBy('plays', 'desc') ->take($count); if (!$allowExplicit) { - $query->whereIsExplicit(false); + $query->where('is_explicit', false); } $results = []; @@ -293,7 +293,8 @@ class Track extends Model implements Searchable, Commentable, Favouritable } return $results; - }); + } + ); if (!count($trackIds)) { return []; diff --git a/database/migrations/2016_06_26_225535_create_users_table.php b/database/migrations/2016_06_26_225535_create_users_table.php index 62cf2cfd..b5fb7484 100644 --- a/database/migrations/2016_06_26_225535_create_users_table.php +++ b/database/migrations/2016_06_26_225535_create_users_table.php @@ -23,7 +23,7 @@ class CreateUsersTable extends Migration { $table->string('slug')->unique(); $table->boolean('uses_gravatar')->default(1); $table->boolean('can_see_explicit_content')->default(0); - $table->text('bio', 65535); + $table->text('bio', 65535)->default(''); $table->integer('track_count')->unsigned()->default(0)->index(); $table->integer('comment_count')->unsigned()->default(0); $table->timestamps(); diff --git a/database/migrations/2016_06_27_014855_insert_static_data.php b/database/migrations/2016_06_27_014855_insert_static_data.php new file mode 100644 index 00000000..fc460026 --- /dev/null +++ b/database/migrations/2016_06_27_014855_insert_static_data.php @@ -0,0 +1,116 @@ +. + */ + +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Database\Migrations\Migration; + +class InsertStaticData extends Migration +{ + /** + * Run the migrations. + * + * @return void + */ + public function up() + { + DB::table('licenses')->insert([ + 'id' => 1, + 'title' => 'Personal', + 'description' => 'Only you and Pony.fm are allowed to distribute and broadcast the track.', + 'affiliate_distribution' => 0, + 'open_distribution' => 0, + 'remix' => 0 + ]); + + DB::table('licenses')->insert([ + 'id' => 2, + 'title' => 'Broadcast', + 'description' => 'You, Pony.fm, and its affiliates may distribute and broadcast the track.', + 'affiliate_distribution' => 1, + 'open_distribution' => 0, + 'remix' => 0 + ]); + + DB::table('licenses')->insert([ + 'id' => 3, + 'title' => 'Open', + 'description' => 'Anyone is permitted to broadcast and distribute the song in its original form, with attribution to you.', + 'affiliate_distribution' => 1, + 'open_distribution' => 1, + 'remix' => 0 + ]); + + DB::table('licenses')->insert([ + 'id' => 4, + 'title' => 'Remix', + 'description' => 'Anyone is permitted to broadcast and distribute the song in any form, or create derivative works based on it for any purpose, with attribution to you.', + 'affiliate_distribution' => 1, + 'open_distribution' => 1, + 'remix' => 1 + ]); + + DB::table('track_types')->insert([ + 'id' => 1, + 'title' => 'Original Song', + 'editor_title' => 'an original song' + ]); + + DB::table('track_types')->insert([ + 'id' => 2, + 'title' => 'Official Song Remix', + 'editor_title' => 'a remix of an official song' + ]); + + DB::table('track_types')->insert([ + 'id' => 3, + 'title' => 'Fan Song Remix', + 'editor_title' => 'a remix of a fan song' + ]); + + DB::table('track_types')->insert([ + 'id' => 4, + 'title' => 'Ponified Song', + 'editor_title' => 'a non-pony song, turned pony' + ]); + + DB::table('track_types')->insert([ + 'id' => 5, + 'title' => 'Official Show Audio Remix', + 'editor_title' => 'a remix of official show audio' + ]); + + DB::table('track_types')->insert([ + 'id' => 6, + 'title' => 'Unclassified', + 'editor_title' => 'an unclassified track' + ]); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + DB::table('licenses')->whereIn('id', [1, 2, 3, 4])->delete(); + DB::table('track_types')->whereIn('id', [1, 2, 3, 4, 5, 6])->delete(); + } +}