1

I am currently working on a php file indexer and I need to create a recursive function to create an array that will contains the files and subfolders list of the parent folder, with the subfolders also being arrays containing their files and their subfolders (etc...). As it is a school project, I cannot use DirectoryRecursiveIterator and its siblings RecursiveIterator and DirectoryIterator. My issue is that it scans the parent folder and finds the subfolders and files but does not go in subfolders to find files and subfolders.

The code

<?php
    class H5AI
    {
        // Properties
        private $_tree;
        private $_path;
    
        // Construct
        public function __construct($_path)
        {
            $_tree = [];
            $parent = $_tree;
            print_r($this->getFiles($_path, $parent));
        }
    
        // Methods
        public function getPath()
        {
            return $this->_path;
        }
        public function getTree()
        {
            return $this->_tree;
        }
    
        public function getFiles($path, $parent)
        {
            //Opening the directory
            $dirHandle = opendir($path);
            while (false !== $entry = readdir($dirHandle)) {
                //If file found
                if (!is_dir($path . DIRECTORY_SEPARATOR . $entry)) {
                    array_push($parent, $entry);
                }
                // When subdirs found (ignore . & ..)
                else if (is_dir($path . DIRECTORY_SEPARATOR . $entry) && $entry !== "." && $entry !== "..") {
                    $newPath = $path . DIRECTORY_SEPARATOR . $entry;
                    $parent[$entry] = [];
                    $this->getFiles($newPath, $parent[$entry]);
                }
            }
            return $parent;
        }
    }
    // Calling function
    $h5a1 = new H5AI($argv[1]);
    
    // Command I use in the terminal
    php index.php "./test_dir"

    //Output
    Array
    (
        [sub_test_dir] => Array
        (
        )

        [0] => test.css
        [sub_test_dir2] => Array
        (
        )
        [1] => test.js
        [2] => test.html
     )

LLEGIT
  • 13
  • 3

2 Answers2

0

You are creating a separate array, which contains what you want, but is not inserted into your parent array. You have everything right, you just need one little fix:

                //...
                else if (is_dir($path . DIRECTORY_SEPARATOR . $entry) && $entry !== "." && $entry !== "..") {
                $newPath = $path . DIRECTORY_SEPARATOR . $entry;
                $parent[$entry] = [];
                $parent[$entry] = $this->getFiles($newPath, $parent[$entry]); // <-- fix is on this line
            }
tola
  • 152
  • 1
  • 7
  • Thanks a lot mate ! It works fine now :) – LLEGIT Mar 08 '22 at 11:29
  • @tola: the line _$parent[$entry] = [];_ is superfluous. – lukas.j Mar 08 '22 at 11:36
  • @lukas.j It depends on the intended result. If he wants to have an empty array to indicate an empty folder, and not just a null valued element, then he needs that line. If having a null valued element in his array, to indicate an empty folder, is good enough, then that line is indeed superfluous – tola Mar 08 '22 at 12:00
  • 1
    @tola: _$this->getFiles()_ will override it in any case. – lukas.j Mar 08 '22 at 12:03
0
class H5AI {

  public function __construct(string $path) {
    print_r($this->getFiles($path));
  }

  public function getFiles(string $directory): array {
    $handle = opendir($directory);
    $entries = [];
    while (true) {
      $entry = readdir($handle);
      if ($entry === false) {
        break;
      }
      $path = $directory . DIRECTORY_SEPARATOR . $entry;
      if (is_file($path) && !str_starts_with($entry, '.')) {
        $entries[] = $entry;
      } elseif (is_dir($path) && !in_array($entry, [ '.', '..', '$RECYCLE.BIN' /* add other dir names to exclude here */ ])) {
        $entries[$entry] = $this->getFiles($path);
      }
    }
    closedir($handle);
    return $entries;
  }
}
lukas.j
  • 6,453
  • 2
  • 5
  • 24