Get all files programmatically inside a file manager folder

Permalink
I have a folder structure likes this(in attachment).
is there any way to retrieve all the pdf file's(programmatically) using the "folder1" id?

1 Attachment

midhunsaffron
 
siton replied on at Permalink Reply
siton
My dream is this feature (i hope in the future or someone will give you the way to create this).
Like: GetFolder("paris")

For images for now i create folder named:
"paris"
Than select all images inside this folder and add set "paris" (Why? I dont like the Sets UI - so its easy to me to make this extra step)
https://documentation.concrete5.org/editors/dashboard/files/sets...

Than for file-sets you have rich API (return array than you loop throw this array)
https://www.concrete5.org/community/forums/5-7-discussion/getting-im...
https://documentation.concrete5.org/developers/working-with-files-an...

Or by attributes and ideas you find her:
https://documentation.concrete5.org/developers/working-with-files-an...

If you want to get all files from set - i think the best way if to add another Q about this topic.
midhunsaffron replied on at Permalink Reply
midhunsaffron
Hi siton,

Thanks for the quick reply, i working with a complex file filtering i already used filesets for implementing it. if i add more filesets it will be very hard to manage by clients
mnakalay replied on at Permalink Reply
mnakalay
Hello,

It is not super straightforward but here's how you can do it

use Concrete\Core\Tree\Node\Type\FileFolder;
use Concrete\Core\File\FolderItemList;
$list = false;
// First grab the folder object
$folder = FileFolder::getNodeByName('Your folder name');
if (is_object($folder)) {
    // if we have a folder grab the list of files inside it
    $list = new FolderItemList();
    $list->filterByParentFolder($folder);
    // optionally sort by name
    $list->sortByNodeName();
}
if ($list) {
    // if we do have a llist of files, let's get  the results (the actual list)
    $files = $list->getResults();


Of course, you will have to deal with the loop and what you want to do with each file.
cd13sr replied on at Permalink Reply
Hey, thanks for this code it's great. However, it seems to only work when logged in. Once I'm logged out the $list->getResults() array is 0. Any thoughts?
mnakalay replied on at Permalink Reply
mnakalay
you probably have permissions set on that folder or on the files in the folder and guests are not allowed to see them
cd13sr replied on at Permalink Reply
I haven't changed any file or folder permissions, so they're all using the defaults—Guests are allowed to View Files. If, however, I change the permissions on a folder to also include Guests access to "Search File Folder", then it works. Thoughts? Shouldn't it work with the default permissions?
mnakalay replied on at Permalink Reply
mnakalay
That is strange. The code I posted will just work with whatever permissions you have in place, meaning it will show files it's allowed to show and disregard files that shouldn't be listed.

I believe it should work with the default permission. Maybe a C5 bug?

What version of C5 are you on?
cd13sr replied on at Permalink Reply
Hmm, interesting. I'm on 8.2.1. I can upgrade to the latest version and try again.
mnakalay replied on at Permalink Reply
mnakalay
That would be really helpful if you could but really make sure to do it carefully with backups and all as it's a pretty new version.

If the behavior persists, could you post an issue report about it on Github?
cd13sr replied on at Permalink Reply
Will do, thanks again.
mnakalay replied on at Permalink Best Answer Reply
mnakalay
I misread your question so the code I posted doesn't go past the first level folder.

Here's another one that will go through all the levels and get you all the files

Just don't go overboard with the number of folders and the number of levels deep

<?php
use Concrete\Core\Tree\Node\Type\FileFolder;
use Concrete\Core\File\FolderItemList;
// First grab the folder object
$folder = FileFolder::getNodeByName('Testing Folder');
if (is_object($folder)) {
    $files = [];
    // if we have a folder we need to grab everything inside and then
    // recursively go through the folder's content
    // if what we get is a file we list it
    // otherwise if it's another folder we go through it as well
    $walk = function ($folder) use (&$files, &$walk) {
            $list = new FolderItemList();
            $list->filterByParentFolder($folder);
            $list->sortByNodeName();
midhunsaffron replied on at Permalink Reply
midhunsaffron
Hi mnakalay,

It works correctly, Thanks for your help :)
siton replied on at Permalink Reply
siton
cool! thanks
softwallcave replied on at Permalink Reply
Will there be a standard file folder page attribute at some point? What about attributes on folders?
MrKDilkington replied on at Permalink Reply
MrKDilkington
@softwallcave

I am not aware of a core folder attribute or the ability to apply attributes to folders.

You could make two GitHub feature request issues for this (one for each). Before creating the issue, do a search first to make sure the issue does not already exist.
https://github.com/concrete5/concrete5/issues...

When writing your feature request issues, please include:
- a description of the feature you are requesting
- how and why it would be useful
- examples of it being used
softwallcave replied on at Permalink Reply
Thanks.

One item I ran into. It appears that getNodeByName() does not retrieve a node within a particular folder. Rather, it globally retrieves the first node that matches. Is this by design? Also, does this imply that using FileFolder::getNodeByName('foo') will return the first random 'foo' found rather than something in the root? If so, seems pretty broken.

I ask because I have a directory structure which happens to have some sub-directories with the same names. To traverse I assumed that the following would work:

$grantDocsFolder = FileFolder::getNodeByName('Grant Documents');
foreach(explode('/', $grantDocsPath) as $folderName) {
   if (is_object($grantDocsFolder)) {
      $grantDocsFolder = $grantDocsFolder->getNodeByName($folderName);
   } else {
      break;
   }
}


I have two paths:
"Grant Documents/2018/bob"
"Grant Documents/2017/bob"

With a valid "path" (slash separated), it ends up with a previously created folder, rather than the one in the path provided. Does this mean I have do to the whole filterByParentFolder() and such at each level? If so, I assume one should never use getNodeByName() on an instance.
softwallcave replied on at Permalink Reply
Yep, that is what it seems to take. Don't know about how to get the stuff in the root correctly if getNodeByName() always looks globally.

$grantDocsFolder = FileFolder::getNodeByName('Grant Documents');
foreach(explode('/', $grantDocsPath) as $folderName) {
   if (!is_object($grantDocsFolder)) {
      break;
   }
   $list = new FolderItemList();
   $list->filterByParentFolder($grantDocsFolder);
   $grantDocsFolder = null;
   foreach ($list->getResults() as $item) {
      if (($item->getTreeNodeTypeHandle() === 'file_folder') && !strcmp($item->getTreeNodeName(), $folderName)) {
         $grantDocsFolder = $item;
         break;
      }
   }
}
MrKDilkington replied on at Permalink Reply
MrKDilkington
@softwallcave

Community member mlocati is working on this.

"FileFolder::getNodeByName and duplicated folder names #6672"
https://github.com/concrete5/concrete5/issues/6672...