Virtual Files for page?

Sorry, for not replying earlier, but once I started with this I found myself into a massive refactoring which I wanted to finish first. :slight_smile: Thank you both, I was able to implement this “virtual file” construction.

I need to have virtual files, because the metadata for our files are also in a database. I started working with the standard File::factory approach and a custom file url() function, but got stuck quickly because of some issues with panel previews. I was then looking for something like “File Models” but this doesn’t exist I think, Bastians idea with an extended File class was the way to go.

Here is a rough skeleton of the code I ended up with:

The custom file class:

class MyFile extends File {

  function __construct($rawData, $parent = null) {
    return parent::__construct([
      'filename' => $rawData->name,
      'parent' => $parent,
      'url' => $rawData->url,
      'template' => 'myFile',
      'content' => [
        'title' => $rawData->title,
        // Some other content fields
      ],
    ]);
  }

  public function url(): string {
    return $this->url;
  }

  public function thumb(array $options = NULL) {
    return $this;
  }

  public function delete(bool $force = false): bool {
    // Delete logic here
  }

  public function writeContent(array $data, string $languageCode = null): bool {
    // Update logic here
  }
}

I needed to have the url and thumb functions, otherwise the Panel didn’t work. Also the constructor needed to be like that, I had issues with filtering and sorting when using other data structures.
The writeContent function calls the constructor with the content array. So it is important that the constructor can deal with that. If the original object is build by for instance with a stdClass the constructor needs to make sure it is converted to that if a content array from the write function arrives. Also the data structure of both have to be the same.

The page class:

class MyPage extends Page {

  public function files(): Files {
    $files = new Files([], $this);

    $children = // Some logic to get the remote data here

    foreach ($children as $key => $child) {
      $picture = new MyFile($child, $this);
      $files->append($picture->id(), $picture);
    }

    return $files;
  }
}

One thing that I found out the hard way, is that the id() function needs to return a string in the structure page-uri/file-name.suffix. Otherwise the collection is not behaving correctly in each scenario. So it is the best to use the original id() function from the Kirby File class.

I hope this is helpful.

I think this is pretty amazing and impressive what Kirby can do here. I is not super complicated but opens a lot of possibilities. :slight_smile: :+1:

Thank you,
Georg

5 Likes