statamic / eloquent-driver

Provides support for storing your Statamic data in a database, rather than flat files.
https://statamic.dev/tips/storing-content-in-a-database
MIT License
104 stars 71 forks source link

Assets gets duplicated when there is at least one capital letter in the name #258

Closed shawinigan closed 3 months ago

shawinigan commented 3 months ago

We try tu upload assets from the CP but they gets inserted in double in the database when there's a capital letter in the name of the file. We just renamed the file and here's the behaviour :

billethackqc.pdf => working fine billethackqc1.pdf => working fine billethackqc_1.pdf => working fine billethackqc_111111111111111111111111111111111111111111111111111111111.pdf => working fine billethackqc_1Allo.pdf => get inserted in double

Again, it was the same pdf file, we only renamed it and got this behaviour. It seems any file with a capital letter is having the same issue.

ryanmitchell commented 3 months ago

Whats the value of statamic.config.assets.lowercase ?

shawinigan commented 3 months ago
'lowercase' => true,
ryanmitchell commented 3 months ago

Thanks, I'll spent some time later in the week seeing if I can replicate this.

ryanmitchell commented 3 months ago

I don't seem to be able to replicate this using a local filesystem. What filesystem are you using?

modrictin commented 3 months ago

Hey there,

If I try to save an asset which contains a whitespace to assets_meta table, I get the following error:

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'one-public-im-az-1710414015.png' for key 'assets_meta.assets_meta_container_folder_basename_unique' (Connection: mysql, SQL: update `assets_meta` set `basename` = im-az-1710414015.png, `filename` = im-az-1710414015, `path` = public/im-az-1710414015.png, `meta` = {"data":[],"size":861322,"last_modified":1710414015,"width":897,"height":673,"mime_type":"image\/png","duration":null}, `assets_meta`.`updated_at` = 2024-03-14 11:00:15 where `id` = 20)

I also get 2 entries saved to my database after the error: image

Maybe it is connected to this.

Thanks in advance, Tin

ryanmitchell commented 3 months ago

@modrictin can you verify you are on the latest version (3.3.2) as I'm not seeing this behaviour there. How are you creating assets?

shawinigan commented 3 months ago

I don't seem to be able to replicate this using a local filesystem. What filesystem are you using?

Here's the config in the filesystem along with the part related to it in the .env file

'documents' => [ 'driver' => ENV('LOCAL_FILE_DRIVER', 'local'), 'host' => ENV('LOCAL_FILE_HOST', ''), 'username' => ENV('LOCAL_FILE_USERNAME', ''), 'password' => ENV('LOCAL_FILE_PASSWORD', ''), 'visibility' => 'private', 'directory_visibility' => ENV('LOCAL_FILE_DIRECTORY_VISIBILITY', ''), 'root' => ENV('LOCAL_FILE_ROOT', storage_path('app')).'/documents', 'throw' => ENV('LOCAL_FILE_THROW', false) ],

LOCAL_FILE_DRIVER=sftp LOCAL_FILE_HOST=10.1.4.151 LOCAL_FILE_USERNAME=**** LOCAL_FILE_PASSWORD=**** LOCAL_FILE_VISIBILITY=public LOCAL_FILE_DIRECTORY_VISIBILITY=public LOCAL_FILE_ROOT=/var/www/projects/intranet/intranet.dev.shawinigan.ca/storage/app/ LOCAL_FILE_THROW=true

ryanmitchell commented 3 months ago

@shawinigan are you uploading assets through the control panel or by another method? Can you confirm you are using the latest version of this driver?

shawinigan commented 3 months ago

I am uploading through the CP and ran a composer update yesterday so we're running version 3.3.2 now. Here's the part of the composer.lock file about eloquent-driver

{
            "name": "statamic/eloquent-driver",
            "version": "v3.3.2",
            "source": {
                "type": "git",
                "url": "https://github.com/statamic/eloquent-driver.git",
                "reference": "3e19212e1ad1abeee0abd9f1afba98f8caf5729c"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/statamic/eloquent-driver/zipball/3e19212e1ad1abeee0abd9f1afba98f8caf5729c",
                "reference": "3e19212e1ad1abeee0abd9f1afba98f8caf5729c",
                "shasum": ""
            },
            "require": {
                "php": "^8.0",
                "statamic/cms": "^4.51"
            },
            "require-dev": {
                "doctrine/dbal": "^3.3",
                "laravel/pint": "^1.0",
                "orchestra/testbench": "^7.0 || ^8.0",
                "phpunit/phpunit": "^9.4"
            },
            "type": "library",
            "extra": {
                "statamic": {
                    "name": "Eloquent Driver",
                    "description": "Allows you to store Statamic data in a database."
                },
                "laravel": {
                    "providers": [
                        "Statamic\\Eloquent\\ServiceProvider"
                    ]
                }
            },
            "autoload": {
                "psr-4": {
                    "Statamic\\Eloquent\\": "src"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "description": "Allows you to store Statamic data in a database.",
            "support": {
                "issues": "https://github.com/statamic/eloquent-driver/issues",
                "source": "https://github.com/statamic/eloquent-driver/tree/v3.3.2"
            },
            "time": "2024-03-11T10:57:32+00:00"
        },
ryanmitchell commented 3 months ago

Interesting, as I said I'm struggling to recreate.

If you do a dump after this line - https://github.com/statamic/eloquent-driver/blob/3e19212e1ad1abeee0abd9f1afba98f8caf5729c/src/Assets/Asset.php#L151 - do you get any values in $original?

shawinigan commented 3 months ago

I receive an empty array

Interesting, as I said I'm struggling to recreate.

If you do a dump after this line -

https://github.com/statamic/eloquent-driver/blob/3e19212e1ad1abeee0abd9f1afba98f8caf5729c/src/Assets/Asset.php#L151

  • do you get any values in $original?
shawinigan commented 3 months ago

Well no, I removed the die and I do receive an empty array, followed by an array. Here's the content:


array(0){
}array(0){
}array(4){
    [
        "path"
    ]=>string(22)"billethackqc_1Allo.pdf"[
        "folder"
    ]=>string(1)"/"[
        "basename"
    ]=>string(22)"billethackqc_1Allo.pdf"[
        "data"
    ]=>array(0){
    }
}{
    "data": {
        "id": "documents::billethackqc_1allo.pdf",
        "path": "billethackqc_1allo.pdf",
        "filename": "billethackqc_1allo",
        "basename": "billethackqc_1allo.pdf",
        "url": null,
        "reference": "asset::documents::billethackqc_1allo.pdf",
        "permalink": null,
        "extension": "pdf",
        "downloadUrl": "http:\/\/localhost:8000\/cp\/assets\/ZG9jdW1lbnRzOjpiaWxsZXRoYWNrcWNfMWFsbG8ucGRm\/download",
        "size": "62.02 KB",
        "lastModified": "2024-03-14",
        "lastModifiedRelative": "il y a 4 secondes",
        "isImage": false,
        "isSvg": false,
        "isAudio": false,
        "isVideo": false,
        "isMedia": false,
        "isPdf": true,
        "isPreviewable": true,
        "pdfUrl": "http:\/\/localhost:8000\/cp\/pdfs\/ZG9jdW1lbnRzOjpiaWxsZXRoYWNrcWNfMWFsbG8ucGRm",
        "values": {
            "alt": null
        },
        "meta": {
            "alt": null
        },
        "allowDownloading": true,
        "actionUrl": "http:\/\/localhost:8000\/cp\/assets\/actions",
        "actions": [
            {
                "handle": "delete",
                "title": "Supprimer",
                "confirm": true,
                "buttonText": "Delete|Delete :count items?",
                "confirmationText": "Are you sure you want to delete this?|Are you sure you want to delete these :count items?",
                "warningText": null,
                "dangerous": true,
                "fields": [],
                "values": [],
                "meta": [],
                "context": {
                    "container": "documents",
                    "folder": "\/"
                }
            },
            {
                "handle": "download_asset",
                "title": "T\u00e9l\u00e9charger",
                "confirm": false,
                "buttonText": "Run action|Run action on :count items",
                "confirmationText": "Are you sure you want to run this action?|Are you sure you want to run this action on :count items?",
                "warningText": null,
                "dangerous": false,
                "fields": [],
                "values": [],
                "meta": [],
                "context": {
                    "container": "documents",
                    "folder": "\/"
                }
            },
            {
                "handle": "duplicate_asset",
                "title": "Dupliquer",
                "confirm": true,
                "buttonText": "Run action|Run action on :count items",
                "confirmationText": "Are you sure you want to run this action?|Are you sure you want to run this action on :count items?",
                "warningText": null,
                "dangerous": false,
                "fields": [],
                "values": [],
                "meta": [],
                "context": {
                    "container": "documents",
                    "folder": "\/"
                }
            },
            {
                "handle": "move_asset",
                "title": "D\u00e9placer",
                "confirm": true,
                "buttonText": "Move Asset|Move :count Assets",
                "confirmationText": "Are you sure you want to move this asset?|Are you sure you want to move these :count assets?",
                "warningText": null,
                "dangerous": false,
                "fields": [
                    {
                        "display": "Dossier",
                        "type": "select",
                        "options": {
                            "\/": "\/",
                            "autres_documents": "autres_documents",
                            "approvisionnement": "approvisionnement",
                            "communications": "communications",
                            "ressources_humaines": "ressources_humaines",
                            "ressources_humaines\/formations": "ressources_humaines\/formations",
                            "ressources_humaines\/formations\/formation_microsoft_office_365_pour_utilisateurs": "ressources_humaines\/formations\/formation_microsoft_office_365_pour_utilisateurs",
                            "ressources_humaines\/formations\/formation_microsoft_office_365_pour_utilisateurs\/bloc_1_office_365_aper\u00e7u_outlook_onedrive_et_onenote_version_online": "ressources_humaines\/formations\/formation_microsoft_office_365_pour_utilisateurs\/bloc_1_office_365_aper\u00e7u_outlook_onedrive_et_onenote_version_online",
                            "ressources_humaines\/formations\/formation_microsoft_office_365_pour_utilisateurs\/bloc_1_office_365_aper\u00e7u_outlook_onedrive_et_onenote_version_online\/formation_de_plus": "ressources_humaines\/formations\/formation_microsoft_office_365_pour_utilisateurs\/bloc_1_office_365_aper\u00e7u_outlook_onedrive_et_onenote_version_online\/formation_de_plus",
                            "ressources_humaines\/formations\/formation_microsoft_office_365_pour_utilisateurs\/bloc_1_office_365_aper\u00e7u_outlook_onedrive_et_onenote_version_online\/formation_de_plus\/test_pour_un_encore_plus_long_path": "ressources_humaines\/formations\/formation_microsoft_office_365_pour_utilisateurs\/bloc_1_office_365_aper\u00e7u_outlook_onedrive_et_onenote_version_online\/formation_de_plus\/test_pour_un_encore_plus_long_path",
                            "ressources_humaines\/formations\/formation_microsoft_office_365_pour_utilisateurs\/bloc_1_office_365_aper\u00e7u_outlook_onedrive_et_onenote_version_online\/formation_de_plus\/test_pour_un_encore_plus_long_path\/voila_le_dernier": "ressources_humaines\/formations\/formation_microsoft_office_365_pour_utilisateurs\/bloc_1_office_365_aper\u00e7u_outlook_onedrive_et_onenote_version_online\/formation_de_plus\/test_pour_un_encore_plus_long_path\/voila_le_dernier",
                            "ressources_humaines\/formations\/formation_microsoft_office_365_pour_utilisateurs\/bloc_2_utiliser_microsoft_teams": "ressources_humaines\/formations\/formation_microsoft_office_365_pour_utilisateurs\/bloc_2_utiliser_microsoft_teams",
                            "cour_municipale": "cour_municipale",
                            "politiques": "politiques",
                            "covid-19": "covid-19"
                        },
                        "validate": "required",
                        "taggable": false,
                        "push_tags": false,
                        "placeholder": "",
                        "multiple": false,
                        "max_items": 0,
                        "clearable": false,
                        "searchable": true,
                        "cast_booleans": false,
                        "default": null,
                        "component": "select",
                        "handle": "folder",
                        "prefix": null,
                        "instructions": null,
                        "required": true,
                        "visibility": "visible",
                        "read_only": false,
                        "always_save": false
                    }
                ],
                "values": {
                    "folder": null
                },
                "meta": {
                    "folder": null
                },
                "context": {
                    "container": "documents",
                    "folder": "\/"
                }
            },
            {
                "handle": "rename_asset",
                "title": "Renommer",
                "confirm": true,
                "buttonText": "Rename Asset|Rename :count Assets",
                "confirmationText": "Are you sure you want to rename this asset?|Are you sure you want to rename these :count assets?",
                "warningText": null,
                "dangerous": false,
                "fields": [
                    {
                        "type": "text",
                        "validate": "required",
                        "classes": "mousetrap",
                        "focus": true,
                        "placeholder": "billethackqc_1allo",
                        "debounce": false,
                        "input_type": "text",
                        "default": null,
                        "character_limit": 0,
                        "autocomplete": null,
                        "prepend": null,
                        "append": null,
                        "antlers": false,
                        "component": "text",
                        "handle": "filename",
                        "prefix": null,
                        "display": "Filename",
                        "instructions": null,
                        "required": true,
                        "visibility": "visible",
                        "read_only": false,
                        "always_save": false
                    }
                ],
                "values": {
                    "filename": null
                },
                "meta": {
                    "filename": null
                },
                "context": {
                    "container": "documents",
                    "folder": "\/"
                }
            },
            {
                "handle": "replace_asset",
                "title": "Remplacer",
                "confirm": true,
                "buttonText": "Replace Asset",
                "confirmationText": "statamic::messages.asset_replace_confirmation",
                "warningText": null,
                "dangerous": false,
                "fields": [
                    {
                        "display": "Nouvelle ressource",
                        "type": "assets",
                        "container": "documents",
                        "folder": "\/",
                        "max_files": 1,
                        "validate": "required",
                        "mode": "list",
                        "restrict": true,
                        "allow_uploads": true,
                        "show_filename": true,
                        "min_files": 0,
                        "show_set_alt": true,
                        "query_scopes": [],
                        "component": "assets",
                        "handle": "new_asset",
                        "prefix": null,
                        "instructions": null,
                        "required": true,
                        "visibility": "visible",
                        "read_only": false,
                        "always_save": false
                    },
                    {
                        "display": "Supprimer la ressource originelle",
                        "type": "toggle",
                        "default": true,
                        "inline_label": "",
                        "inline_label_when_true": "",
                        "component": "toggle",
                        "handle": "delete_original",
                        "prefix": null,
                        "instructions": null,
                        "required": false,
                        "visibility": "visible",
                        "read_only": false,
                        "always_save": false
                    }
                ],
                "values": {
                    "new_asset": [],
                    "delete_original": true
                },
                "meta": {
                    "new_asset": {
                        "data": [],
                        "container": "documents"
                    },
                    "delete_original": null
                },
                "context": {
                    "container": "documents",
                    "folder": "\/"
                }
            },
            {
                "handle": "reupload_asset",
                "title": "T\u00e9l\u00e9verser de nouveau",
                "confirm": true,
                "buttonText": "Reupload",
                "confirmationText": "statamic::messages.asset_reupload_confirmation",
                "warningText": "statamic::messages.asset_reupload_warning",
                "dangerous": false,
                "fields": [
                    {
                        "type": "files",
                        "max_files": 1,
                        "validate": [
                            "required"
                        ],
                        "container": "documents",
                        "component": "files",
                        "handle": "file",
                        "prefix": null,
                        "display": "Fichier",
                        "instructions": null,
                        "required": true,
                        "visibility": "visible",
                        "read_only": false,
                        "always_save": false
                    }
                ],
                "values": {
                    "file": []
                },
                "meta": {
                    "file": {
                        "uploadUrl": "http:\/\/localhost:8000\/cp\/fieldtypes\/files\/upload"
                    }
                },
                "context": {
                    "container": "documents",
                    "folder": "\/"
                }
            }
        ],
        "blueprint": {
            "title": "Documents",
            "handle": "documents",
            "tabs": [
                {
                    "display": "Principal",
                    "instructions": null,
                    "handle": "main",
                    "sections": [
                        {
                            "fields": [
                                {
                                    "type": "text",
                                    "display": "Texte alternatif",
                                    "instructions": "Description de l'image",
                                    "input_type": "text",
                                    "placeholder": null,
                                    "default": null,
                                    "character_limit": 0,
                                    "autocomplete": null,
                                    "prepend": null,
                                    "append": null,
                                    "antlers": false,
                                    "component": "text",
                                    "handle": "alt",
                                    "prefix": null,
                                    "required": false,
                                    "visibility": "visible",
                                    "read_only": false,
                                    "always_save": false
                                }
                            ]
                        }
                    ]
                }
            ],
            "empty": false
        }
    }
}
ryanmitchell commented 3 months ago

If you add:

$source->syncOriginal();

after this line does it fix it?

https://github.com/statamic/eloquent-driver/blob/3e19212e1ad1abeee0abd9f1afba98f8caf5729c/src/Assets/Asset.php#L172

shawinigan commented 3 months ago

If you add:

$source->syncOriginal();

after this line does it fix it?

https://github.com/statamic/eloquent-driver/blob/3e19212e1ad1abeee0abd9f1afba98f8caf5729c/src/Assets/Asset.php#L172

No, it still gets duplicated in the DB

modrictin commented 3 months ago

Hey @ryanmitchell ,

yes, I can confirm: image

All the best, Tin

ryanmitchell commented 3 months ago

It seems bringing back syncOriginal on upload from before https://github.com/statamic/eloquent-driver/issues/251 fixes this, so I'll need to find a way of solving that issue without it causing these duplications.

potsky commented 3 months ago

Hi @ryanmitchell, we have the same problem:

According to the title, in fact it happens when the sanitized file name is not the same as the original one...

It was my poor contribution!

ryanmitchell commented 3 months ago

@potsky see if https://github.com/statamic/eloquent-driver/pull/259 fixes it

potsky commented 3 months ago

@potsky see if #259 fixes it

Yeeeeeah, it works 👍