Skip to content

Instantly share code, notes, and snippets.

@SiarheyUchukhlebau
Created July 22, 2025 15:05
Show Gist options
  • Select an option

  • Save SiarheyUchukhlebau/743d3574f37caa41756b1ceec19c4589 to your computer and use it in GitHub Desktop.

Select an option

Save SiarheyUchukhlebau/743d3574f37caa41756b1ceec19c4589 to your computer and use it in GitHub Desktop.
Fixes empty title fields in serialized PHP templates by replacing them with "BADTITLE". Recursively processes arrays and objects inside hash_options, then saves updated data back to a new file.
#!/usr/bin/env php
<?php
/**
* fix_empty_titles.php — v5
* Usage: php fix_empty_titles.php in.serialized out.serialized
*/
declare(strict_types=1);
error_reporting(E_ALL);
ini_set('display_errors', 'stderr');
/* ----------------- arguments ----------------- */
if ($argc !== 3) {
fwrite(STDERR, "Usage: php {$argv[0]} <input_file> <output_file>\n");
exit(1);
}
[$_, $inputFile, $outputFile] = $argv;
if (!is_readable($inputFile)) {
fwrite(STDERR, "Cannot read {$inputFile}\n");
exit(1);
}
/* ----------------- helpers ----------------- */
function isEmptyTitle($v): bool
{
return $v === null || (is_string($v) && trim($v) === '');
}
function fixEmptyTitles(&$data): void
{
/* array */
if (is_array($data)) {
foreach ($data as $k => &$v) {
if ($k === 'title' && isEmptyTitle($v)) {
$v = 'BADTITLE';
} else {
fixEmptyTitles($v); // <-- recursion must remain
}
}
return;
}
/* object */
if (is_object($data)) {
$ro = new ReflectionObject($data);
foreach ($ro->getProperties() as $prop) {
$prop->setAccessible(true);
$val = $prop->getValue($data);
if ($prop->getName() === 'title' && isEmptyTitle($val)) {
$prop->setValue($data, 'BADTITLE');
} else {
fixEmptyTitles($val);
$prop->setValue($data, $val);
}
}
}
}
/**
* Processes the array of templates and returns the modified array.
*
* @param array $data
* @return array
*/
function processTemplates(array $data): array
{
foreach ($data as $tplKey => &$tpl) { // & – but tpl ≠ options!
if (!isset($tpl['hash_options'])) {
fwrite(STDERR, "Template {$tplKey}: no hash_options\n");
continue;
}
$options = @unserialize($tpl['hash_options']);
if (!is_array($options)) {
fwrite(STDERR, "Template {$tplKey}: bad hash_options\n");
continue;
}
/* recursively fix titles */
fixEmptyTitles($options);
/* serialize back in one line */
$tpl['hash_options'] = serialize($options);
}
unset($tpl);
return $data;
}
/* ----------------- 1. deserialize entire file ----------------- */
$raw = file_get_contents($inputFile);
$data = unserialize($raw, ['allowed_classes' => true]);
if ($data === false && $raw !== 'b:0;') {
fwrite(STDERR, "unserialize() failed – input broken?\n");
exit(1);
}
/* ----------------- 2. process templates ----------------- */
$data = processTemplates($data);
/* ----------------- 3. save result ----------------- */
file_put_contents($outputFile, serialize($data));
echo "Done: {$outputFile}\n";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment