Last active
July 17, 2023 20:28
-
-
Save mmcev106/e0c4078de57d37a6b3a81d84a366ffbb to your computer and use it in GitHub Desktop.
change-wordpress-url-in-database
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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