Skip to content

Commit

Permalink
fix: [#554] Storage can't judge nesting folder correctly (#59)
Browse files Browse the repository at this point in the history
  • Loading branch information
hwbrzzl authored Jan 6, 2025
1 parent a738393 commit 123a746
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 8 deletions.
60 changes: 59 additions & 1 deletion cloudinary.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/gookit/color"
"github.com/goravel/framework/contracts/config"
"github.com/goravel/framework/contracts/filesystem"
"github.com/goravel/framework/support/str"
)

type Cloudinary struct {
Expand Down Expand Up @@ -175,6 +176,10 @@ func (r *Cloudinary) Directories(path string) ([]string, error) {

// Exists checks if a file exists in the Cloudinary storage.
func (r *Cloudinary) Exists(file string) bool {
if strings.HasSuffix(file, "/") {
return r.isDirectoryExist(file)
}

_, err := r.getAsset(file)
return err == nil
}
Expand Down Expand Up @@ -227,7 +232,7 @@ func (r *Cloudinary) LastModified(file string) (time.Time, error) {
// MakeDirectory creates a directory.
func (r *Cloudinary) MakeDirectory(directory string) error {
result, err := r.instance.Admin.CreateFolder(r.ctx, admin.CreateFolderParams{
Folder: directory,
Folder: validPath(directory),
})
if err != nil {
return err
Expand Down Expand Up @@ -286,6 +291,12 @@ func (r *Cloudinary) Path(file string) string {

// Put stores a new file on the disk.
func (r *Cloudinary) Put(file, content string) error {
// If the file is created in a folder directly, we can't check if the folder exists.
// So we need to create the top folder first.
if err := r.makeDirectories(file); err != nil {
return err
}

tempFile, err := r.tempFile(content)
defer os.Remove(tempFile.Name())
if err != nil {
Expand All @@ -302,6 +313,12 @@ func (r *Cloudinary) Put(file, content string) error {

// PutFile stores a new file on the disk.
func (r *Cloudinary) PutFile(path string, source filesystem.File) (string, error) {
// If the file is created in a folder directly, we can't check if the folder exists.
// So we need to create the top folder first.
if err := r.makeDirectories(str.Of(path).Finish("/").String()); err != nil {
return "", err
}

uploadResult, err := r.instance.Upload.Upload(r.ctx, source.File(), uploader.UploadParams{
Folder: validPath(path),
UseFilename: api.Bool(true),
Expand All @@ -315,6 +332,12 @@ func (r *Cloudinary) PutFile(path string, source filesystem.File) (string, error

// PutFileAs stores a new file on the disk.
func (r *Cloudinary) PutFileAs(path string, source filesystem.File, name string) (string, error) {
// If the file is created in a folder directly, we can't check if the folder exists.
// So we need to create the top folder first.
if err := r.makeDirectories(str.Of(path).Finish("/").String()); err != nil {
return "", err
}

uploadResult, err := r.instance.Upload.Upload(r.ctx, source.File(), uploader.UploadParams{
Folder: validPath(path),
PublicID: name,
Expand Down Expand Up @@ -379,6 +402,41 @@ func (r *Cloudinary) getAsset(path string) (*uploader.ExplicitResult, error) {
return nil, errors.New("file not found")
}

func (r *Cloudinary) isDirectoryExist(path string) bool {
pathNoSlash := strings.TrimSuffix(path, "/")
paths := str.Of(path).RTrim("/").Split("/")
searchPath := "/"
if len(paths) > 1 {
searchPath = strings.Join(paths[:len(paths)-1], "/")
}

folders, err := r.instance.Admin.SubFolders(r.ctx, admin.SubFoldersParams{
Folder: searchPath,
MaxResults: 100000,
})
if err != nil {
return false
}
for _, folder := range folders.Folders {
if folder.Path == pathNoSlash {
return true
}
}
return false
}

func (r *Cloudinary) makeDirectories(path string) error {
folders := strings.Split(path, "/")
for i := 1; i < len(folders); i++ {
folder := strings.Join(folders[:i], "/")
if err := r.MakeDirectory(folder); err != nil {
return err
}
}

return nil
}

func (r *Cloudinary) tempFile(content string) (*os.File, error) {
tempFile, err := os.CreateTemp(os.TempDir(), "goravel-")
if err != nil {
Expand Down
20 changes: 14 additions & 6 deletions cloudinary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import (
"time"

"github.com/gookit/color"
filesystemcontract "github.com/goravel/framework/contracts/filesystem"
configmock "github.com/goravel/framework/mocks/config"
contractsfilesystem "github.com/goravel/framework/contracts/filesystem"
mocksconfig "github.com/goravel/framework/mocks/config"
"github.com/goravel/framework/support/carbon"
"github.com/stretchr/testify/assert"
)
Expand All @@ -25,7 +25,7 @@ func TestStorage(t *testing.T) {

assert.Nil(t, os.WriteFile("test.txt", []byte("Goravel"), 0644))

mockConfig := &configmock.Config{}
mockConfig := &mocksconfig.Config{}
mockConfig.On("GetString", "filesystems.disks.cloudinary.key").Return(os.Getenv("CLOUDINARY_ACCESS_KEY_ID"))
mockConfig.On("GetString", "filesystems.disks.cloudinary.secret").Return(os.Getenv("CLOUDINARY_ACCESS_KEY_SECRET"))
mockConfig.On("GetString", "filesystems.disks.cloudinary.cloud").Return(os.Getenv("CLOUDINARY_CLOUD"))
Expand All @@ -49,6 +49,11 @@ func TestStorage(t *testing.T) {
assert.True(t, driver.Exists("AllDirectories/1.txt"))
assert.True(t, driver.Exists("AllDirectories/2.txt"))
assert.True(t, driver.Exists("AllDirectories/3/3.txt"))
assert.True(t, driver.Exists("AllDirectories/3/4/"))
assert.True(t, driver.Exists("AllDirectories/"))
assert.True(t, driver.Exists("AllDirectories/3/"))
assert.True(t, driver.Exists("AllDirectories/3/5/"))
assert.True(t, driver.Exists("AllDirectories/3/5/6/"))
assert.True(t, driver.Exists("AllDirectories/3/5/6/6.txt"))
files, err := driver.AllDirectories("AllDirectories")
assert.Nil(t, err)
Expand Down Expand Up @@ -271,8 +276,11 @@ func TestStorage(t *testing.T) {
{
name: "Put",
setup: func() {
assert.Nil(t, driver.Put("Put/1.txt", "Goravel"))
assert.True(t, driver.Exists("Put/1.txt"))
assert.Nil(t, driver.Put("Put/a/b/1.txt", "Goravel"))
assert.True(t, driver.Exists("Put/"))
assert.True(t, driver.Exists("Put/a/"))
assert.True(t, driver.Exists("Put/a/b/"))
assert.True(t, driver.Exists("Put/a/b/1.txt"))
assert.True(t, driver.Missing("Put/2.txt"))
assert.Nil(t, driver.DeleteDirectory("Put"))
},
Expand Down Expand Up @@ -391,7 +399,7 @@ type File struct {
path string
}

func (f *File) Disk(disk string) filesystemcontract.File {
func (f *File) Disk(disk string) contractsfilesystem.File {
return &File{}
}

Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,17 @@ require (
github.com/dromara/carbon/v2 v2.5.2 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/schema v1.4.1 // indirect
github.com/kr/pretty v0.1.0 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/text v0.21.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect
google.golang.org/grpc v1.69.2 // indirect
google.golang.org/protobuf v1.35.1 // indirect
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
8 changes: 7 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ github.com/goravel/framework v1.15.1 h1:9K5Vf51+0YIQbLMd1+hk0L7LDBMaAmeLlQnoHJu6
github.com/goravel/framework v1.15.1/go.mod h1:Qo5Xlf+slrosyMxBKbNoxpEmzB6y2C5FI4BHNdVOSyI=
github.com/gorilla/schema v1.4.1 h1:jUg5hUjCSDZpNGLuXQOgIWGdlgrIdYvgQ0wZtdK1M3E=
github.com/gorilla/schema v1.4.1/go.mod h1:Dg5SSm5PV60mhF2NFaTV1xuYYj8tV8NOPRo4FggUMnM=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
Expand Down Expand Up @@ -62,8 +67,9 @@ google.golang.org/grpc v1.69.2 h1:U3S9QEtbXC0bYNvRtcoklF3xGtLViumSYxWykJS+7AU=
google.golang.org/grpc v1.69.2/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4=
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

0 comments on commit 123a746

Please sign in to comment.