Background
I'm writing a plugin that will function as a document-archive with access-rights to different folders set based on user-groups.
In addition to folders which are restricted, there is also one folder in the asset-source which is "open" to everyone.
I have the full plugin working; or at least so I thought until one of the test-users moved the "open" folder inside the asset-source trough the CP.
Suddenly the "open" folder (and it's contents) were no longer displayed anywhere.
I was fetching this folder based on it its ID.
Why you should not rely on folder-ids in Craft
Basically - folder-IDs are dynamic, which means that you cannot safely look up a folder by ID!
Let's do a little experiment.
Create an asset-source named My assets
, and under it create two folders: Test
and Test2
Now - if you look at your craft_assetfolders
database-table, you'll see something akin to:
ID - parentId - sourceId - name - path
77 - NULL - 4 - "My-assets" -
78 - 77 - 4 - "Test" - "Test/"
79 - 77 - 4 - "Test2" - "Test2/"
Note that id
, parentId
and sourceId
might be different numbers in your example - they depend on how much your craft_assetfolders
database-table contained before you started this example.
So far this all makes perfect sense - until you move a folder! Per example, drag and drop Test
into Test2
, then reload the view of your database-table
It will now read
ID - parentId - sourceId - name - path
77 - NULL - 4 - "My-assets" -
79 - 77 - 4 - "Test2" - "Test2/"
80 - 79 - 4 - "Test" - "Test2/Test/"
What happened to id 78
? It's gone! However the folder Test
still exists, it still contains all of its assets etc - it just has a new ID.
Now - for the sake of experimenting, let us drag and drop Test
back to the root of our asset-source and reload our view of the database-table
ID - parentId - sourceId - name - path
77 - NULL - 4 - "My-assets" -
79 - 77 - 4 - "Test2" - "Test2/"
81 - 77 - 4 - "Test" - "Test/"
Basically - whenever you move an asset-folder, rather than simply update the path
and parentId
values of the associated database-row, the old row is deleted and a new one is created.
Summa summarium - having a plugin or template reference a folder by its ID is hardly safe!
What other options do we have?
Well, in addition to ID folders also have a UID. But, since that is set on row creation, that also changes when a folder is moved. So that's another no-go.
We could look it up by name - but names can be changed, so that's as unreliable as looking it up by ID (or UID).
Even if you were to write up a plugin-setting that allows you to pick the desired folder, that would - given that you move (or - if your plugin stores name rather than ID - rename) the folder - contain a null-reference.
So how can we - safely - identify a single asset-folder in a plugin, and know that it will always point to said folder and subsequently its contents?