Skip to content

Instantly share code, notes, and snippets.

@eexit
Last active August 29, 2015 14:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eexit/774b49a2d6f1e49430a2 to your computer and use it in GitHub Desktop.
Save eexit/774b49a2d6f1e49430a2 to your computer and use it in GitHub Desktop.
This file a Wordpress to Ghost image importer.
<?php
/*
This file a Wordpress to Ghost image importer.
Before you run this script, you must have done the following:
1. Import your blog content in Ghost with Markdown syntax (very important).
I used ExitWP (https://github.com/thomasf/exitwp) then
replaced all my Ghost data by its equivalent in Markdown
2. Export your Ghost database (yourblogurl/ghost/debug)
3. Configure this script (see variables below)
4. Run this script in console (needs PHP >= 5.3)
5. Re-generate a ghost.db file (backup your old one first) by
deleting it and restarting the app
6. Import your updated Ghost database (generated by this script)
7. Move all your pictures into your Ghost installation picture directory
*/
// Your WP domain + content path
$uploadPath = 'blog.eexit.net/wp-content/uploads/';
// Your exported Ghost DB path
$ghostFile = __DIR__ . '/GhostData.json';
// The path where you want the images to be downloaded (as a temp dir)
$downloadDir = __DIR__ . '/images/';
/*
----------------------------------------------------------------
DO NOT EDIT BELOW THIS LINE UNLESS YOU KNOW WHAT YOU ARE DOING
----------------------------------------------------------------
*/
ini_set('html_errors', false);
header('Content-Type: text/plain');
$updatedGhost = __DIR__ . '/GhostDataUpdated.json';
$sanitize = function($dirty) {
return preg_replace('/([\.\/])/', '\\\$1', $dirty);
};
$jsonValidator = function($jsonFilePath) {
if (!json_decode(file_get_contents($jsonFilePath))) {
$jsonErrors = array(
0 => 'JSON_ERROR_NONE',
1 => 'JSON_ERROR_DEPTH',
2 => 'JSON_ERROR_STATE_MISMATCH',
3 => 'JSON_ERROR_CTRL_CHAR',
4 => 'JSON_ERROR_SYNTAX',
5 => 'JSON_ERROR_UTF8'
);
throw new InvalidArgumentException(sprintf('JSON error (code %s) for file "%s": %s',
json_last_error(),
$jsonFilePath,
$jsonErrors[json_last_error()]
));
}
};
$pathBuilder = function ($dateVal, $stripDownloadDir = false) use ($downloadDir) {
$dateVal = explode('/', $dateVal);
$datetime = new DateTime();
$datetime->setDate($dateVal[0], $dateVal[1], 1);
if ($stripDownloadDir) {
return sprintf('%s%s',
$datetime->format(sprintf('Y%sM', DIRECTORY_SEPARATOR)),
DIRECTORY_SEPARATOR
);
}
return sprintf('%s%s%s',
$downloadDir,
$datetime->format(sprintf('Y%sM', DIRECTORY_SEPARATOR)),
DIRECTORY_SEPARATOR
);
};
try {
$ghostDb = file_get_contents($ghostFile);
if (!is_writable(__DIR__)) {
throw new InvalidArgumentException(sprintf(
'Cannot write current directory "%s". Please check permissions.',
__DIR__
));
}
if (!is_readable($ghostFile)) {
throw new InvalidArgumentException(sprintf(
'Cannot read Ghost DB file "%s". Please check permissions.',
$ghostFile
));
}
$jsonValidator($ghostFile);
if (!is_writable($downloadDir)) {
throw new InvalidArgumentException(sprintf(
'Download directory is not writtable: %s',
$downloadDir
));
}
$uploadPath = $sanitize($uploadPath);
$pattern = sprintf('/\(((https?:\/\/%s(\d{4}\/\d{2}))\/([^)]*))\)/', $uploadPath);
$count = preg_match_all($pattern, $ghostDb, $matches);
echo <<< EOT
+-+-+-+-+-+-+-+-+ +-+-+-+-+-+ +-+-+-+-+-+-+-+-+
|W|P|2|G|h|o|s|t| |i|m|a|g|e| |i|m|p|o|r|t|e|r|
+-+-+-+-+-+-+-+-+ +-+-+-+-+-+ +-+-+-+-+-+-+-+-+
There are $count URLs found:
EOT;
foreach ($matches[1] as $key => $url) {
$targetDir = $pathBuilder($matches[3][$key]);
$targetFile = sprintf('%s%s', $targetDir, basename($url));
$fileRelPath = sprintf('/content/images/%s',
$pathBuilder($matches[3][$key], true)
);
// Replaces Windows directory separator by slashes
$fileRelPath = str_replace(DIRECTORY_SEPARATOR, '/', $fileRelPath);
// Adds the file to the picture relative path
$fileRelPath .= $matches[4][$key];
if (!is_dir($targetDir)) {
if (!mkdir($targetDir, 0777, true)) {
throw new RuntimeException(sprintf(
'Unable to create directory: %s',
$targetDir
));
}
}
if (!$fileContent = file_get_contents($url)) {
throw new InvalidArgumentException(sprintf(
'Unable to download: %s', $url
));
}
if (!file_put_contents($targetFile, $fileContent)) {
throw new RuntimeException(sprintf(
'Unable to write the file "%s". Check your permissions!',
$targetFile
));
}
// Replaces the file URL by the relative path in the DB file
$ghostDb = str_replace($url, $fileRelPath, $ghostDb);
echo sprintf('[ %s/%s ] %s%s', ($key + 1), $count, $targetFile, PHP_EOL);
}
// Save the new DB
if (!file_put_contents($updatedGhost, $ghostDb)) {
throw new RuntimeException(sprintf(
'Unable to create the updated Ghost DB file "%s"',
$updatedGhost
));
}
// Validates the format of the new DB
$jsonValidator($updatedGhost);
echo <<< EOT
Importing done.
Your new Ghost database is: $updatedGhost.
All your pictures have been downloaded in: $downloadDir.
You must move them into your Ghost instance directory, beware of file permissions.
Example:
Ghost/content/images
└── 2014
├── Apr
└── May
Script written by Joris Berthelot <admin@eexit.net>
http://github.com/eexit
EOT;
} catch (Exception $e) {
echo <<< EOT
Oops! Something went wrong.
You should carefully read the following error and fix whatever it says.
Before relaunching the script, please consider:
- delete everyhing in: $downloadDir
- delete the new DB (if created): $updatedGhost
Error message: {$e->getMessage()}
EOT;
exit(1);
}
exit(0);
/*
Copyright (c) 2014 Joris Berthelot <admin@eexit.net>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment