diff --git a/approot/messages.xml b/approot/messages.xml index 8b4557e9..9d3ad6f4 100644 --- a/approot/messages.xml +++ b/approot/messages.xml @@ -33,6 +33,7 @@ Error occured! Go home Release not found +Playlist not found You are not allowed to perform this operation User not found @@ -125,6 +126,7 @@ Play shuffled Random Recently added +Recently modified Recently played Albums Star @@ -155,6 +157,12 @@ Copyright Disc {1} + + + {1} track + {1} tracks + + Delete playlist? diff --git a/approot/messages_fr.xml b/approot/messages_fr.xml index e3423213..9da6e08a 100644 --- a/approot/messages_fr.xml +++ b/approot/messages_fr.xml @@ -33,6 +33,7 @@ Une erreur est survenue! Retour à l'accueil Cet album n'existe pas +Cette liste de lecture n'existe pas Vous n'avez pas les droits pour effectuer cette opération L'utilisateur n'existe pas @@ -125,6 +126,7 @@ Jouer aléatoirement Aléatoire Ajoutés récemment +Modifiés récemment Joués récemment Albums Ajouter aux favoris @@ -155,6 +157,12 @@ Copyright Disque {1} + + + {1} piste + {1} pistes + + Supprimer la liste de lecture ? diff --git a/approot/messages_it.xml b/approot/messages_it.xml index a7574885..e779790f 100644 --- a/approot/messages_it.xml +++ b/approot/messages_it.xml @@ -33,6 +33,7 @@ C'è stato un errore! Ritorna alla home Album non trovato + Non sei autorizzato ad eseguire questa operazione Utente non trovato @@ -124,6 +125,7 @@ Aggiungi alla coda di riproduzione mischiando Casuali Aggiunti di recente + Riprodotti di recente Album Aggiungi ai preferiti @@ -154,8 +156,15 @@ Copyright Disco {1} + + + + + + + Ricerca... diff --git a/approot/messages_zh.xml b/approot/messages_zh.xml index 9246e707..ac634b2d 100644 --- a/approot/messages_zh.xml +++ b/approot/messages_zh.xml @@ -33,6 +33,7 @@ 发生错误! 返回主页 发布未找到 + 不允许执行此操作 未找到此用户 @@ -125,6 +126,7 @@ 随机播放 随机 最近添加 + 最近播放 专辑 收藏 @@ -155,7 +157,13 @@ 版权所有 唱片 {1} - + + + + + + + 搜索中... diff --git a/approot/tracklist.xml b/approot/tracklist.xml new file mode 100644 index 00000000..093a7884 --- /dev/null +++ b/approot/tracklist.xml @@ -0,0 +1,39 @@ + + + + + + + ${name} + ${track-count} · ${duration} + + ${play-btn class="btn btn-primary"} + + + ${play-shuffled class="dropdown-item"} + ${play-last class="dropdown-item"} + ${download class="dropdown-item"} + ${delete class="dropdown-item"} + + + + ${tracks} + + + + + + + + ${tr:Lms.Explore.TrackLists.del-tracklist-confirm} + + + + + + + + + diff --git a/approot/tracklists.xml b/approot/tracklists.xml index 86560654..7bb0549a 100644 --- a/approot/tracklists.xml +++ b/approot/tracklists.xml @@ -3,51 +3,26 @@ + + + + ${recently-modified class="nav-link"} + + + ${all class="nav-link"} + + + ${tracklists} - - - ${name} - - - ${duration} - - - ${play-btn class="btn btn-sm btn-outline-secondary border-0"} - - ${more-btn data-bs-toggle="dropdown" aria-expanded="false" class="btn btn-sm btn-outline-secondary border-0"} - - ${play-shuffled class="dropdown-item"} - ${play-last class="dropdown-item"} - ${download class="dropdown-item"} - ${delete class="dropdown-item"} - - - - + ${name class="text-decoration-none link-secondary"} - ${elements} + ${elements class="d-grid gap-3"} ${loading-indicator} - - - - - - ${tr:Lms.Explore.TrackLists.del-tracklist-confirm} - - - - - - - - diff --git a/src/libs/services/auth/impl/AuthServiceBase.cpp b/src/libs/services/auth/impl/AuthServiceBase.cpp index 01b87a0a..133ce8f5 100644 --- a/src/libs/services/auth/impl/AuthServiceBase.cpp +++ b/src/libs/services/auth/impl/AuthServiceBase.cpp @@ -45,7 +45,7 @@ namespace Auth LMS_LOG(AUTH, DEBUG) << "Creating user '" << loginName << "', admin = " << (type == UserType::ADMIN); - user = User::create(session, loginName); + user = session.create(loginName); user.modify()->setType(type); } diff --git a/src/libs/services/auth/impl/AuthTokenService.cpp b/src/libs/services/auth/impl/AuthTokenService.cpp index 01ac9c87..7decbc14 100644 --- a/src/libs/services/auth/impl/AuthTokenService.cpp +++ b/src/libs/services/auth/impl/AuthTokenService.cpp @@ -60,7 +60,7 @@ namespace Auth if (!user) throw Exception {"User deleted"}; - Database::AuthToken::pointer authToken {Database::AuthToken::create(session, secretHash, expiry, user)}; + Database::AuthToken::pointer authToken {session.create(secretHash, expiry, user)}; LMS_LOG(UI, DEBUG) << "Created auth token for user '" << user->getLoginName() << "', expiry = " << expiry.toString(); diff --git a/src/libs/services/database/impl/Artist.cpp b/src/libs/services/database/impl/Artist.cpp index 7d904bd8..c267b3c9 100644 --- a/src/libs/services/database/impl/Artist.cpp +++ b/src/libs/services/database/impl/Artist.cpp @@ -40,6 +40,12 @@ _MBID {MBID ? MBID->getAsString() : ""} { } +Artist::pointer +Artist::create(Session& session, const std::string& name, const std::optional& MBID) +{ + return session.getDboSession().add(std::unique_ptr {new Artist {name, MBID}}); +} + std::size_t Artist::getCount(Session& session) { @@ -81,17 +87,6 @@ Artist::exists(Session& session, ArtistId id) return session.getDboSession().query("SELECT 1 FROM artist").where("id = ?").bind(id).resultValue() == 1; } -Artist::pointer -Artist::create(Session& session, const std::string& name, const std::optional& MBID) -{ - session.checkUniqueLocked(); - - Artist::pointer res {session.getDboSession().add(std::make_unique(name, MBID))}; - session.getDboSession().flush(); - - return res; -} - static Wt::Dbo::Query createQuery(Session& session, const Artist::FindParameters& params) @@ -119,13 +114,13 @@ createQuery(Session& session, const Artist::FindParameters& params) for (std::string_view keyword : params.keywords) { clauses.push_back("a.name LIKE ? ESCAPE '" ESCAPE_CHAR_STR "'"); - query.bind("%" + escapeLikeKeyword(keyword) + "%"); + query.bind("%" + Utils::escapeLikeKeyword(keyword) + "%"); } for (std::string_view keyword : params.keywords) { sortClauses.push_back("a.sort_name LIKE ? ESCAPE '" ESCAPE_CHAR_STR "'"); - query.bind("%" + escapeLikeKeyword(keyword) + "%"); + query.bind("%" + Utils::escapeLikeKeyword(keyword) + "%"); } query.where("(" + StringUtils::joinStrings(clauses, " AND ") + ") OR (" + StringUtils::joinStrings(sortClauses, " AND ") + ")"); @@ -193,7 +188,7 @@ Artist::findAllOrphans(Session& session, Range range) session.checkSharedLocked(); auto query {session.getDboSession().query("SELECT DISTINCT a.id FROM artist a WHERE NOT EXISTS(SELECT 1 FROM track t INNER JOIN track_artist_link t_a_l ON t_a_l.artist_id = a.id WHERE t.id = t_a_l.track_id)")}; - return execQuery(query, range); + return Utils::execQuery(query, range); } RangeResults @@ -202,7 +197,7 @@ Artist::find(Session& session, const FindParameters& params) session.checkSharedLocked(); auto query {createQuery(session, params)}; - return execQuery(query, params.range); + return Utils::execQuery(query, params.range); } RangeResults @@ -246,10 +241,11 @@ Artist::findSimilarArtists(EnumSet artistLinkTypes, Range r .bind(getId()) .groupBy("a.id") .orderBy("COUNT(*) DESC, RANDOM()")}; + for (TrackArtistLinkType type : artistLinkTypes) query.bind(type); - return execQuery(query, range); + return Utils::execQuery(query, range); } std::vector> diff --git a/src/libs/services/database/impl/AuthToken.cpp b/src/libs/services/database/impl/AuthToken.cpp index 85058a01..b2702d00 100644 --- a/src/libs/services/database/impl/AuthToken.cpp +++ b/src/libs/services/database/impl/AuthToken.cpp @@ -38,12 +38,7 @@ namespace Database AuthToken::pointer AuthToken::create(Session& session, std::string_view value, const Wt::WDateTime& expiry, ObjectPtr user) { - session.checkUniqueLocked(); - - AuthToken::pointer res {session.getDboSession().add(std::make_unique(value, expiry, user))}; - session.getDboSession().flush(); - - return res; + return session.getDboSession().add(std::unique_ptr {new AuthToken {value, expiry, user}}); } void diff --git a/src/libs/services/database/impl/Cluster.cpp b/src/libs/services/database/impl/Cluster.cpp index 87ec28b1..ed01031a 100644 --- a/src/libs/services/database/impl/Cluster.cpp +++ b/src/libs/services/database/impl/Cluster.cpp @@ -36,6 +36,12 @@ Cluster::Cluster(ObjectPtr type, std::string_view name) { } +Cluster::pointer +Cluster::create(Session& session, ObjectPtr type, std::string_view name) +{ + return session.getDboSession().add(std::unique_ptr {new Cluster {type, name}}); +} + std::size_t Cluster::getCount(Session& session) { @@ -44,24 +50,13 @@ Cluster::getCount(Session& session) return session.getDboSession().query("SELECT COUNT(*) FROM cluster"); } -Cluster::pointer -Cluster::create(Session& session, ObjectPtr type, std::string_view name) -{ - session.checkUniqueLocked(); - - Cluster::pointer res {session.getDboSession().add(std::make_unique(type, name))}; - session.getDboSession().flush(); - - return res; -} - RangeResults Cluster::find(Session& session, Range range) { session.checkSharedLocked(); auto query {session.getDboSession().query("SELECT id FROM cluster")}; - return execQuery(query, range); + return Utils::execQuery(query, range); } RangeResults @@ -70,7 +65,7 @@ Cluster::findOrphans(Session& session, Range range) session.checkSharedLocked(); auto query {session.getDboSession().query("SELECT DISTINCT c.id FROM cluster c WHERE NOT EXISTS(SELECT 1 FROM track_cluster t_c WHERE t_c.cluster_id = c.id)")}; - return execQuery(query, range); + return Utils::execQuery(query, range); } Cluster::pointer @@ -95,7 +90,7 @@ Cluster::getTracks(Range range) const auto query {session()->query("SELECT t.id FROM track t INNER JOIN cluster c ON c.id = t_c.cluster_id INNER JOIN track_cluster t_c ON t_c.track_id = t.id") .where("c.id = ?").bind(getId())}; - return execQuery(query, range); + return Utils::execQuery(query, range); } std::size_t @@ -113,6 +108,12 @@ ClusterType::ClusterType(std::string_view name) { } +ClusterType::pointer +ClusterType::create(Session& session, const std::string& name) +{ + return session.getDboSession().add(std::unique_ptr {new ClusterType {name}}); +} + std::size_t ClusterType::getCount(Session& session) { @@ -132,7 +133,7 @@ ClusterType::findOrphans(Session& session, Range range) " LEFT OUTER JOIN cluster c ON c_t.id = c.cluster_type_id") .where("c.id IS NULL")}; - return execQuery(query, range); + return Utils::execQuery(query, range); } RangeResults @@ -144,7 +145,7 @@ ClusterType::findUsed(Session& session, Range range) "SELECT DISTINCT c_t.id from cluster_type c_t") .join("cluster c ON c_t.id = c.cluster_type_id")}; - return execQuery(query, range); + return Utils::execQuery(query, range); } ClusterType::pointer @@ -170,18 +171,7 @@ ClusterType::find(Session& session, Range range) auto query {session.getDboSession().query("SELECT id from cluster_type")}; - return execQuery(query, range); -} - -ClusterType::pointer -ClusterType::create(Session& session, const std::string& name) -{ - session.checkUniqueLocked(); - - ClusterType::pointer res {session.getDboSession().add(std::make_unique(name))}; - session.getDboSession().flush(); - - return res; + return Utils::execQuery(query, range); } Cluster::pointer diff --git a/src/libs/services/database/impl/Listen.cpp b/src/libs/services/database/impl/Listen.cpp index c9a2cb45..8e37711c 100644 --- a/src/libs/services/database/impl/Listen.cpp +++ b/src/libs/services/database/impl/Listen.cpp @@ -141,6 +141,12 @@ namespace Database , _track {getDboPtr(track)} {} + Listen::pointer + Listen::create(Session& session, ObjectPtr user, ObjectPtr track, Scrobbler scrobbler, const Wt::WDateTime& dateTime) + { + return session.getDboSession().add(std::unique_ptr {new Listen {user, track, scrobbler, dateTime}}); + } + std::size_t Listen::getCount(Session& session) { @@ -172,7 +178,7 @@ namespace Database if (parameters.scrobblingState) query.where("scrobbling_state = ?").bind(*parameters.scrobblingState); - return execQuery(query, parameters.range); + return Utils::execQuery(query, parameters.range); } Listen::pointer @@ -188,17 +194,6 @@ namespace Database .resultValue(); } - Listen::pointer - Listen::create(Session& session, ObjectPtr user, ObjectPtr track, Scrobbler scrobbler, const Wt::WDateTime& dateTime) - { - session.checkUniqueLocked(); - - Listen::pointer res {session.getDboSession().add(std::make_unique(user, track, scrobbler, dateTime))}; - session.getDboSession().flush(); - - return res; - } - RangeResults Listen::getTopArtists(Session& session, UserId userId, @@ -213,7 +208,7 @@ namespace Database .orderBy("COUNT(a.id) DESC") .groupBy("a.id")}; - return execQuery(query, range); + return Utils::execQuery(query, range); } RangeResults @@ -227,7 +222,7 @@ namespace Database .orderBy("COUNT(r.id) DESC") .groupBy("r.id")}; - return execQuery(query, range); + return Utils::execQuery(query, range); } RangeResults @@ -241,7 +236,7 @@ namespace Database .orderBy("COUNT(t.id) DESC") .groupBy("t.id")}; - return execQuery(query, range); + return Utils::execQuery(query, range); } RangeResults @@ -256,7 +251,7 @@ namespace Database .groupBy("a.id").having("l.date_time = MAX(l.date_time)") .orderBy("l.date_time DESC")}; - return execQuery(query, range); + return Utils::execQuery(query, range); } RangeResults @@ -270,7 +265,7 @@ namespace Database .groupBy("r.id").having("l.date_time = MAX(l.date_time)") .orderBy("l.date_time DESC")}; - return execQuery(query, range); + return Utils::execQuery(query, range); } RangeResults @@ -284,7 +279,7 @@ namespace Database .groupBy("t.id").having("l.date_time = MAX(l.date_time)") .orderBy("l.date_time DESC")}; - return execQuery(query, range); + return Utils::execQuery(query, range); } diff --git a/src/libs/services/database/impl/Migration.cpp b/src/libs/services/database/impl/Migration.cpp index a2c9616c..ef897499 100644 --- a/src/libs/services/database/impl/Migration.cpp +++ b/src/libs/services/database/impl/Migration.cpp @@ -576,12 +576,21 @@ CREATE TABLE IF NOT EXISTS "track_artist_link_backup" ( migrateFromV34(Session& session) { // Add scrobbling state - // By default, everythin needs to be sent + // By default, everything needs to be sent session.getDboSession().execute("ALTER TABLE starred_artist ADD scrobbling_state INTEGER NOT NULL DEFAULT(" + std::to_string(static_cast(/*ScrobblingState::PendingAdd*/0)) + ")"); session.getDboSession().execute("ALTER TABLE starred_release ADD scrobbling_state INTEGER NOT NULL DEFAULT(" + std::to_string(static_cast(/*ScrobblingState::PendingAdd*/0)) + ")"); session.getDboSession().execute("ALTER TABLE starred_track ADD scrobbling_state INTEGER NOT NULL DEFAULT(" + std::to_string(static_cast(/*ScrobblingState::PendingAdd*/0)) + ")"); } + static + void + migrateFromV35(Session& session) + { + // Add creattion/last modif date time for tracklists + session.getDboSession().execute("ALTER TABLE tracklist ADD creation_date_time TEXT"); + session.getDboSession().execute("ALTER TABLE tracklist ADD last_modified_date_time TEXT"); + } + void doDbMigration(Session& session) { @@ -623,6 +632,7 @@ CREATE TABLE IF NOT EXISTS "track_artist_link_backup" ( {32, migrateFromV32}, {33, migrateFromV33}, {34, migrateFromV34}, + {35, migrateFromV35}, }; while (1) diff --git a/src/libs/services/database/impl/Migration.hpp b/src/libs/services/database/impl/Migration.hpp index 65b8b284..2e7f2f04 100644 --- a/src/libs/services/database/impl/Migration.hpp +++ b/src/libs/services/database/impl/Migration.hpp @@ -26,7 +26,7 @@ namespace Database class Session; using Version = std::size_t; - static constexpr Version LMS_DATABASE_VERSION {35}; + static constexpr Version LMS_DATABASE_VERSION {36}; class VersionInfo { public: diff --git a/src/libs/services/database/impl/Release.cpp b/src/libs/services/database/impl/Release.cpp index 3ca55456..1b2bf630 100644 --- a/src/libs/services/database/impl/Release.cpp +++ b/src/libs/services/database/impl/Release.cpp @@ -57,7 +57,7 @@ createQuery(Session& session, const Release::FindParameters& params) } for (std::string_view keyword : params.keywords) - query.where("r.name LIKE ? ESCAPE '" ESCAPE_CHAR_STR "'").bind("%" + escapeLikeKeyword(keyword) + "%"); + query.where("r.name LIKE ? ESCAPE '" ESCAPE_CHAR_STR "'").bind("%" + Utils::escapeLikeKeyword(keyword) + "%"); if (params.starringUser.isValid()) { @@ -172,6 +172,12 @@ _MBID {MBID ? MBID->getAsString() : ""} { } +Release::pointer +Release::create(Session& session, const std::string& name, const std::optional& MBID) +{ + return session.getDboSession().add(std::unique_ptr {new Release {name, MBID}}); +} + std::vector Release::find(Session& session, const std::string& name) { @@ -214,17 +220,6 @@ Release::exists(Session& session, ReleaseId id) return session.getDboSession().query("SELECT 1 FROM release").where("id = ?").bind(id).resultValue() == 1; } -Release::pointer -Release::create(Session& session, const std::string& name, const std::optional& MBID) -{ - session.checkSharedLocked(); - - Release::pointer res {session.getDboSession().add(std::make_unique(name, MBID))}; - session.getDboSession().flush(); - - return res; -} - std::size_t Release::getCount(Session& session) { @@ -238,7 +233,7 @@ Release::findOrderedByArtist(Session& session, Range range) { session.checkSharedLocked(); - // TODO merge with execQuery + // TODO merge with find auto query {session.getDboSession().query( "SELECT DISTINCT r.id FROM release r" " INNER JOIN track t ON r.id = t.release_id" @@ -246,7 +241,7 @@ Release::findOrderedByArtist(Session& session, Range range) " INNER JOIN artist a ON t_a_l.artist_id = a.id") .orderBy("a.name COLLATE NOCASE, r.name COLLATE NOCASE")}; - return execQuery(query, range); + return Utils::execQuery(query, range); } RangeResults @@ -255,7 +250,7 @@ Release::findOrphans(Session& session, Range range) session.checkSharedLocked(); auto query {session.getDboSession().query("select r.id from release r LEFT OUTER JOIN Track t ON r.id = t.release_id WHERE t.id IS NULL")}; - return execQuery(query, range); + return Utils::execQuery(query, range); } RangeResults @@ -265,7 +260,7 @@ Release::find(Session& session, const FindParameters& params) auto query {createQuery(session, params)}; - return execQuery(query, params.range); + return Utils::execQuery(query, params.range); } std::optional diff --git a/src/libs/services/database/impl/ScanSettings.cpp b/src/libs/services/database/impl/ScanSettings.cpp index 13005720..45ff9f38 100644 --- a/src/libs/services/database/impl/ScanSettings.cpp +++ b/src/libs/services/database/impl/ScanSettings.cpp @@ -120,7 +120,7 @@ ScanSettings::setClusterTypes(Session& session, const std::set& clu if (!clusterType) { LMS_LOG(DB, INFO) << "Creating cluster type " << clusterTypeName; - clusterType = ClusterType::create(session, clusterTypeName); + clusterType = session.create(clusterTypeName); _clusterTypes.insert(getDboPtr(clusterType)); needRescan = true; diff --git a/src/libs/services/database/impl/StarredArtist.cpp b/src/libs/services/database/impl/StarredArtist.cpp index 1960a66e..ca4b3638 100644 --- a/src/libs/services/database/impl/StarredArtist.cpp +++ b/src/libs/services/database/impl/StarredArtist.cpp @@ -36,6 +36,12 @@ namespace Database { } + StarredArtist::pointer + StarredArtist::create(Session& session, ObjectPtr artist, ObjectPtr user, Scrobbler scrobbler) + { + return session.getDboSession().add(std::unique_ptr {new StarredArtist {artist, user, scrobbler}}); + } + std::size_t StarredArtist::getCount(Session& session) { @@ -61,20 +67,9 @@ namespace Database .resultValue(); } - StarredArtist::pointer - StarredArtist::create(Session& session, ObjectPtr artist, ObjectPtr user, Scrobbler scrobbler) - { - session.checkUniqueLocked(); - - StarredArtist::pointer res {session.getDboSession().add(std::make_unique(artist, user, scrobbler))}; - session.getDboSession().flush(); - - return res; - } - void StarredArtist::setDateTime(const Wt::WDateTime& dateTime) { - _dateTime = normalizeDateTime(dateTime); + _dateTime = Utils::normalizeDateTime(dateTime); } } diff --git a/src/libs/services/database/impl/StarredRelease.cpp b/src/libs/services/database/impl/StarredRelease.cpp index 22b556bf..17f1c598 100644 --- a/src/libs/services/database/impl/StarredRelease.cpp +++ b/src/libs/services/database/impl/StarredRelease.cpp @@ -36,6 +36,12 @@ namespace Database { } + StarredRelease::pointer + StarredRelease::create(Session& session, ObjectPtr release, ObjectPtr user, Scrobbler scrobbler) + { + return session.getDboSession().add(std::unique_ptr{new StarredRelease{release, user, scrobbler}}); + } + std::size_t StarredRelease::getCount(Session& session) { @@ -61,20 +67,9 @@ namespace Database .resultValue(); } - StarredRelease::pointer - StarredRelease::create(Session& session, ObjectPtr release, ObjectPtr user, Scrobbler scrobbler) - { - session.checkUniqueLocked(); - - StarredRelease::pointer res {session.getDboSession().add(std::make_unique(release, user, scrobbler))}; - session.getDboSession().flush(); - - return res; - } - void StarredRelease::setDateTime(const Wt::WDateTime& dateTime) { - _dateTime = normalizeDateTime(dateTime); + _dateTime = Utils::normalizeDateTime(dateTime); } } diff --git a/src/libs/services/database/impl/StarredTrack.cpp b/src/libs/services/database/impl/StarredTrack.cpp index b2ddb486..21158c9a 100644 --- a/src/libs/services/database/impl/StarredTrack.cpp +++ b/src/libs/services/database/impl/StarredTrack.cpp @@ -36,6 +36,12 @@ namespace Database { } + StarredTrack::pointer + StarredTrack::create(Session& session, ObjectPtr track, ObjectPtr user, Scrobbler scrobbler) + { + return session.getDboSession().add(std::unique_ptr {new StarredTrack{track, user, scrobbler}}); + } + std::size_t StarredTrack::getCount(Session& session) { @@ -75,23 +81,12 @@ namespace Database if (params.user.isValid()) query.where("s_t.user_id = ?").bind(params.user); - return execQuery(query, params.range); - } - - StarredTrack::pointer - StarredTrack::create(Session& session, ObjectPtr track, ObjectPtr user, Scrobbler scrobbler) - { - session.checkUniqueLocked(); - - StarredTrack::pointer res {session.getDboSession().add(std::make_unique(track, user, scrobbler))}; - session.getDboSession().flush(); - - return res; + return Utils::execQuery(query, params.range); } void StarredTrack::setDateTime(const Wt::WDateTime& dateTime) { - _dateTime = normalizeDateTime(dateTime); + _dateTime = Utils::normalizeDateTime(dateTime); } } diff --git a/src/libs/services/database/impl/Track.cpp b/src/libs/services/database/impl/Track.cpp index 66cc6d1a..b6f22f7d 100644 --- a/src/libs/services/database/impl/Track.cpp +++ b/src/libs/services/database/impl/Track.cpp @@ -46,7 +46,7 @@ createQuery(Session& session, const Track::FindParameters& params) auto query {session.getDboSession().query("SELECT DISTINCT t.id from track t")}; for (std::string_view keyword : params.keywords) - query.where("t.name LIKE ? ESCAPE '" ESCAPE_CHAR_STR "'").bind("%" + escapeLikeKeyword(keyword) + "%"); + query.where("t.name LIKE ? ESCAPE '" ESCAPE_CHAR_STR "'").bind("%" + Utils::escapeLikeKeyword(keyword) + "%"); if (params.writtenAfter.isValid()) query.where("t.file_last_write > ?").bind(params.writtenAfter); @@ -156,12 +156,7 @@ Track::Track(const std::filesystem::path& p) Track::pointer Track::create(Session& session, const std::filesystem::path& p) { - session.checkUniqueLocked(); - - Track::pointer res {session.getDboSession().add(std::make_unique(p))}; - session.getDboSession().flush(); - - return res; + return session.getDboSession().add(std::unique_ptr {new Track {p}}); } std::size_t @@ -219,7 +214,7 @@ Track::findPaths(Session& session, Range range) // TODO Dbo traits on filesystem auto query {session.getDboSession().query("SELECT id, file_path FROM track")}; - RangeResults queryResults {execQuery(query, range)}; + RangeResults queryResults {Utils::execQuery(query, range)}; RangeResults res; res.range = queryResults.range; @@ -243,7 +238,7 @@ Track::findRecordingMBIDDuplicates(Session& session, Range range) auto query {session.getDboSession().query( "SELECT track.id FROM track WHERE recording_mbid in (SELECT recording_mbid FROM track WHERE recording_mbid <> '' GROUP BY recording_mbid HAVING COUNT (*) > 1)") .orderBy("track.release_id,track.disc_number,track.track_number,track.recording_mbid")}; - return execQuery(query, range); + return Utils::execQuery(query, range); } RangeResults @@ -255,7 +250,7 @@ Track::findWithRecordingMBIDAndMissingFeatures(Session& session, Range range) .where("LENGTH(t.recording_mbid) > 0") .where("NOT EXISTS (SELECT * FROM track_features t_f WHERE t_f.track_id = t.id)")}; - return execQuery(query, range); + return Utils::execQuery(query, range); } std::vector @@ -284,7 +279,7 @@ Track::find(Session& session, const FindParameters& parameters) auto query {createQuery(session, parameters)}; - return execQuery(query, parameters.range); + return Utils::execQuery(query, parameters.range); } RangeResults @@ -297,7 +292,7 @@ Track::findByNameAndReleaseName(Session& session, std::string_view trackName, st .where("t.name = ?").bind(trackName) .where("r.name = ?").bind(releaseName)}; - return execQuery(query, Range {}); + return Utils::execQuery(query, Range {}); } RangeResults @@ -328,7 +323,7 @@ Track::findSimilarTracks(Session& session, const std::vector& tracks, R for (TrackId trackId : tracks) query.bind(trackId); - return execQuery(query, range); + return Utils::execQuery(query, range); } void diff --git a/src/libs/services/database/impl/TrackBookmark.cpp b/src/libs/services/database/impl/TrackBookmark.cpp index 28e169ca..71b09708 100644 --- a/src/libs/services/database/impl/TrackBookmark.cpp +++ b/src/libs/services/database/impl/TrackBookmark.cpp @@ -33,6 +33,12 @@ _track {getDboPtr(track)} { } +TrackBookmark::pointer +TrackBookmark::create(Session& session, ObjectPtr user, ObjectPtr track) +{ + return session.getDboSession().add(std::unique_ptr {new TrackBookmark {user, track}}); +} + std::size_t TrackBookmark::getCount(Session& session) { @@ -41,18 +47,6 @@ TrackBookmark::getCount(Session& session) return session.getDboSession().query("SELECT COUNT(*) FROM track_bookmark"); } - -TrackBookmark::pointer -TrackBookmark::create(Session& session, ObjectPtr user, ObjectPtr track) -{ - session.checkUniqueLocked(); - - TrackBookmark::pointer res {session.getDboSession().add(std::make_unique(user, track))}; - session.getDboSession().flush(); - - return res; -} - RangeResults TrackBookmark::find(Session& session, UserId userId, Range range) { @@ -61,7 +55,7 @@ TrackBookmark::find(Session& session, UserId userId, Range range) auto query {session.getDboSession().query("SELECT id from track_bookmark") .where("user_id = ?").bind(userId)}; - return execQuery(query, range); + return Utils::execQuery(query, range); } TrackBookmark::pointer diff --git a/src/libs/services/database/impl/TrackFeatures.cpp b/src/libs/services/database/impl/TrackFeatures.cpp index 628c10c7..35f92b27 100644 --- a/src/libs/services/database/impl/TrackFeatures.cpp +++ b/src/libs/services/database/impl/TrackFeatures.cpp @@ -36,6 +36,12 @@ _track {getDboPtr(track)} { } +TrackFeatures::pointer +TrackFeatures::create(Session& session, ObjectPtr track, const std::string& jsonEncodedFeatures) +{ + return session.getDboSession().add(std::unique_ptr {new TrackFeatures {track, jsonEncodedFeatures}}); +} + std::size_t TrackFeatures::getCount(Session& session) { @@ -71,18 +77,7 @@ TrackFeatures::find(Session& session, Range range) auto query {session.getDboSession().query("SELECT id from track_features")}; - return execQuery(query, range); -} - -TrackFeatures::pointer -TrackFeatures::create(Session& session, ObjectPtr track, const std::string& jsonEncodedFeatures) -{ - session.checkUniqueLocked(); - - TrackFeatures::pointer res {session.getDboSession().add(std::make_unique(track, jsonEncodedFeatures))}; - session.getDboSession().flush(); - - return res; + return Utils::execQuery(query, range); } FeatureValues diff --git a/src/libs/services/database/impl/TrackList.cpp b/src/libs/services/database/impl/TrackList.cpp index 4f2bb0ba..504e09b9 100644 --- a/src/libs/services/database/impl/TrackList.cpp +++ b/src/libs/services/database/impl/TrackList.cpp @@ -36,23 +36,20 @@ namespace Database { TrackList::TrackList(std::string_view name, TrackListType type, bool isPublic, ObjectPtr user) -: _name {name}, - _type {type}, - _isPublic {isPublic}, - _user {getDboPtr(user)} + : _name {name} +, _type {type} +, _isPublic {isPublic} +, _creationDateTime {Wt::WDateTime::currentDateTime()} +, _lastModifiedDateTime {Wt::WDateTime::currentDateTime()} +, _user {getDboPtr(user)} { + assert(user); } TrackList::pointer TrackList::create(Session& session, std::string_view name, TrackListType type, bool isPublic, ObjectPtr user) { - session.checkUniqueLocked(); - assert(user); - - TrackList::pointer res {session.getDboSession().add( std::make_unique(name, type, isPublic, user) )}; - session.getDboSession().flush(); - - return res; + return session.getDboSession().add(std::unique_ptr {new TrackList {name, type, isPublic, user}}); } std::size_t @@ -112,9 +109,19 @@ TrackList::find(Session& session, const FindParameters& params) query.where(oss.str()); } - query.orderBy("t_l.name COLLATE NOCASE"); + switch (params.sortMethod) + { + case TrackListSortMethod::None: + break; + case TrackListSortMethod::Name: + query.orderBy("t_l.name COLLATE NOCASE"); + break; + case TrackListSortMethod::LastModifiedDesc: + query.orderBy("t_l.last_modified_date_time DESC"); + break; + } - return execQuery(query, params.range); + return Utils::execQuery(query, params.range); } TrackList::pointer @@ -173,7 +180,7 @@ TrackList::getEntryByTrackAndDateTime(ObjectPtr track, const Wt::WDateTim return session()->find() .where("tracklist_id = ?").bind(getId()) .where("track_id = ?").bind(track->getId()) - .where("date_time = ?").bind(normalizeDateTime(dateTime)) + .where("date_time = ?").bind(Utils::normalizeDateTime(dateTime)) .resultValue(); } @@ -596,23 +603,30 @@ TrackList::getTopTracks(const std::vector& clusterIds, std::optional< } TrackListEntry::TrackListEntry(ObjectPtr track, ObjectPtr tracklist, const Wt::WDateTime& dateTime) -: _dateTime {normalizeDateTime(dateTime)} +: _dateTime {Utils::normalizeDateTime(dateTime)} , _track {getDboPtr(track)} , _tracklist {getDboPtr(tracklist)} { + assert(track); + assert(tracklist); } TrackListEntry::pointer TrackListEntry::create(Session& session, ObjectPtr track, ObjectPtr tracklist, const Wt::WDateTime& dateTime) { - session.checkUniqueLocked(); - assert(track); - assert(tracklist); + return session.getDboSession().add(std::unique_ptr( new TrackListEntry {track, tracklist, dateTime})); +} - auto res = session.getDboSession().add(std::make_unique( track, tracklist, dateTime)); - session.getDboSession().flush(); +void +TrackListEntry::onPostCreated() +{ + _tracklist.modify()->setLastModifiedDateTime(Wt::WDateTime::currentDateTime()); +} - return res; +void +TrackListEntry::onPreRemove() +{ + _tracklist.modify()->setLastModifiedDateTime(Wt::WDateTime::currentDateTime()); } TrackListEntry::pointer diff --git a/src/libs/services/database/impl/User.cpp b/src/libs/services/database/impl/User.cpp index 31728e06..f7a4d4c0 100644 --- a/src/libs/services/database/impl/User.cpp +++ b/src/libs/services/database/impl/User.cpp @@ -35,6 +35,12 @@ User::User(std::string_view loginName) { } +User::pointer +User::create(Session& session, std::string_view loginName) +{ + return session.getDboSession().add(std::unique_ptr {new User {loginName}}); +} + std::size_t User::getCount(Session& session) { @@ -53,7 +59,7 @@ User::find(Session& session, const FindParameters& params) if (params.scrobbler) query.where("scrobbler = ?").bind(*params.scrobbler); - return execQuery(query, params.range); + return Utils::execQuery(query, params.range); } User::pointer @@ -64,17 +70,6 @@ User::findDemoUser(Session& session) return session.getDboSession().find().where("type = ?").bind(UserType::DEMO).resultValue(); } -User::pointer -User::create(Session& session, std::string_view loginName) -{ - session.checkUniqueLocked(); - - User::pointer user {session.getDboSession().add(std::make_unique(loginName))}; - session.getDboSession().flush(); - - return user; -} - User::pointer User::find(Session& session, UserId id) { diff --git a/src/libs/services/database/impl/Utils.cpp b/src/libs/services/database/impl/Utils.cpp index e0994090..ceb3af41 100644 --- a/src/libs/services/database/impl/Utils.cpp +++ b/src/libs/services/database/impl/Utils.cpp @@ -21,7 +21,7 @@ #include "utils/String.hpp" -namespace Database +namespace Database::Utils { std::string escapeLikeKeyword(std::string_view keyword) @@ -35,6 +35,5 @@ namespace Database // force second resolution return Wt::WDateTime::fromTime_t(dateTime.toTime_t()); } - -} // namespace Database +} // namespace Database::Utils diff --git a/src/libs/services/database/impl/Utils.hpp b/src/libs/services/database/impl/Utils.hpp index b92b12c3..213bce59 100644 --- a/src/libs/services/database/impl/Utils.hpp +++ b/src/libs/services/database/impl/Utils.hpp @@ -27,7 +27,7 @@ #include "services/database/Types.hpp" -namespace Database +namespace Database::Utils { #define ESCAPE_CHAR_STR "\\" static inline constexpr char escapeChar {'\\'}; @@ -82,5 +82,5 @@ namespace Database } Wt::WDateTime normalizeDateTime(const Wt::WDateTime& dateTime); -} // namespace Database +} // namespace Database::Utils diff --git a/src/libs/services/database/include/services/database/Artist.hpp b/src/libs/services/database/include/services/database/Artist.hpp index 23b153af..04067a9c 100644 --- a/src/libs/services/database/include/services/database/Artist.hpp +++ b/src/libs/services/database/include/services/database/Artist.hpp @@ -72,7 +72,6 @@ class Artist : public Object }; Artist() = default; - Artist(const std::string& name, const std::optional& MBID = {}); // Accessors static std::size_t getCount(Session& session); @@ -101,9 +100,6 @@ class Artist : public Object void setMBID(const std::optional& mbid) { _MBID = mbid ? mbid->getAsString() : ""; } void setSortName(const std::string& sortName); - // Create - static pointer create(Session& session, const std::string& name, const std::optional& UUID = {}); - template void persist(Action& a) { @@ -118,6 +114,11 @@ class Artist : public Object private: static const std::size_t _maxNameLength = 128; + friend class Session; + // Create + Artist(const std::string& name, const std::optional& MBID = {}); + static pointer create(Session& session, const std::string& name, const std::optional& UUID = {}); + std::string _name; std::string _sortName; std::string _MBID; // Musicbrainz Identifier diff --git a/src/libs/services/database/include/services/database/AuthToken.hpp b/src/libs/services/database/include/services/database/AuthToken.hpp index 646a5d9f..6d784ef2 100644 --- a/src/libs/services/database/include/services/database/AuthToken.hpp +++ b/src/libs/services/database/include/services/database/AuthToken.hpp @@ -36,10 +36,8 @@ namespace Database { public: AuthToken() = default; - AuthToken(std::string_view value, const Wt::WDateTime& expiry, ObjectPtr user); // Utility - static pointer create(Session& session, std::string_view value, const Wt::WDateTime&expiry, ObjectPtr user); static void removeExpiredTokens(Session& session, const Wt::WDateTime& now); static pointer find(Session& session, std::string_view value); @@ -57,6 +55,10 @@ namespace Database } private: + friend class Session; + AuthToken(std::string_view value, const Wt::WDateTime& expiry, ObjectPtr user); + static pointer create(Session& session, std::string_view value, const Wt::WDateTime&expiry, ObjectPtr user); + std::string _value; Wt::WDateTime _expiry; Wt::Dbo::ptr _user; diff --git a/src/libs/services/database/include/services/database/Cluster.hpp b/src/libs/services/database/include/services/database/Cluster.hpp index a1cac3f7..72c05883 100644 --- a/src/libs/services/database/include/services/database/Cluster.hpp +++ b/src/libs/services/database/include/services/database/Cluster.hpp @@ -42,7 +42,6 @@ class Cluster : public Object { public: Cluster() = default; - Cluster(ObjectPtr type, std::string_view name); // Find utility static std::size_t getCount(Session& session); @@ -50,9 +49,6 @@ class Cluster : public Object static pointer find(Session& session, ClusterId id); static RangeResults findOrphans(Session& session, Range range); - // Create utility - static pointer create(Session& session, ObjectPtr type, std::string_view name); - // Accessors const std::string& getName() const { return _name; } ObjectPtr getType() const { return _clusterType; } @@ -72,6 +68,10 @@ class Cluster : public Object } private: + friend class Session; + Cluster(ObjectPtr type, std::string_view name); + static pointer create(Session& session, ObjectPtr type, std::string_view name); + static const std::size_t _maxNameLength = 128; std::string _name; @@ -85,7 +85,6 @@ class ClusterType : public Object { public: ClusterType() = default; - ClusterType(std::string_view name); // Getters static std::size_t getCount(Session& session); @@ -95,7 +94,6 @@ class ClusterType : public Object static RangeResults findOrphans(Session& session, Range range); static RangeResults findUsed(Session& session, Range range); - static pointer create(Session& session, const std::string& name); static void remove(Session& session, const std::string& name); // Accessors @@ -112,6 +110,10 @@ class ClusterType : public Object } private: + friend class Session; + ClusterType(std::string_view name); + static pointer create(Session& session, const std::string& name); + static const std::size_t _maxNameLength = 128; std::string _name; diff --git a/src/libs/services/database/include/services/database/Listen.hpp b/src/libs/services/database/include/services/database/Listen.hpp index edbb218b..1c981b65 100644 --- a/src/libs/services/database/include/services/database/Listen.hpp +++ b/src/libs/services/database/include/services/database/Listen.hpp @@ -42,7 +42,6 @@ class Listen : public Object { public: Listen() = default; - Listen(ObjectPtr user, ObjectPtr track, Scrobbler scrobbler, const Wt::WDateTime& dateTime); struct FindParameters { @@ -63,9 +62,6 @@ class Listen : public Object static pointer find(Session& session, UserId userId, TrackId trackId, Scrobbler scrobbler, const Wt::WDateTime& dateTime); static RangeResults find(Session& session, const FindParameters& parameters); - // Create - static pointer create(Session& session, ObjectPtr user, ObjectPtr track, Scrobbler scrobbler, const Wt::WDateTime& dateTime); - // Stats static RangeResults getTopArtists(Session& session, UserId userId, @@ -120,6 +116,10 @@ class Listen : public Object } private: + friend class Session; + Listen(ObjectPtr user, ObjectPtr track, Scrobbler scrobbler, const Wt::WDateTime& dateTime); + static pointer create(Session& session, ObjectPtr user, ObjectPtr track, Scrobbler scrobbler, const Wt::WDateTime& dateTime); + Wt::WDateTime _dateTime; Scrobbler _scrobbler; ScrobblingState _scrobblingState {ScrobblingState::PendingAdd}; diff --git a/src/libs/services/database/include/services/database/Object.hpp b/src/libs/services/database/include/services/database/Object.hpp index 79ccf4be..e4ea5342 100644 --- a/src/libs/services/database/include/services/database/Object.hpp +++ b/src/libs/services/database/include/services/database/Object.hpp @@ -19,6 +19,7 @@ #pragma once +#include #include #include "services/database/IdType.hpp" @@ -38,7 +39,11 @@ namespace Database bool operator!=(const ObjectPtr& other) const { return other._obj != _obj; } auto modify() { return _obj.modify(); } - void remove() { _obj.remove(); } + void remove() + { + _obj.modify()->onPreRemove(); + _obj.remove(); + } private: template friend class Object; @@ -61,6 +66,10 @@ namespace Database typename Wt::Dbo::dbo_traits::IdType id() const = delete; protected: + template friend class ObjectPtr; + virtual void onPostCreated() {} + virtual void onPreRemove() {} + // Can get raw dbo ptr only from Objects template static diff --git a/src/libs/services/database/include/services/database/Release.hpp b/src/libs/services/database/include/services/database/Release.hpp index 656dc69e..0bf62e43 100644 --- a/src/libs/services/database/include/services/database/Release.hpp +++ b/src/libs/services/database/include/services/database/Release.hpp @@ -79,7 +79,6 @@ class Release : public Object }; Release() = default; - Release(const std::string& name, const std::optional& MBID = {}); // Accessors static std::size_t getCount(Session& session); @@ -98,9 +97,6 @@ class Release : public Object // size is the max number of cluster per cluster type std::vector>> getClusterGroups(const std::vector>& clusterTypes, std::size_t size) const; - // Create - static pointer create(Session& session, const std::string& name, const std::optional& MBID = {}); - // Utility functions std::optional getReleaseYear(bool originalDate = false) const; std::optional getCopyright() const; @@ -133,6 +129,10 @@ class Release : public Object } private: + friend class Session; + Release(const std::string& name, const std::optional& MBID = {}); + static pointer create(Session& session, const std::string& name, const std::optional& MBID = {}); + static const std::size_t _maxNameLength {128}; std::string _name; diff --git a/src/libs/services/database/include/services/database/ScanSettings.hpp b/src/libs/services/database/include/services/database/ScanSettings.hpp index 19def107..e51a6cc0 100644 --- a/src/libs/services/database/include/services/database/ScanSettings.hpp +++ b/src/libs/services/database/include/services/database/ScanSettings.hpp @@ -39,7 +39,8 @@ class ScanSettings : public Object { public: // Do not modify values (just add) - enum class UpdatePeriod { + enum class UpdatePeriod + { Never = 0, Daily, Weekly, diff --git a/src/libs/services/database/include/services/database/Session.hpp b/src/libs/services/database/include/services/database/Session.hpp index 1aab2d66..0766404f 100644 --- a/src/libs/services/database/include/services/database/Session.hpp +++ b/src/libs/services/database/include/services/database/Session.hpp @@ -19,16 +19,15 @@ #pragma once -#include - #include #include #include "utils/RecursiveSharedMutex.hpp" +#include "services/database/Object.hpp" + namespace Database { - class UniqueTransaction { private: @@ -73,11 +72,22 @@ namespace Database Wt::Dbo::Session& getDboSession() { return _session; } Db& getDb() { return _db; } + template + typename Object::pointer create(Args&&... args) + { + checkUniqueLocked(); + + typename Object::pointer res {Object::create(*this, std::forward(args)...)}; + getDboSession().flush(); + + res.modify()->onPostCreated(); + return res; + } + private: Db& _db; Wt::Dbo::Session _session; }; - } // namespace Database diff --git a/src/libs/services/database/include/services/database/StarredArtist.hpp b/src/libs/services/database/include/services/database/StarredArtist.hpp index 7c731578..3d7a0d18 100644 --- a/src/libs/services/database/include/services/database/StarredArtist.hpp +++ b/src/libs/services/database/include/services/database/StarredArtist.hpp @@ -38,16 +38,12 @@ namespace Database { public: StarredArtist() = default; - StarredArtist(ObjectPtr artist, ObjectPtr user, Scrobbler scrobbler); // Search utility static std::size_t getCount(Session& session); static pointer find(Session& session, StarredArtistId id); static pointer find(Session& session, ArtistId artistId, UserId userId, Scrobbler scrobbler); - // Create utility - static pointer create(Session& session, ObjectPtr artist, ObjectPtr user, Scrobbler scrobbler); - // Accessors ObjectPtr getArtist() const { return _artist; } ObjectPtr getUser() const { return _user; } @@ -71,6 +67,10 @@ namespace Database } private: + friend class Session; + StarredArtist(ObjectPtr artist, ObjectPtr user, Scrobbler scrobbler); + static pointer create(Session& session, ObjectPtr artist, ObjectPtr user, Scrobbler scrobbler); + Scrobbler _scrobbler; // for which scrobbler ScrobblingState _scrobblingState {ScrobblingState::PendingAdd}; Wt::WDateTime _dateTime; // when it was starred diff --git a/src/libs/services/database/include/services/database/StarredRelease.hpp b/src/libs/services/database/include/services/database/StarredRelease.hpp index c79ce4b2..b53c1850 100644 --- a/src/libs/services/database/include/services/database/StarredRelease.hpp +++ b/src/libs/services/database/include/services/database/StarredRelease.hpp @@ -38,16 +38,12 @@ namespace Database { public: StarredRelease() = default; - StarredRelease(ObjectPtr release, ObjectPtr user, Scrobbler scrobbler); // Search utility static std::size_t getCount(Session& session); static pointer find(Session& session, StarredReleaseId id); static pointer find(Session& session, ReleaseId releaseId, UserId userId, Scrobbler scrobbler); - // Create utility - static pointer create(Session& session, ObjectPtr release, ObjectPtr user, Scrobbler scrobbler); - // Accessors ObjectPtr getRelease() const { return _release; } ObjectPtr getUser() const { return _user; } @@ -71,6 +67,10 @@ namespace Database } private: + friend class Session; + StarredRelease(ObjectPtr release, ObjectPtr user, Scrobbler scrobbler); + static pointer create(Session& session, ObjectPtr release, ObjectPtr user, Scrobbler scrobbler); + Scrobbler _scrobbler; // for which scrobbler ScrobblingState _scrobblingState {ScrobblingState::PendingAdd}; Wt::WDateTime _dateTime; // when it was starred diff --git a/src/libs/services/database/include/services/database/StarredTrack.hpp b/src/libs/services/database/include/services/database/StarredTrack.hpp index 1332e1ae..376fd00d 100644 --- a/src/libs/services/database/include/services/database/StarredTrack.hpp +++ b/src/libs/services/database/include/services/database/StarredTrack.hpp @@ -39,7 +39,6 @@ namespace Database { public: StarredTrack() = default; - StarredTrack(ObjectPtr track, ObjectPtr user, Scrobbler scrobbler); struct FindParameters { @@ -59,9 +58,6 @@ namespace Database static pointer find(Session& session, TrackId trackId, UserId userId, Scrobbler scrobbler); static RangeResults find(Session& session, const FindParameters& findParams); - // Create utility - static pointer create(Session& session, ObjectPtr track, ObjectPtr user, Scrobbler scrobbler); - // Accessors ObjectPtr getTrack() const { return _track; } ObjectPtr getUser() const { return _user; } @@ -85,6 +81,10 @@ namespace Database } private: + friend class Session; + StarredTrack(ObjectPtr track, ObjectPtr user, Scrobbler scrobbler); + static pointer create(Session& session, ObjectPtr track, ObjectPtr user, Scrobbler scrobbler); + Scrobbler _scrobbler; // for which scrobbler ScrobblingState _scrobblingState {ScrobblingState::PendingAdd}; Wt::WDateTime _dateTime; // when it was starred diff --git a/src/libs/services/database/include/services/database/Track.hpp b/src/libs/services/database/include/services/database/Track.hpp index 3cc10e7c..f47d903b 100644 --- a/src/libs/services/database/include/services/database/Track.hpp +++ b/src/libs/services/database/include/services/database/Track.hpp @@ -91,7 +91,6 @@ class Track : public Object }; Track() = default; - Track(const std::filesystem::path& p); // Find utility functions static std::size_t getCount(Session& session); @@ -107,9 +106,6 @@ class Track : public Object static RangeResults findRecordingMBIDDuplicates(Session& session, Range range); static RangeResults findWithRecordingMBIDAndMissingFeatures(Session& session, Range range); - // Create utility - static pointer create(Session& session, const std::filesystem::path& p); - // Accessors void setScanVersion(std::size_t version) { _scanVersion = version; } void setTrackNumber(int num) { _trackNumber = num; } @@ -196,6 +192,10 @@ class Track : public Object } private: + friend class ::Database::Session; + Track(const std::filesystem::path& p); + static pointer create(Session& session, const std::filesystem::path& p); + static const std::size_t _maxNameLength = 128; static const std::size_t _maxCopyrightLength = 128; static const std::size_t _maxCopyrightURLLength = 128; diff --git a/src/libs/services/database/include/services/database/TrackBookmark.hpp b/src/libs/services/database/include/services/database/TrackBookmark.hpp index d1d31768..dee9b0fa 100644 --- a/src/libs/services/database/include/services/database/TrackBookmark.hpp +++ b/src/libs/services/database/include/services/database/TrackBookmark.hpp @@ -41,10 +41,6 @@ class TrackBookmark : public Object { public: TrackBookmark () = default; - TrackBookmark(ObjectPtr user, ObjectPtr track); - - // utility - static pointer create(Session& session, ObjectPtr user, ObjectPtr track); // Find utility functions static std::size_t getCount(Session& session); @@ -70,7 +66,12 @@ class TrackBookmark : public Object Wt::Dbo::belongsTo(a, _track, "track", Wt::Dbo::OnDeleteCascade); Wt::Dbo::belongsTo(a, _user, "user", Wt::Dbo::OnDeleteCascade); } + private: + friend class Session; + TrackBookmark(ObjectPtr user, ObjectPtr track); + static pointer create(Session& session, ObjectPtr user, ObjectPtr track); + static const std::size_t _maxCommentLength = 128; std::chrono::duration _offset; diff --git a/src/libs/services/database/include/services/database/TrackFeatures.hpp b/src/libs/services/database/include/services/database/TrackFeatures.hpp index 1c1251fa..b294fc72 100644 --- a/src/libs/services/database/include/services/database/TrackFeatures.hpp +++ b/src/libs/services/database/include/services/database/TrackFeatures.hpp @@ -46,7 +46,6 @@ class TrackFeatures : public Object { public: TrackFeatures() = default; - TrackFeatures(ObjectPtr track, const std::string& jsonEncodedFeatures); // Find utilities static std::size_t getCount(Session& session); @@ -54,9 +53,6 @@ class TrackFeatures : public Object static pointer find(Session& session, TrackId trackId); static RangeResults find(Session& session, Range range); - // Create utility - static pointer create(Session& session, ObjectPtr track, const std::string& jsonEncodedFeatures); - FeatureValues getFeatureValues(const FeatureName& feature) const; FeatureValuesMap getFeatureValuesMap(const std::unordered_set& featureNames) const; @@ -71,6 +67,10 @@ class TrackFeatures : public Object } private: + friend class Session; + TrackFeatures(ObjectPtr track, const std::string& jsonEncodedFeatures); + static pointer create(Session& session, ObjectPtr track, const std::string& jsonEncodedFeatures); + std::string _data; Wt::Dbo::ptr _track; }; diff --git a/src/libs/services/database/include/services/database/TrackList.hpp b/src/libs/services/database/include/services/database/TrackList.hpp index c23ef926..5eeb7d94 100644 --- a/src/libs/services/database/include/services/database/TrackList.hpp +++ b/src/libs/services/database/include/services/database/TrackList.hpp @@ -48,7 +48,6 @@ class TrackList : public Object { public: TrackList() = default; - TrackList(std::string_view name, TrackListType type, bool isPublic, ObjectPtr user); // Stats utility std::vector> getTopArtists(const std::vector& clusterIds, std::optional linkType, std::optional range, bool& moreResults) const; @@ -62,20 +61,19 @@ class TrackList : public Object Range range; std::optional type; UserId user; // only tracklists owned by this user + TrackListSortMethod sortMethod {TrackListSortMethod::None}; FindParameters& setClusters(const std::vector& _clusters) { clusters = _clusters; return *this; } FindParameters& setRange(Range _range) { range = _range; return *this; } FindParameters& setType(TrackListType _type) { type = _type; return *this; } FindParameters& setUser(UserId _user) { user = _user; return *this; } + FindParameters& setSortMethod(TrackListSortMethod _sortMethod) {sortMethod = _sortMethod; return *this; } }; static std::size_t getCount(Session& session); static pointer find(Session& session, std::string_view name, TrackListType type, UserId userId); static pointer find(Session& session, TrackListId tracklistId); static RangeResults find(Session& session, const FindParameters& params); - // Create utility - static pointer create(Session& session, std::string_view name, TrackListType type, bool isPublic, ObjectPtr user); - // Accessors std::string_view getName() const { return _name; } bool isPublic() const { return _isPublic; } @@ -86,6 +84,7 @@ class TrackList : public Object void setName(const std::string& name) { _name = name; } void setIsPublic(bool isPublic) { _isPublic = isPublic; } void clear() { _entries.clear(); } + void setLastModifiedDateTime(const Wt::WDateTime& dateTime) { _lastModifiedDateTime = dateTime; } // Get tracks, ordered by position bool isEmpty() const; @@ -117,18 +116,26 @@ class TrackList : public Object template