3

The use case of vfsStream is as follows:

$directories = explode('/', 'path/to/some/dir');

$structure = [];
$reference =& $structure;

foreach ($directories as $directory) {
    $reference[$directory] = [];
    $reference =& $reference[$directory];
}

vfsStream::setup();
$root = vfsStream::create($structure);
$file = vfsStream::newFile('file')
    ->at($root) //should changes be introduced here?
    ->setContent($content = 'Some content here');

The output of vfsStream::inspect(new vfsStreamStructureVisitor())->getStructure() is

Array
(
    [root] => Array
    (
        [path] => Array
        (
            [to] => Array
            (
                [some] => Array
                (
                    [dir] => Array
                    (
                    )
                )
            )
        )

        [file] => Some content here
    )
)

Is it possible to insert a file into specific directory, for example, under dir directory?

sitilge
  • 3,687
  • 4
  • 30
  • 56
  • The simplest way of doing that, after reading the docs a bit, seems to actually build the file in the structure at the start. Why can't you define it when building the structure? – Félix Adriyel Gagnon-Grenier Dec 31 '15 at 19:43
  • @FélixGagnon-Grenier yes, that could be possible; however I seek the solution for the given situation. Wonder if that could be achieved in any way? – sitilge Dec 31 '15 at 21:28

2 Answers2

1

Yes, apparently it is possible to add a child to a vfsStreamFirectory with the addChild() method:

However I've found no simple method in the API Docs that allow for easily traversing a structure to add content. Here is a horrible hacky of doing this for this particular case, it would fail if for instance there were more than one folder per path element.

Basically we have to recursively step through each level, verify if the name is the one to which we want to add the file, then add it when it's found.

use org\bovigo\vfs\vfsStream;
use org\bovigo\vfs\vfsStreamDirectory;
use org\bovigo\vfs\visitor\vfsStreamStructureVisitor;

$directories = explode('/', 'path/to/some/dir');

$structure = [];
$reference =& $structure;

foreach ($directories as $directory) {
    $reference[$directory] = [];
    $reference =& $reference[$directory];
}

vfsStream::setup();
$root = vfsStream::create($structure);
$file = vfsStream::newFile('file')
    ->setContent($content = 'Some content here');

$elem = $root;
while ($elem instanceof vfsStreamDirectory)
{
    if ($elem->getName() === 'dir')
    {
        $elem->addChild($file);
    }
    $children = $elem = $elem->getChildren();
    if (!isset($children[0]))
    {
        break;
    }
    $elem = $children[0];
}

print_r(vfsStream::inspect(new vfsStreamStructureVisitor())->getStructure());
0

The answer was given on github; thus instead of

->at($root)

one should use

->at($root->getChild('path/to/some/dir')).
sitilge
  • 3,687
  • 4
  • 30
  • 56
  • 1
    This leads to following error at my end `TypeError: Argument 1 passed to org\bovigo\vfs\vfsStreamAbstractContent::at() must implement interface org\bovigo\vfs\vfsStreamContainer, instance of org\bovigo\vfs\vfsStreamFile given` Any suggestions? – Schmalitz Jan 28 '21 at 13:01