Using the panel to access and manipulate files from a folder outside /content

Hi

I currently have this setup for my mp3 files:

/content
  /podcasts
    /ep1
      - file1.mp3
      - podcast.txt
    /ep2
      - file2.mp3
      - podcast.txt

And I want to move to this:

/content
  /podcasts
    /ep1
      - podcast.txt
    /ep2
      - podcast.txt
/podcasts
  - file1.mp3
  - file2.mp3

To facilitate mp3 files saves and reduce the size of my git repo. I want to continue using the panel to upload the mp3 files, or be able to select one from the panel if I already uploaded it before. It means accessing a folder that is outside /content and I’m not sure if it is doable.

I know about the Destination and Template for Uploads but if I understand correctly, it’s only for existing pages and does not work with the kirby object which is the only way to get out of content (or I could not find how to use it).

I also tried to query language to have a list of files, something like query: kirby.roots.podcasts but I don’t know if that’s supposed to exist to being with.

Any tips? Thanks!

You could create them as virtual files, create a page model for the podcast page type (or maybe just the parent page) and redefine the files method, see

Thanks for the tips, I managed to make it work.

First, I created a hook that transfers the file to the /podcast directory on upload:

'hooks' => [
        'file.create:after' => function (Kirby\Cms\File $file) {
            if($file->extension() == "mp3") {
                rename($file->root(), kirby()->roots()->index() . '/podcasts/' . $file->filename());
            }
        }
    ]

Then following your guidance, I created a plugin and directed it to use a model called audiofiles that inherits Files.

// site/plugins/audio-files/index.php
<?php
use Kirby\Cms\App as Kirby;
require __DIR__ . '/models/audiofiles.php';

Kirby::plugin('cookbook/audio-files', [
  'pageModels' => [ 'audiofiles' => 'AudioFilesPage']
]);

In this model, I list all mp3 files in the /podcasts folder, and for each one I construct a direct url to the file.

// site/plugins/audio-files/models/audiofiles.php
<?php

use Kirby\Cms\Page;
use Kirby\Cms\Files;
class AudioFilesPage extends Page
{
  public function files()
  {
    $files = [];
    $localFiles =  preg_grep('~\.(mp3)$~', scandir(kirby()->roots()->index() . '/podcasts'));

    foreach ($localFiles as $filename) {
      $newFile = ['filename' => $filename, 'url' => kirby()->url() . "/podcasts/" . $filename];
      array_push($files, $newFile);
    }

    return $this->files = Files::factory($files, $this);
  }
}

In /content I created /content/audiofiles/audiofiles.txt with a simple Title: Audio Files inside (and kirby added the Uuid).

And finally in the existing pages, if I want to, upload, list and select the mp3 files:

mp3:
    type: files
    query: site.find("audiofiles")
    uploads:
      parent: site.find("audiofiles")

When I open the selector from the panel, Kirby immediately creates a corresponding .txt file inside /content/audiofiles for each mp3 file that does not have one, with the Uuid inside.

Once the mp3 file has been selected, its Uuid is referenced in the podcast.txt.

For example for podcast1.mp3:

  • /content/audiofiles/podcast1.txt contains Uuid 12345
  • /content/podcasts/podcast1/podcast.txt contains Mp3: - file://12345

When uploading a mp3 file, kirby creates the .txt corresponding file inside /content/audiofiles thanks to the uploads part in the blueprint.

Finally on the template side, a simple $page->mp3()->url() retrieves the file url.

Thanks a lot for your help @texnixe, and thanks to the team for creating such an amazingly versatile yet easy to use CMS. :blush:

1 Like