Hello there,
I’m looking for a way to upload and select archives in different pages, but saving / uploading them to a central folder. I want to achieve this without depending on the dashboard / panel view.
Right now, I got this to select already uploaded files from certain other pages:
download:
label: Archive
type: files
layout: list
query: site.index.filterBy("intendedTemplate", "release").files.filterBy("type", "archive")
… but what I’d like is the following: when editing pages with “intendedTemplate”, “release”, one should be able to upload (section type: files) and select from those (field type: files), but they should be saved in a central folder (inside or outside content
, doesn’t matter). I’d be okay if the ‘root’ files section lives in a site.yml
tab, but it should be accessible through those ‘release’ pages.
For accessing those from a files field, I’d just alter above blueprint query, but what about the upload problem?
Thanks for your time and thoughts,
S1SYPHOS
// Edit: Among other stuff, my current solution eliminates uploading the same file twice, but it is generated two times inside the media folder (pages/page1/file.zip
and pages/page2/file.zip
), resulting in wasted webspace
It is not necessary to upload files to the current page. You can put a files section into your blueprint that uses a central media hub folder as the parent, well, using the parent
option.
The only thing I somehow can’t make out is how to set the site as files section parent.
using parent: site
seemed to work just fine for me … ?
Well, that was the most obvious and I tried that and always got an error. Did you test with 3.0.3 or 3.0.2? Maybe I have to update first, I tested with 3.0.2.
Edit: no, I keep getting a “The JSON response from the API could not be parsed. Please check your API connection.” error even with a fresh 3.0.3 Starterkit. Maybe I’m just being dumb somehow.
sections:
files:
headline: Files
type: files
parent: site
template: archive
info: "{{ file.niceSize }}"
… worked just fine with v3.0.2
Maybe you can help me once again.
I’m making a site for couple musicians, some of them released records together. However, I’m looking for a way to organize them - my first attempt being the obvious choice, subpages, but for shared releases, I don’t want to duplicate pages, because if something changes, you’d have to change two subpages: subpage below musician1 and again as subpage of musician 2, so maybe by using a related pages = musicians field?
I’d create records and musicians. Then use a pages field to assign musicians to records.
That way you can query the related musicians on every record page. And you can also fetch all records that belong to a musician on a musician’s page.
2 Likes
Ok, looks like something was really messed up, because I got it to work with a new new Starterkit. But still very strange.
I’m going with a pages field, but don’t seem to get the filtering t work like expected - on the musician page, I’m trying to get all records that contain this specific musician inside their pages
field …
@S1SYPHOS Could you please post your code?
Each record / release has a pages field containing all musicians that worked on the piece:
# pages/release.yml
sections:
about:
type: fields
fields:
artists:
label: Musicians
type: pages
query: site.index.filterBy("intendedTemplate", "artist")
required: true
In the artist template, I want to display all records / releases linked to this artist:
<div class="container">
<div class="columns is-mobile is-centered is-multiline has-text-centered">
<?php
foreach ($releases as $release) :
$slug = str::slug($release->title());
$cover = $release->cover()->toFile();
$image = $cover->thumb(option('thumbs.presets.cover'));
?>
<a class="modal-toggle" data-toggle="<?= $slug ?>" href="#">
<img src="<?= $image->url() ?>" title="<?= $release->title() ?>" alt="Cover von <?= $release->title() ?>" width="<?= $image->width(); ?>" height="<?= $image->height() ?>">
</a>
<?php endforeach ?>
</div>
</div>
The important part is defining $releases
in the controller:
<?php
$raps = page('releases')->children()->listed()->filterBy(???)
I tried different stuff but nothing seemed to work …
$raps = page('releases')->children()->listed()->filter(function($child) use($page) {
$artists = $child->artists()->toPages();
if($artists->has($page)) {
return $child;
}
});
1 Like
Last thing I want to know:
Is there a way to put this complex monster into a pages
field for every musician to show the releases that are bound to him/her?
The notation translates like ->
becomes .
but what about the filter
function? Given there are definitions as well?
That is very well possible:
Kirby::plugin('texnixe/customMethods', [
'pagesMethods' => [
'getRecords' => function ($musician) {
$records = $this->filter(function($child) use($musician) {
$artists = $child->artists()->toPages();
if($artists->has($musician)) {
return $child;
}
});
return $records;
}
]
]);
In your controller/template:
$records = page('releases')->children()->listed()->getRecords($page); // where page is the musician page
dump($records);
This is also available inside a blueprint somehow, I presume?
// I meant to show associated records in the panel page of each musician, meaning I’d define them somehow inside blueprints/pages/artist.yml
That method should be available in the Panel as well. Maybe you can use @rasteiner’s Pagesdisplay plugin
I’ll try that and report back.
// Edit:
Works like a charm in the frontend, but not from within the blueprint:
sections:
releases:
headline: Releases
type: pagesdisplay
query: site.find("releases").children.getRecords(page)
that won’t work because the query language doesn’t support evaluating function arguments.
Your query is automatically converted to the equivalent of:
site.find("releases").children.getRecords("page")
(page
is simply seen as a string and not as a variable pointing to your artist)
There are many ways to work around this.
I guess the cleanest and most expressive one would be to create a page model for your “artist” pages.
That would go like this:
/site/models/artist.php:
<?php
use Kirby\Cms\Page;
class ArtistPage extends Page {
function getRecords($recordsId) {
return site()->find($recordsId)->children()->getRecords($this);
}
}
you would use it in your artist.yml
like this:
sections:
releases:
headline: Releases
type: pagesdisplay
query: page.getRecords("releases")
If you only ever will have a single page that collects all records (and that one will never change uid), you might as well hardcode the path to it:
<?php
use Kirby\Cms\Page;
class ArtistPage extends Page {
function getRecords() {
return site()->find('releases')->children()->getRecords($this);
}
}
and then simply use it as query like this:
query: page.getRecords
you can of course use that function also in your artist template ($page->getRecords()
)
PS: I haven’t tried any of that code.