Skip to content

Instantly share code, notes, and snippets.

@mmcev106
Last active July 17, 2023 20:28
Show Gist options
  • Save mmcev106/e0c4078de57d37a6b3a81d84a366ffbb to your computer and use it in GitHub Desktop.
Save mmcev106/e0c4078de57d37a6b3a81d84a366ffbb to your computer and use it in GitHub Desktop.
change-wordpress-url-in-database
#!/usr/bin/env php
<?php
// TODO - Add support for multisite
// Could start by just throwing an error when a multisite install is detected.
// TODO - Add support for urls inside serialized objects.
// This may be very easily to do by including PHP's serialized string
// syntax (including the length) in the list of strings to replace.
if(count($argv) != 4){
die("You must specify an input file, new url, and output file!");
}
$inPath = $argv[1];
$newUrl = rtrim($argv[2], '/');
$outPath = $argv[3];
if(!file_exists($inPath)){
die("The specified input file doesn't exist!");
}
if($inPath == $outPath){
die("Input and output files cannot be the same!");
}
$oldUrl = getOldUrl($inPath);
replaceUrls($inPath, $outPath, $oldUrl, $newUrl);
return;
/*-------------------------------------------------------------------*/
function startsWith($haystack, $needle)
{
$length = strlen($needle);
return (substr($haystack, 0, $length) === $needle);
}
function getOldUrl($path){
$file = fopen($path, "r");
$siteUrl = null;
while(!feof($file)){
$line = fgets($file);
if(startsWith($line, "INSERT INTO `wp_options`")){
$siteUrlStart = strpos($line, '(') + 1;
$siteUrlEnd = strpos($line, ')', $siteUrlStart);
$homeStart = strpos($line, '(', $siteUrlEnd) + 1;
$homeEnd = strpos($line, ')', $homeStart);
$siteUrlParts = explode(',', substr($line, $siteUrlStart, $siteUrlEnd - $siteUrlStart));
$homeParts = explode(',', substr($line, $homeStart, $homeEnd - $homeStart));
$siteUrl = trim($siteUrlParts[2], "'");
$home = trim($homeParts[2], "'");
if($siteUrl != $home){
throw new Exception("The siteurl ($siteUrl) and home ($home) are not the same!!!");
}
break;
}
}
fclose($file);
if(empty($siteUrl)){
throw new Exception("The siteurl could not be detected!");
}
return rtrim($siteUrl, '/');
}
function getDomain($url){
$parts = explode('/', $url);
return $parts[2];
}
function replaceUrls($inPath, $outPath, $oldUrl, $newUrl){
if(startsWith($newUrl, 'https')){
$alternateOldUrl = str_replace('http://', 'https://', $oldUrl);
}
else{
$alternateOldUrl = str_replace('https://', 'http://', $oldUrl);
}
$oldDomain = getDomain($oldUrl);
$newDomain = getDomain($newUrl);
$inFile = fopen($inPath, "r");
$outFile = fopen($outPath, 'w');
while(!feof($inFile)){
$line = fgets($inFile);
// $die = false;
// if(strpos($line, $oldUrl) !== FALSE){
// $die = true;
// echo "Before: $line\n";
// }
$line = replaceInSerializedArrays($oldUrl, $newUrl, $line);
$line = replaceInSerializedArrays($alternateOldUrl, $newUrl, $line);
$line = str_replace($oldUrl, $newUrl, $line);
$line = str_replace($alternateOldUrl, $newUrl, $line);
// Replace references to the domain only inside single quoted strings (like source_domain).
$line = str_replace("'$oldDomain'", "'$newDomain'", $line);
// if($die){
// echo "After: $line\n";
// die();
// }
fwrite($outFile, $line);
}
fclose($inFile);
fclose($outFile);
}
function replaceInSerializedArrays($find, $replace, $subject){
$offset = 0;
while(preg_match('/s:([0-9]+):\\\(")/', $subject, $matches, PREG_OFFSET_CAPTURE, $offset)){
// print_r($matches);
$start = $matches[0][1];
$length = $matches[1][0];
$handleChar = function($char, $nextChar){
if($char == '\\'){
if($nextChar == '\\'){
return 1;
}
else{
return 0;
}
}
else{
return 1;
}
};
$contentStart = $matches[2][1]+1;
$i = $contentStart;
$charCount = 0;
while($charCount < $length){
$charCount += $handleChar($subject[$i], $subject[$i+1]);
$i++;
}
$end = $i+3;
$endChars = substr($subject, $end-3, 3);
$substr = substr($subject, $contentStart, $end - $contentStart);
if($endChars != '\";'){
throw new Exception("Error parsing serialized string. Expected to find '\"' at offset $end, but found \"$endChars\" instead in the following string: $substr");
}
$rawLengthBefore = strlen($substr);
$substr = str_replace($find, $replace, $substr);
$length += strlen($substr) - $rawLengthBefore;
$subject = substr($subject, 0, $start) . "s:$length:\\\"" . $substr . substr($subject, $end);
$offset = $start+1;
}
return $subject;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment