From 32fb22c039ff5edc99c20063bcacf5b8e622171c Mon Sep 17 00:00:00 2001 From: Michael Mayer Date: Tue, 23 Nov 2021 20:25:32 +0100 Subject: [PATCH] Months, Countries & States: Update album title and slug if needed #1664 --- internal/entity/album.go | 66 +++++++++++++++++++-- internal/entity/album_test.go | 32 +++++++++- internal/migrate/dialect_mysql.go | 2 +- internal/migrate/dialect_sqlite.go | 2 +- internal/migrate/mysql/20211121-094727.sql | 2 +- internal/migrate/sqlite/20211121-094727.sql | 2 +- internal/photoprism/moments.go | 20 ++++--- 7 files changed, 108 insertions(+), 18 deletions(-) diff --git a/internal/entity/album.go b/internal/entity/album.go index c666b087b..a0cfd0adc 100644 --- a/internal/entity/album.go +++ b/internal/entity/album.go @@ -177,6 +177,9 @@ func NewMomentsAlbum(albumTitle, albumSlug, albumFilter string) *Album { // NewStateAlbum creates a new moment. func NewStateAlbum(albumTitle, albumSlug, albumFilter string) *Album { + albumTitle = strings.TrimSpace(albumTitle) + albumSlug = strings.TrimSpace(albumSlug) + if albumTitle == "" || albumSlug == "" || albumFilter == "" { return nil } @@ -198,6 +201,9 @@ func NewStateAlbum(albumTitle, albumSlug, albumFilter string) *Album { // NewMonthAlbum creates a new month album. func NewMonthAlbum(albumTitle, albumSlug string, year, month int) *Album { + albumTitle = strings.TrimSpace(albumTitle) + albumSlug = strings.TrimSpace(albumSlug) + if albumTitle == "" || albumSlug == "" || year == 0 || month == 0 { return nil } @@ -225,6 +231,17 @@ func NewMonthAlbum(albumTitle, albumSlug string, year, month int) *Album { return result } +// FindMonthAlbum finds a matching month album or returns nil. +func FindMonthAlbum(year, month int) *Album { + result := Album{} + + if err := UnscopedDb().Where("album_year = ? AND album_month = ? AND album_type = ?", year, month, AlbumMonth).First(&result).Error; err != nil { + return nil + } + + return &result +} + // FindAlbumBySlug finds a matching album or returns nil. func FindAlbumBySlug(albumSlug, albumType string) *Album { result := Album{} @@ -236,6 +253,17 @@ func FindAlbumBySlug(albumSlug, albumType string) *Album { return &result } +// FindAlbumByFilter finds a matching album or returns nil. +func FindAlbumByFilter(albumFilter, albumType string) *Album { + result := Album{} + + if err := UnscopedDb().Where("album_filter = ? AND album_type = ?", albumFilter, albumType).First(&result).Error; err != nil { + return nil + } + + return &result +} + // FindFolderAlbum finds a matching folder album or returns nil. func FindFolderAlbum(albumPath string) *Album { albumPath = strings.Trim(albumPath, string(os.PathSeparator)) @@ -333,9 +361,34 @@ func (m *Album) SetTitle(title string) { } } +// UpdateSlug updates title and slug of generated albums if needed. +func (m *Album) UpdateSlug(title, slug string) error { + title = strings.TrimSpace(title) + slug = strings.TrimSpace(slug) + + if title == "" || slug == "" { + return nil + } + + changed := false + + if m.AlbumSlug != slug { + m.AlbumSlug = slug + changed = true + } + + if !changed { + return nil + } + + m.AlbumTitle = title + + return m.Updates(Values{"album_title": m.AlbumTitle, "album_slug": m.AlbumSlug}) +} + // UpdateState updates the album location. -func (m *Album) UpdateState(stateName, countryCode string) error { - if stateName == "" || countryCode == "" { +func (m *Album) UpdateState(title, slug, stateName, countryCode string) error { + if title == "" || slug == "" || stateName == "" || countryCode == "" { return nil } @@ -357,13 +410,18 @@ func (m *Album) UpdateState(stateName, countryCode string) error { changed = true } + if m.AlbumSlug != slug { + m.AlbumSlug = slug + changed = true + } + if !changed { return nil } - m.AlbumTitle = stateName + m.AlbumTitle = title - return m.Updates(Values{"album_title": m.AlbumTitle, "album_location": m.AlbumLocation, "album_country": m.AlbumCountry, "album_state": m.AlbumState}) + return m.Updates(Values{"album_title": m.AlbumTitle, "album_slug": m.AlbumSlug, "album_location": m.AlbumLocation, "album_country": m.AlbumCountry, "album_state": m.AlbumState}) } // SaveForm updates the entity using form data and stores it in the database. diff --git a/internal/entity/album_test.go b/internal/entity/album_test.go index 725b53c31..3c01624b7 100644 --- a/internal/entity/album_test.go +++ b/internal/entity/album_test.go @@ -69,6 +69,36 @@ is an oblate spheroid.` }) } +func TestAlbum_UpdateSlug(t *testing.T) { + t.Run("success", func(t *testing.T) { + album := NewMonthAlbum("Foo ", "foo", 2002, 11) + + assert.Equal(t, "Foo", album.AlbumTitle) + assert.Equal(t, "foo", album.AlbumSlug) + assert.Equal(t, "", album.AlbumDescription) + assert.Equal(t, 2002, album.AlbumYear) + assert.Equal(t, 11, album.AlbumMonth) + + if err := album.Create(); err != nil { + t.Fatal(err) + } + + if err := album.UpdateSlug("November / 2002", "november-2002"); err != nil { + t.Fatal(err) + } + + assert.Equal(t, "November / 2002", album.AlbumTitle) + assert.Equal(t, "november-2002", album.AlbumSlug) + assert.Equal(t, "", album.AlbumDescription) + assert.Equal(t, 2002, album.AlbumYear) + assert.Equal(t, 11, album.AlbumMonth) + + if err := album.DeletePermanently(); err != nil { + t.Fatal(err) + } + }) +} + func TestAlbum_UpdateState(t *testing.T) { t.Run("success", func(t *testing.T) { album := NewAlbum("Any State", AlbumState) @@ -80,7 +110,7 @@ func TestAlbum_UpdateState(t *testing.T) { t.Fatal(err) } - if err := album.UpdateState("Alberta", "ca"); err != nil { + if err := album.UpdateState("Alberta", "canada-alberta", "Alberta", "ca"); err != nil { t.Fatal(err) } diff --git a/internal/migrate/dialect_mysql.go b/internal/migrate/dialect_mysql.go index 941c61d16..08551606f 100644 --- a/internal/migrate/dialect_mysql.go +++ b/internal/migrate/dialect_mysql.go @@ -5,6 +5,6 @@ var DialectMySQL = Migrations{ { ID: "20211121-094727", Dialect: "mysql", - Query: "DROP INDEX IF EXISTS uix_places_place_label ON `places`;", + Query: "DROP INDEX IF EXISTS uix_places_place_label ON `places`", }, } diff --git a/internal/migrate/dialect_sqlite.go b/internal/migrate/dialect_sqlite.go index 931b3e150..c6ed985a7 100644 --- a/internal/migrate/dialect_sqlite.go +++ b/internal/migrate/dialect_sqlite.go @@ -5,6 +5,6 @@ var DialectSQLite = Migrations{ { ID: "20211121-094727", Dialect: "sqlite", - Query: "DROP INDEX IF EXISTS idx_places_place_label;", + Query: "DROP INDEX IF EXISTS idx_places_place_label", }, } diff --git a/internal/migrate/mysql/20211121-094727.sql b/internal/migrate/mysql/20211121-094727.sql index 832c87417..5ac866d8d 100644 --- a/internal/migrate/mysql/20211121-094727.sql +++ b/internal/migrate/mysql/20211121-094727.sql @@ -1 +1 @@ -DROP INDEX IF EXISTS uix_places_place_label ON `places`; \ No newline at end of file +DROP INDEX IF EXISTS uix_places_place_label ON `places` \ No newline at end of file diff --git a/internal/migrate/sqlite/20211121-094727.sql b/internal/migrate/sqlite/20211121-094727.sql index b9c22e36b..bd4204d36 100644 --- a/internal/migrate/sqlite/20211121-094727.sql +++ b/internal/migrate/sqlite/20211121-094727.sql @@ -1 +1 @@ -DROP INDEX IF EXISTS idx_places_place_label; \ No newline at end of file +DROP INDEX IF EXISTS idx_places_place_label \ No newline at end of file diff --git a/internal/photoprism/moments.go b/internal/photoprism/moments.go index a89cc3d1d..d0f94f1ad 100644 --- a/internal/photoprism/moments.go +++ b/internal/photoprism/moments.go @@ -112,9 +112,11 @@ func (w *Moments) Start() (err error) { log.Errorf("moments: %s", err.Error()) } else { for _, mom := range results { - w.MigrateSlug(mom, entity.AlbumMonth) + if a := entity.FindMonthAlbum(mom.Year, mom.Month); a != nil { + if err := a.UpdateSlug(mom.Title(), mom.Slug()); err != nil { + log.Errorf("moments: %s (update slug)", err.Error()) + } - if a := entity.FindAlbumBySlug(mom.Slug(), entity.AlbumMonth); a != nil { if !a.Deleted() { log.Tracef("moments: %s already exists (%s)", txt.Quote(a.AlbumTitle), a.AlbumFilter) } else if err := a.Restore(); err != nil { @@ -137,15 +139,17 @@ func (w *Moments) Start() (err error) { log.Errorf("moments: %s", err.Error()) } else { for _, mom := range results { - w.MigrateSlug(mom, entity.AlbumMoment) - f := form.PhotoSearch{ Country: mom.Country, Year: strconv.Itoa(mom.Year), Public: true, } - if a := entity.FindAlbumBySlug(mom.Slug(), entity.AlbumMoment); a != nil { + if a := entity.FindAlbumByFilter(f.Serialize(), entity.AlbumMoment); a != nil { + if err := a.UpdateSlug(mom.Title(), mom.Slug()); err != nil { + log.Errorf("moments: %s (update slug)", err.Error()) + } + if a.DeletedAt != nil { // Nothing to do. log.Tracef("moments: %s was deleted (%s)", txt.Quote(a.AlbumTitle), a.AlbumFilter) @@ -170,16 +174,14 @@ func (w *Moments) Start() (err error) { log.Errorf("moments: %s", err.Error()) } else { for _, mom := range results { - w.MigrateSlug(mom, entity.AlbumState) - f := form.PhotoSearch{ Country: mom.Country, State: mom.State, Public: true, } - if a := entity.FindAlbumBySlug(mom.Slug(), entity.AlbumState); a != nil { - if err := a.UpdateState(mom.State, mom.Country); err != nil { + if a := entity.FindAlbumByFilter(f.Serialize(), entity.AlbumState); a != nil { + if err := a.UpdateState(mom.Title(), mom.Slug(), mom.State, mom.Country); err != nil { log.Errorf("moments: %s (update state)", err.Error()) }