Get file system path of a files content folder

How can I tell the file system path (not the URL) for the folder a file is in?

This is close but its the url:

<?= $page->audio()->first()->page()?>

Im trying to write a file in the same content folder as a file, so i need to give F:write the path to write too.

The $file->root() method, I think, gives you the filepath to the file.

https://getkirby.com/docs/reference/objects/file/root

You can use PHP’s dirname to get the parent directory from the filepath.

http://www.php.net/manual/en/function.dirname.php

Thanks… this did it, but its a bit of a dance… im sure theres a better way. I did try dirname but it was giving me the wrong answers (theres a chance i was doing it wrong!).

<?php
$a = $page->audio()->first()->root();
echo str_replace($page->audio()->first()->filename(),"",$a);
?>

If you need the full directory path:

$page->file()->parent()->mediaroot()
1 Like

Thats not it either. That points to the media folder, not the content folder…

/public/media/pages/about-us/04-one-slip-art.jpg

I need it to write to:

/public/content/1_about-us/04-one-slip-art.jpg
$page->file()->parent()->root()

then…?

1 Like

Woop! thanks @texnixe that did it. Just one tiny problem now. Ive got it to rip the album cover form the MP3 and save it to the file system, but it’s not showing up in the files panel, I’m guessing because it was done directly on the filesystem rather then through the panel.

How do i “touch” the image so that the panel is aware of it?

I think you have to publish it, so that it is copied to the media folder.

https://getkirby.com/docs/reference/objects/file/publish

1 Like

hmm… cant seem to tell it which file to publish. Im calling this file method from a hook…

'getIDart' => function() {
	// Write File
	$audiofilepath = $this->parent()->root();
	$audioartfilename = substr($this->filename(), 0, -4) . '-art.jpg';
	$audioartfilepath = $audiofilepath.'/'.$audioartfilename;
	$audioart = explode( ',', $this->id3('cover'));
	$audioartdecode = base64_decode($audioart[1]);
	F::write($audioartfilepath, $audioartdecode);
	return $page->file($audioartfilename)->publish();
},

Well, first of all, $page is not define in your method.

Secondly, your method should probably return the filename, then you fetch the file from the page in your hook and publish it.

But it doesnt like working with the $page stuff in the file hook… heres my current plugin & hook…

<?php

require('lib/getid3/getid3.php');

Kirby::plugin('hashandsalt/id3', [

	'fileMethods' => [

		// Fetch info from the ID tag
		'getIDtag' => function() {
			$getID3 = new getID3;
			$fetchid = $getID3->analyze($this->root());
			getid3_lib::CopyTagsToComments($fetchid);

			$data = $fetchid;

			// Check existence...
			$basicinfo = $data['comments_html']?? [];

			// Check for Album Artwork
			if ($coverimg = $data['comments']['picture'][0]['data']?? []) {
				$coverbase64 = 'data:image/jpeg;base64,'.base64_encode($coverimg);
			}	else {
  			$coverbase64 = '';
			}

			// Duration and Artwork
			$otherinfo = array(
				'cover'			=> array($coverbase64),
				'duration' 	=> array($data['playtime_string']),
			);

			// Merge all the info
			$audioinfo = array_merge($basicinfo, $otherinfo);

			if ($audioinfo) {
				$audioinfo['track'] = $audioinfo['track_number'];
				unset($audioinfo['track_number']);
				$audioinfo['year'] = array(substr(implode('', $audioinfo['year']), 0, 4));
			}

			return $audioinfo;

		},

		// Work info from the ID tag
		'id3' => function ($mediainfo = 'title') {
			$audiodata = $this->getIDtag($this);
			return implode('', $audiodata[$mediainfo]?? []) ;
		},

		// Get the Cover art from the MP3 File
		'getIDart' => function() {
			// Write File
			$audiofilepath = $this->parent()->root();
			$audioartfilename = substr($this->filename(), 0, -4) . '-art.jpg';
			$audioartfilepath = $audiofilepath.'/'.$audioartfilename;
			$audioart = explode( ',', $this->id3('cover'));
			$audioartdecode = base64_decode($audioart[1]);
			F::write($audioartfilepath, $audioartdecode);
			return $audioartfilename;
		},

	],

'hooks' => [

	'file.create:after' => function ($file) {

			$coverfile = $file->getIDart();

			$file->update([
	 		 'title' => $file->id3('title'),
	 		 'artist' => $file->id3('artist'),
	 		 'album' => $file->id3('album'),
	 		 'genre' => $file->id3('genre'),
	 		 'year'  => $file->id3('year'),
	 		 'composer' => $file->id3('composer'),
	 		 'duration' => $file->id3('duration'),
	 		 'track' => $file->id3('track'),
	 		 'cover' => $coverfile,

	 	 ]);

	},

]

]);

I don’t see you doing anything with the page in your hook?

Oh sorry… I tried this but it doesnt work and nor does it give me any errors…

	'file.create:after' => function ($file, $page) {

			$coverfile = $file->getIDart();

			$page->file($coverfile)->publish();

			$file->update([
	 		 'title' => $file->id3('title'),
	 		 'artist' => $file->id3('artist'),
	 		 'album' => $file->id3('album'),
	 		 'genre' => $file->id3('genre'),
	 		 'year'  => $file->id3('year'),
	 		 'composer' => $file->id3('composer'),
	 		 'duration' => $file->id3('duration'),
	 		 'track' => $file->id3('track'),
	 		 'cover' => $coverfile,

	 	 ]);

	},

Try

$file->parent()->file($coverfile)->publish();

And remove the $page parameter…

That gives me this error…

Call to a member function publish() on null

But going back to the original problem: does the newly created page not even show up after refreshing the Panel? I mean, if you upload files to the filesystem, they do get recognized by the Panel without having to publish them?
And remove the $page parameter…

I did remove the $page parameter.

When i upload MP3 files to page, the file gets created, the cover image file gets created from the mp3 file, the meta file gets created and stamped with all the stuff in the hook, including the name of the coverfile…

…the cover image is just not showing up in the panel.

Direct to the file system doesn’t seem to work either. It seems you must upload them through the panel for them to show up in the panel, which i can see upsetting some devs who like to work without panel that have clients that do use the panel… sooner or later the dev is going to do something the client cannot see.

The odd thing is that i just deleted the media folder for this page and even that didnt force them to show up.

I’m wondering whether the Panel needs a file content/meta textfile for showing the file in the panel. Maybe we need to check that.

Does it show up if you manually add the content file, e.g. 04-one-slip-art.jpg.txt?

I had to delete my last post, I uploaded to the wrong folder.

No, it doesn’t need a meta data file, but you have to reload the page to make the file show up. Unless you have limited the section to files with a given template, of course. Then the file wouldn’t show up without a meta data file.