🚀 A new era: Kirby 4 Get to know
Skip to content

Core improvements

QR Code generation

Kirby's new Kirby\Image\QrCode class, qr() helper function and ->toQrCode() field method allow you to create QR Codes right out of the box:

$qr = new Kirby\Image\QrCode('https://getkirby.com');
$qr->toSvg(color: '#ff00ff');
$qr->toDataUri(color: '#ff00ff');

qr('https://getkirby.com')->toSvg();
$page->myLinkField()->toQrCode()->toSvg();

Support for UUIDs and permalinks in URL helper

You can now pass a page UUID, a file UUID or a permalink to the url() helper and it will be converted to the actual URL:

<?= url('page://abcd') ?>
<?= url('file://abcd') ?>
<?= url('/@/page/abcd') ?>
<?= url('/@/file/abcd') ?>

This will also work for other URL methods like $field->toUrl(), Url:to(), etc.

Support for UUIDs in API calls

You can now use UUIDs in API calls to request pages and files. #4769

/api/pages/@$pageUUID

The UUIDs must be passed without scheme, but a prefixed @. I.e.:

// Nope
/api/pages/page://abcd

// Yes
/api/pages/@abcd

File routes can also handle file UUIDs for files and parents:

/api/pages/@$pageUUID/files/$filename
/api/pages/@$pageUUID/files/@$fileUUID

In addition to that there are new direct UUID file routes:

/api/files/@$fileUUID

Better plugin asset handling

  • New assets plugin extension that allows plugins to specify assets from custom paths and with a wider range of extensions than previously supported
  • New Kirby\Cms\Plugin::assets() and Kirby\Cms\Plugin::asset($assetName) methods
  • New Kirby\Cms\PluginAsset object with many methods, e.g. $plugin->asset('styles.css')->url()
  • Plugin asset media url contains a modification timestamp to easily cachebust (e.g. /media/plugins/getkirby/test-plugin/2375797551-472389240/styles.css)
  • css() and js() helpers support passing plugin and plugin assets objects to include all assets of the plugin:
css([
  'assets/css/index.css',
  $kirby->plugin('foo/bar')
]);

css([
  'assets/css/index.css',
  $kirby->plugin('foo/bar')->assets(),
]);

css([
  'assets/css/index.css',
  $kirby->plugin('foo/bar')->asset('styles.css'),
]);

New SymmetricCrypto class

Kirby\Toolkit\SymmetricCrypto is a user-friendly and safe abstraction for symmetrical authenticated encryption using the PHP sodium extension:

use Kirby\Toolkit\SymmetricCrypto;

// encryption/decryption with a password
$crypto     = new SymmetricCrypto(password: 'super secure');
$ciphertext = $crypto->encrypt('a very confidential string');
$plaintext  = $crypto->decrypt($ciphertext);

// encryption with a random key
$crypto     = new SymmetricCrypto();
$ciphertext = $crypto->encrypt('a very confidential string');
$secretKey  = $crypto->secretKey();

// encryption/decryption with a previously generated key
$crypto     = new SymmetricCrypto(secretKey: $secretKey);
$ciphertext = $crypto->encrypt('a very confidential string');
$plaintext  = $crypto->decrypt($ciphertext);

New LazyValue class

Kirby\Toolkit\LazyValue allows to protect a closure function from being called by other code that is testing for instanceof Closure:

$value = new LazyValue(fn ($a, $b, $c) => 'please protect me');

// ...

if ($value instanceof Closure) {
  // we would hate if our value gets unwrapped here,
  // that's why we cannot use a normal closure but LazyValue
  $value = $value();
}

// ...

// finally we want to unwrap our protected closure
if ($value instanceof LazyValue) {
  $value = $value->resolve($a, $b, $c);
}

More improvements