2021-02-20 14:03:54 +00:00
package shroom
2021-02-17 18:41:35 +00:00
import (
"errors"
"fmt"
2021-12-20 21:08:21 +00:00
"github.com/bouncepaw/mycorrhiza/hyphae/backlinks"
2021-02-17 18:41:35 +00:00
"regexp"
"github.com/bouncepaw/mycorrhiza/history"
2021-02-20 14:03:54 +00:00
"github.com/bouncepaw/mycorrhiza/hyphae"
2021-10-10 03:51:34 +00:00
"github.com/bouncepaw/mycorrhiza/l18n"
2021-02-17 18:41:35 +00:00
"github.com/bouncepaw/mycorrhiza/user"
"github.com/bouncepaw/mycorrhiza/util"
)
2022-02-03 21:47:36 +00:00
func canRenameThisToThat ( oh hyphae . Hypher , nh hyphae . Hypher , u * user . User , lc * l18n . Localizer ) ( errtitle string , err error ) {
if nh . DoesExist ( ) {
rejectRenameLog ( oh , u , fmt . Sprintf ( "name ‘ %s’ taken already" , nh . CanonicalName ( ) ) )
return lc . Get ( "ui.rename_taken" ) , fmt . Errorf ( lc . Get ( "ui.rename_taken_tip" , & l18n . Replacements { "name" : "<a href='/hypha/%[1]s'>%[1]s</a>" } ) , nh . CanonicalName ( ) )
2021-02-17 18:41:35 +00:00
}
2022-02-03 21:47:36 +00:00
if nh . CanonicalName ( ) == "" {
2021-02-17 18:41:35 +00:00
rejectRenameLog ( oh , u , "no new name given" )
2021-10-10 03:51:34 +00:00
return lc . Get ( "ui.rename_noname" ) , errors . New ( lc . Get ( "ui.rename_noname_tip" ) )
2021-02-17 18:41:35 +00:00
}
2022-02-03 21:47:36 +00:00
if ! hyphae . IsValidName ( nh . CanonicalName ( ) ) {
rejectRenameLog ( oh , u , fmt . Sprintf ( "new name ‘ %s’ invalid" , nh . CanonicalName ( ) ) )
2021-10-10 03:51:34 +00:00
return lc . Get ( "ui.rename_badname" ) , errors . New ( lc . Get ( "ui.rename_badname_tip" , & l18n . Replacements { "chars" : "<code>^?!:#@><*|\"\\'&%</code>" } ) )
2021-02-17 18:41:35 +00:00
}
2021-10-01 17:34:56 +00:00
return "" , nil
2021-02-17 18:41:35 +00:00
}
// RenameHypha renames hypha from old name `hyphaName` to `newName` and makes a history record about that. If `recursive` is `true`, its subhyphae will be renamed the same way.
2022-02-03 21:47:36 +00:00
func RenameHypha ( h hyphae . Hypher , newHypha hyphae . Hypher , recursive bool , u * user . User , lc * l18n . Localizer ) ( hop * history . Op , errtitle string ) {
2021-02-17 18:41:35 +00:00
newHypha . Lock ( )
defer newHypha . Unlock ( )
hop = history . Operation ( history . TypeRenameHypha )
2021-10-10 03:51:34 +00:00
if errtitle , err := CanRename ( u , h , lc ) ; errtitle != "" {
2021-02-26 16:43:45 +00:00
hop . WithErrAbort ( err )
2021-02-17 18:41:35 +00:00
return hop , errtitle
}
2021-10-10 03:51:34 +00:00
if errtitle , err := canRenameThisToThat ( h , newHypha , u , lc ) ; errtitle != "" {
2021-02-26 16:43:45 +00:00
hop . WithErrAbort ( err )
2021-02-17 18:41:35 +00:00
return hop , errtitle
}
var (
2022-02-03 21:47:36 +00:00
re = regexp . MustCompile ( ` (?i) ` + h . CanonicalName ( ) )
2021-02-17 18:41:35 +00:00
replaceName = func ( str string ) string {
2022-02-03 21:47:36 +00:00
return re . ReplaceAllString ( util . CanonicalName ( str ) , newHypha . CanonicalName ( ) )
2021-02-17 18:41:35 +00:00
}
hyphaeToRename = findHyphaeToRename ( h , recursive )
renameMap , err = renamingPairs ( hyphaeToRename , replaceName )
renameMsg = "Rename ‘ %s’ to ‘ %s’ "
)
if err != nil {
hop . Errs = append ( hop . Errs , err )
return hop , hop . FirstErrorText ( )
}
if recursive && len ( hyphaeToRename ) > 0 {
renameMsg += " recursively"
}
hop . WithFilesRenamed ( renameMap ) .
2022-02-03 21:47:36 +00:00
WithMsg ( fmt . Sprintf ( renameMsg , h . CanonicalName ( ) , newHypha . CanonicalName ( ) ) ) .
2021-02-17 18:41:35 +00:00
WithUser ( u ) .
Apply ( )
if len ( hop . Errs ) == 0 {
for _ , h := range hyphaeToRename {
2022-02-03 21:47:36 +00:00
h := h . ( * hyphae . Hypha ) // ontology think
oldName := h . CanonicalName ( )
h . RenameTo ( replaceName ( h . CanonicalName ( ) ) )
2021-02-20 06:48:27 +00:00
h . Lock ( )
h . TextPath = replaceName ( h . TextPath )
h . BinaryPath = replaceName ( h . BinaryPath )
h . Unlock ( )
2021-12-30 19:59:28 +00:00
backlinks . UpdateBacklinksAfterRename ( h , oldName )
2021-02-17 18:41:35 +00:00
}
}
return hop , ""
}
2022-02-03 21:47:36 +00:00
func findHyphaeToRename ( superhypha hyphae . Hypher , recursive bool ) [ ] hyphae . Hypher {
hyphaList := [ ] hyphae . Hypher { superhypha }
2021-02-17 18:41:35 +00:00
if recursive {
2022-02-03 21:47:36 +00:00
hyphaList = append ( hyphaList , hyphae . Subhyphae ( superhypha ) ... )
2021-02-17 18:41:35 +00:00
}
2022-02-03 21:47:36 +00:00
return hyphaList
2021-02-17 18:41:35 +00:00
}
2022-02-03 21:47:36 +00:00
func renamingPairs ( hyphaeToRename [ ] hyphae . Hypher , replaceName func ( string ) string ) ( map [ string ] string , error ) {
2021-02-17 18:41:35 +00:00
renameMap := make ( map [ string ] string )
newNames := make ( [ ] string , len ( hyphaeToRename ) )
for _ , h := range hyphaeToRename {
2021-03-02 16:36:57 +00:00
h . Lock ( )
2022-02-03 21:47:36 +00:00
newNames = append ( newNames , replaceName ( h . CanonicalName ( ) ) )
if h . HasTextPart ( ) {
renameMap [ h . TextPartPath ( ) ] = replaceName ( h . TextPartPath ( ) )
2021-02-17 18:41:35 +00:00
}
2022-02-03 21:47:36 +00:00
if h . Kind ( ) == hyphae . HyphaMedia { // ontology think
h := h . ( * hyphae . Hypha )
2021-02-17 18:41:35 +00:00
renameMap [ h . BinaryPath ] = replaceName ( h . BinaryPath )
}
2021-03-02 16:36:57 +00:00
h . Unlock ( )
2021-02-17 18:41:35 +00:00
}
2021-02-20 14:03:54 +00:00
if firstFailure , ok := hyphae . AreFreeNames ( newNames ... ) ; ! ok {
2021-02-17 18:41:35 +00:00
return nil , errors . New ( "Hypha " + firstFailure + " already exists" )
}
return renameMap , nil
}