I manage to workaround a solution without JavaScript or frontend intervention.
First, I created a hook and filter the call of resize function by page template name. This hook will be triggered after the “bigimage” ($file parameter) will be uploaded.
'hooks' => [
'file.create:after' => function ($file) {
if($file->parent()->template()->name()=='game') {
autoResizeImage($file);
}
},
],
Now, the autoResizeImage function is based on the blueprint field details that is a custom field (type: fileswithresize) which will be described like this (notice the targetfields value which will address the existing target fields from the blueprint):
fields:
bigimage:
type: fileswithresize
label: Big Image
max: 1
multiple: false
targetfields:
- name: img178pxX240px
width: 178
height: 240
- name: img220pxX290px
width: 220
height: 290
images:
label: Images
icon: image
fields:
img178pxX240px:
type: files
label: "178px X 240px:"
max: 1
multiple: false
img220pxX290px:
type: files
label: "220px X 290px:"
max: 1
multiple: false
autoResizeImage function:
function autoResizeImage($file){
$default_lang = kirby()->defaultLanguage()->code();
$current_page = $file->parent();
$page_template_name = $current_page->template()->name();
$blueprint = 'pages/'.$page_template_name;
$blueprintfields = Blueprint::factory($blueprint,null,page())->fields();
$pagecutom_fields_attributes = array_column($blueprintfields,'targetfields'); // can be more custom fields on the page
deleteImages($current_page,$file);
if($file->isResizable()){
if(is_array($pagecutom_fields_attributes[0])){
$fields_to_be_updated = [];
foreach ($pagecutom_fields_attributes[0] as $attribute) {
$targetfield = $attribute['name'];
$width = $attribute['width'];
$height = $attribute['height'];
$quality = 100;
try {
$newfile = $file->crop($width, $height, $quality);
$newfile_created = $current_page->createFile([
'source' => $newfile->root(),
'parent' => $current_page,
'filename' => $newfile->filename(),
'template' => 'default'
], true);
$newfile_created->update();
$fields_to_be_updated[$attribute['name']] = Yaml::encode($newfile_created->filename());
}catch (Exception $e) {
throw new Exception($e->getMessage());
}
}
$fields_to_be_updated['update_type'] = 'autoresize';
if(count($fields_to_be_updated)>0) {
$current_page->update($fields_to_be_updated, $default_lang);
}
}
}
}
function deleteImages($page, $file_except = null){
$files = $page->files();
foreach ($files as $file) {
if($file->filename() != $file_except->filename()) {
$file->delete();
}
}
}
Now, if you do the above, the target fields will be updated but not saved yet and when trying to save the data files will be overridden with empty data. In order to avoid this, I had to get and save the data with state pushed from the autoResizeImage function → line:
$fields_to_be_updated[‘update_type’] = ‘autoresize’;
into the writeContent method from the page (which is a virtual page also).
public function writeContent(array $data, string $languageCode = null): bool
{
//this should be on update only
if (isset($data['update_type'])){
switch ($data['update_type']) {
case 'autoresize':
$data['update_type'] = 'autoresize_save'; //reset the update type to status for saving the page
break;
case 'autoresize_save':
$blueprint = 'pages/game';
$blueprintfields = Blueprint::factory($blueprint,null,page())->fields(); // get the fields from blueprint
$pagecutom_fields_attributes = array_column($blueprintfields,'targetfields'); //filter the custom fields
if(is_array($pagecutom_fields_attributes[0])){ // only one custom field permited per page
foreach ($pagecutom_fields_attributes[0] as $attribute) { // get attributes from custom field
if(!empty($this->{$attribute['name']}()->value())){ // preserve already saved field value
$data[$attribute['name']] = $this->{$attribute['name']}()->value(); // override the image field with the existing value
}
}
}
$data['update_type'] = 'normal'; //reset to normal
break;
case 'normal':
// do nothing, let the image be saved as is
break;
}
}
}
Also, to ensure two steps (refresh the page after update) I created two tabs, one for the big image and one for the target fields. Also, I used an section gallery files to give the user a preview after upload and creating of the new files (which will be great if someone will explain me how to make it read-only).
First step:
Second tab with target images fields with correct data and with full functionality (like replace it manually if wanted):
That’s it.