$page->update() not working correctly for files fields

I’m using a plugin to programatically do things, including updating a page.

The relevant operation to this questions is to fetch a file from a remote location via cURL, save it to the page content folder using F::write and then update the page with $page->update(), and then reload the page.

$response = curl_exec($curl);
curl_close($curl);

F::write($file, $response, false);

try {
  $page->update([
    'my_id' => get('id'),
    'my_file' => F::filename($file),
    'my_text' => get('s'),
    'my_check' => F::filename($file),
  ]);
  return [
    'response' => $file,
  ];
  } catch(Exception $e) {
    echo $e->getMessage();
  }

The issue I’m having is that other field types (text, hidden) save with their values, but the files type field does not. If I call the function a second time, it will save the value into the .txt file and update as expected?

In the sample above, my_id, my_text and my_check will all save with the correct values; my_file will not. If I run the function a second time, then my_file will save.

I have tried putting delays after F::write, before $page->update() I’ve tried using $page->update() twice within the function; nothing seems to work.

This app is using Kirby v3.5.3.1 and cannot be updated at the moment. Does anyone know what in particular is the behaviour of a files field with $page->update() that this isn’t functioning correctly on the first call?

Edit: disregard this comment. It’s something else.

Additionally, a files field expects data as an array, not a string

Also, at this point Kirby doesn’t know that this file exist yet as it is not in the inventory, so it won’t be stored. You have to add it to the inventory first.

1 Like

About how “adding to inventory” works I don’t know, all those methods seem to be protected. But it might be easier to pretend the file is an “upload”.

$response = curl_exec($curl);
curl_close($curl);

// I'm changing the $file variable here, 
// you might want to do this in a more appropriate location
$file = tempnam(sys_get_temp_dir(), 'curl');
F::write($file, $response, false);

// kirby should keep its inventory up to date with this:
$file = $page->createFile([
  'source' => $file
]);

try {
  $page->update([
    'my_id' => get('id'),
    'my_file' => [ $file->filename() ],
    'my_text' => get('s'),
    'my_check' => $file->filename(),
  ]);
  return [
    'response' => $file,
  ];
  } catch(Exception $e) {
    echo $e->getMessage();
  }

Yes, right, like here: Save external image from url in kirby 3 - #3 by squareclouds

Thank you. That worked a charm! :pray: