From time to time there are suggestions about having logic in the blueprints, but for security concerns (?), blueprints are static yml files.
It’s not that easy to make a plugin to use logic in blueprint files because they are not very pluggable. However I’ve come up with an idea that works.
Plugin
Installation
- Save the plugin code (down this page) as a file and place it in
plugins/kirby-blueprint-logic/kirby-blueprint-logic.php. - Done!
Setup
Add a php file and place it in blueprints/_project.php if your blueprint filename is project.yml. The underscore is important.
Usage
In the PHP, add stuff just like a blueprint, but you can use logic as well.
title: Project
fields:
<?php
for( $i = 0; $i < 3; $i++ ) : ?>
my_field_<?php echo $i . "\n"; ?>
label: My field <?php echo $i . "\n"; ?>
type: text
<?php endfor;
Pitfalls
- In some odd cases like if you rename a page to
editortemplate. It can trigger errors.
The plugin code
<?php
if( class_exists('panel') ) {
class BlueprintLogic {
public $path;
public $url;
public $panelpages;
public $id;
public $page;
public $yml;
public $ymlFile;
public $snippet;
public function setup() {
$this->setPath();
}
public function setPath() {
$this->panelpages = panel()->urls()->index() . '/pages/';
$this->setCurrentUrl();
if( $this->isPage() ) {
$path = kirby()->roots()->blueprints() . DS . 'default.yml';
$this->setId();
$this->setPage();
$this->setYml();
$this->setPhp();
if( ! empty( $this->php ) ) {
$this->loadPhp();
}
}
}
public function setCurrentUrl() {
$this->url = $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
}
public function setId() {
$url = $this->url;
$url = preg_replace('/\/edit$/', '', $url);
$url = preg_replace('/\/toggle$/', '', $url);
$url = preg_replace('/\/template$/', '', $url);
$url = preg_replace('/\/url$/', '', $url);
$url = preg_replace('/\/delete$/', '', $url);
$url = ( strstr($url, '/file/', true) ) ? strstr($url, '/file/', true) : $url;
$url = str_replace($this->panelpages, '', $url);
$this->id = $url;
}
public function setPage() {
$this->page = page($this->id);
}
public function setYml() {
$root = kirby()->roots()->blueprints();
if( file_exists( $root . DS . $this->page->template() . '.yml' ) ) {
$this->yml = $this->page->template();
} else {
$this->yml = 'default';
}
$this->ymlFile = $root . DS . $this->yml . '.yml';
}
public function isPage() {
if( str::contains( $this->url, $this->panelpages ) ) {
return true;
} else {
return false;
}
}
public function setPhp() {
$php = kirby()->roots()->blueprints() . DS . '_' . $this->yml . '.php';
if( file_exists( $php)) {
$this->php = $php;
}
}
public function loadPhp() {
$php_content = tpl::load($this->php, array(
'site' => site(),
'children' => site()->children(),
'page' => $this->page,
));
$yml_content = tpl::load($this->ymlFile);
if( $php_content != $yml_content ) {
f::write($this->ymlFile, $php_content);
go($this->url);
}
}
}
$blueprintlogic = new BlueprintLogic();
$blueprintlogic->setup();
}
I will release it on github in 2017.
What do you think of the idea?

If this would have been implemented into the core, it would have been solved in another way.
. Especially with languages that care about indentation like YAML.