-
-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[K4] How to migrate content to native link field #88
Comments
fantastic work - i extended it a little to link to pages and files by UUID <?php declare(strict_types=1);
use Kirby\CLI\CLI;
use Kirby\Uuid\Uuid;
return [
'description' => 'Migrate from Link plugin to native K4 link field',
'args' => [
'verbose' => [
'shortPrefix' => 'v',
'longPrefix' => 'verbose',
'description' => 'Verbose output',
'defaultValue' => false,
'noValue' => true,
],
'dryrun' => [
'longPrefix' => 'dry-run',
'description' => 'Dry run',
'defaultValue' => false,
'noValue' => true,
],
],
'command' => static function (CLI $cli): void {
$directory = kirby()->roots()->content();
$processed = 0;
$replacements = 0;
$isDryRun = $cli->arg('dryrun');
$isVerbose = $cli->arg('verbose');
// Recursively iterate through all files in the content directory
$filenames = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($directory),
RecursiveIteratorIterator::SELF_FIRST
);
foreach ($filenames as $filename) {
$filepath = $filename->getPathname();
$relpath = str_replace($directory . '/', '', $filepath);
// Process only .txt files
if ($filename->isDir() || pathinfo($filepath, PATHINFO_EXTENSION) !== 'txt') {
continue;
}
$content = file_get_contents($filepath);
$fileReplacements = 0;
// Process YAML-like structure with JSON content
$content = preg_replace_callback(
'/^(\w+):\s*(\[.*\])$/ms',
function ($matches) use (&$fileReplacements, $isVerbose, $cli, $relpath) {
$fieldName = $matches[1];
$jsonContent = $matches[2];
$json = json_decode($jsonContent, true);
if (json_last_error() === JSON_ERROR_NONE) {
$json = transformNestedJson($json, $fileReplacements);
if ($isVerbose && $fileReplacements > 0) {
$cli->out(" Transformed field '{$fieldName}' in {$relpath}");
}
return $fieldName . ': ' . json_encode($json, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
}
return $matches[0];
},
$content
);
// Write changes to file if not a dry run
if (!$isDryRun && $fileReplacements > 0) {
file_put_contents($filepath, $content);
}
// Output processing results
if ($fileReplacements === 0 && $isVerbose) {
$cli->out("⏩ [0] {$relpath}");
} elseif ($fileReplacements > 0) {
$cli->out("✅ [{$fileReplacements}] {$relpath}");
}
$processed++;
$replacements += $fileReplacements;
}
$cli->success("Files processed: {$processed}, Total replacements: {$replacements}");
}
];
/**
* Recursively transform nested JSON structures, including those stored as strings
*
* @param mixed $data The data to transform
* @param int $replacements Reference to the replacement counter
* @return mixed The transformed data
*/
function transformNestedJson($data, &$replacements)
{
if (is_array($data)) {
foreach ($data as $key => &$value) {
if (is_array($value)) {
$value = transformNestedJson($value, $replacements);
} elseif (is_string($value) && $key === 'categories') {
// Handle nested JSON stored as a string
$nestedJson = json_decode($value, true);
if (json_last_error() === JSON_ERROR_NONE) {
$value = json_encode(transformNestedJson($nestedJson, $replacements), JSON_UNESCAPED_SLASHES);
}
}
// Check for link structure and transform if found
if (is_array($value) &&
isset($value['type']) &&
in_array($value['type'], ['url', 'page', 'file', 'email', 'tel'])) {
if (!isset($value['value']) || empty($value['value'])) {
// If there's no value or it's empty, set the entire field to an empty string
$value = '';
} else {
$value = transformLink($value['type'], $value['value']);
}
$replacements++;
}
}
}
return $data;
}
/**
* Transform a single link based on its type
*
* @param string $type The type of the link (url, page, file, email, tel)
* @param string $value The value of the link
* @return string The transformed link value
*/
function transformLink(string $type, string $value): string
{
if (empty($value)) {
return '';
}
switch ($type) {
case 'email':
return 'mailto:' . $value;
case 'tel':
return 'tel:' . $value;
case 'page':
$page = kirby()->page($value);
return $page ? Uuid::for($page)->toString() : '';
case 'file':
$file = kirby()->file($value);
return $file ? Uuid::for($file)->toString() : '';
default:
return $value;
}
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I created a Kirby CLI command for migrating content to the native link field. It's still a work in progress and may not work correctly if you've used more features of the link field than I have. Please run a dry run first and consider this a starting point. Feel free to expand on it and share your improvements.
The command automatically transforms this structure…
…to this:
It can also handle JSON content (blocks field) and turns this…
…to this:
Here's the command:
The text was updated successfully, but these errors were encountered: