Batch Editing Kirby Content Files
published on
In a recent project I built with Kirby, I came across a challenge that I needed (or rather wanted) to add an extra field to all of my yaml files. The project is a theater site and contains a lot of event entries, which hold the date and location of what’s playing each day.
The project has been migrated from an old version of webEdition CMS, which the site has been running on for several years. The previous (partial) structure of the event entry model contained a date field and the time of the show, which after getting the data into Kirby looked like this:
Date: 2019-02-13
——
Time: 20:00
I wanted to add a new field with a timestamp that was generated from these two values. I could have done this on the fly as well, but for various reasons, adding a timestamp directly to the files was the better solution. The timestamp is from now on generated when creating a new date entry. The new yaml file and what I wanted to achieve looks like this:
Date: 2019-02-13
——
Time: 20:00
——
Timestamp: 1550088000
So, how do you do that in a thousand files? At first, I thought about writing a shell script, which for a similar task I had done before. I had a stab and couldn’t get it to work. Since I’m more familiar with PHP than Shell scripting, I decided to go down the PHP route.
I always find it a little difficult to traverse directories and iterate on them in any language and it’s the same with PHP. It took me a little time to get it right, but it finally worked and I got done what I needed to be done.
The script below is provided as is and meant as a stating point, in case you have to solve a similar problem. It will likely need modification to work for you, since it’s very specific for my task. It’s also not the prettiest of them all, but it got the job done and that’s enough. If you have ideas on how it can be improved, I’d be happy to hear your comments though ;)
The file structure of my content files looks like this:
showdates
— 1-showdate1
— entry.txt
— 2-showdate2
— entry.txt
— 3-showdate3
— entry.txt
Prerequisites for the addTimeStamp.php script:
- An "Eventtimestamp:" key already exists in the yaml file, but it could be with or without the actual timestamp value;
- The script operates on files named “entry.txt”;
- The script needs to be saved in the parent directory of the directories containing “entry.txt”. In this example it’s the “showdates” directory;
- The script does not handle any errors.
It’s always a good idea to have a backup of the files you’re working on, just in case something goes wrong. That said, here’s the script:
<?php
/*
addTimeStamp.php
This script adds an "eventtimestamp" entry to yaml files in subdirectories of "showdates".
The script needs to be stored in the directory it works on
and only operates on files with the specified name
*/
$path = realpath( './' );
$objects = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $path ) );
foreach ( $objects as $file ) {
if ( preg_match( '/entry\.txt/', $file ) ) {
$content = file_get_contents( $file );
$patternDate = '/Date\: ?(.+)/i';
$patternTime = '/Time\: ?(.+)/i';
preg_match( $patternDate, $content, $matchesDate );
preg_match( $patternTime, $content, $matchesTime );
if ( count( $matchesDate ) && count( $matchesTime ) ) {
date_default_timezone_set( 'Europe/Berlin' );
$eventtimestamp = strtotime( $matchesDate[1] .' '. $matchesTime[1] );
$replacePattern = 'Eventtimestamp: ' . $eventtimestamp . "\n\n";
$stampedContent = preg_replace( '/eventtimestamp\:.*?/i', $replacePattern, $content );
}
file_put_contents( $file, $stampedContent );
} else {
echo "Could not find any files to process.";
die;
}
}
?>
To run the script, save it in the directory you want to run it in, cd
to the directory (e.g. $ cd showdates
) in your Terminal and then run the script with: $ php addTimeStamp.php
. That's all. If everything went right, your files should now all have a new Eventtimestamp key with its respective value.
I hope this might help you out in case you run into a similar problem with either Kirby content files or elsewhere. Feel free to reach out of you have any questions or comments.