Exporting Ghost to Wordpress - json

I've been searching for a possibility to copy my Ghost Blog posts to Wordpress.
So far, I've managed to export all ghost data to a JSON file -- do you know any existing tool to convert it to something Wordpress can import?
If not, and I have to build something myself, would you recommend parsing the JSON to a WXR file or similar, or rather import into Wordpress' DB directly?
Thanks in advance!
K.

I migrated a Ghost blog to Wordpress by reading in the Ghost JSON export, massaging it a little and using wp_insert_post to import the posts.
This code should be placed in your theme's functions.php file - you can export your Ghost posts (GhostData.json) at http://example.com/ghost/debug/.
Note: example below doesn't import all data, but most key fields.
/**
* A function used to programmatically create a post in WordPress.
*
* http://tommcfarlin.com/programmatically-create-a-post-in-wordpress/
*
* #returns post ID if successful
* -1 if the post was never created
* -2 if a post with the same title exists
*/
function create_wp_post ($post_details) {
// Initialize the page ID to -1. This indicates no action has been taken.
$post_id = -1;
$post = get_page_by_title($post_details['title'], 'OBJECT', 'post');
// If the page title doesn't already exist, then insert the post
if (is_null($post)) {
// Set the post ID so that we know the post was created successfully
$post_id = wp_insert_post(
array(
'comment_status' => 'closed',
'ping_status' => 'closed',
'post_author' => $post_details['author'],
'post_content' => $post_details['content'],
'post_date' => $post_details['date'],
'post_date_gmt' => $post_details['date_gmt'],
'post_name' => $post_details['slug'],
'post_status' => $post_details['status'],
'post_title' => $post_details['title'],
'post_type' => 'post',
'tags_input' => $post_details['tags_input']
)
);
// Page title already exists, return error
} else {
$post_id = -2;
}
}
/**
* A function used to filter Ghost blog posts into Wordpress format.
*/
function filter_ghost_posts () {
$posts = json_decode(file_get_contents('GhostData.json'), true);
if ($posts) {
foreach ($posts['data']['posts'] as $post) {
$post_details = array(
'author' => $post['author_id'],
'date' => date('Y-m-d H:i:s', $post['published_at'] / 1000),
'date_gmt' => gmdate('Y-m-d H:i:s', $post['published_at'] / 1000),
'id' => $post['id'],
'content' => $post['html'],
'status' => $post['status'],
'slug' => $post['slug'],
'title' => $post['title']
);
// Status
// Fix discrepancy in naming between Ghost and Wordpress
if ($post_details['status'] === 'published') {
$post_details['status'] = 'publish';
}
// Tags
$post_tags_list = [];
foreach ($posts['data']['posts_tags'] as $post_tags) {
if ($post['id'] === $post_tags['post_id']) {
$post_tags_id = $post_tags['tag_id'];
array_push($post_tags_list, $posts['data']['tags'][$post_tags_id]['name']);
}
}
if (count($post_tags_list) > 0) {
$post_details['tags_input'] = implode(',', $post_tags_list);
}
$post_id = create_wp_post($post_details);
if ($post_id == -1 || $post_id == -2) {
// Error handling here
}
}
}
}
add_filter('after_setup_theme', 'filter_ghost_posts');

My recommendation would be to use Google Refine to import the JSON, and export a CSV, then use WP Ultimate CSV Importer Plugin to import it into your WordPress site. Hope this helps.

The question is quite old, but as of 2017 I still wasn't able to find a solution for Ghost > WP posts migration. What I did is:
Export JSON data, as described here - https://help.ghost.org/hc/en-us/articles/224112927-Import-Export-Data
Change a few JSON fields, like title, markdown... to post_title and post_content etc. (list of WP post fields is here - https://codex.wordpress.org/Class_Reference/WP_Post), and remove a few unneeded ones, like update_at or amp. What I left with was:
ID
post_title
post_name
post_content
post_status
meta_title
meta_description
post_author
post_date
Remove other JSON fields/structure, so there's only "posts": []
Use JSON to CSV converter, like this one - https://konklone.io/json/ and download CSV result file.
Now, when you have a CSV file, install WordPress CSV Importer plugin - https://wordpress.org/plugins/wp-ultimate-csv-importer/ (or similar)
Upload CSV file to the importer, check if fields are selected correctly.
Enjoy the imported posts on your WP dashboard ;)
Notice:
Ghost does not enable image exporting with other data (as of 31/01/2017).
You may wish to change "post_status" from "publish" to "pending", so posts are not published right away, before you edit them properly ;)

In case anyone is looking for this in future:
You could use the ghost-to-wp npm package. This will convert the JSON file you get as an export from Ghost into a WordPress-ready WXR file that can be directly imported into WordPress:
$ npm i -g ghost-to-wp
$ ghost-to-wp yourghostexport.json
As noted by #lomza there is still no way to nicely export images as part of the Ghost file so you will have to migrate images manually.
Disclosure: I am the author of ghost-to-wp.

I tried various importers and the best solution ended up just importing directly from RSS URL like https://myghostblog.com/rss/ with import-xml-feed plugin.
P.S. Keep pagination in mind. Your RSS link might show only first page of posts by default, and so for importing other pages you'll have to manually add /2/ /3/ to the URL and importing each separately. (At least, that's what I needed to do.)

Related

How to access /posts WordPress JSON REST API and filter by post_type?

I have a number of posts in the table wp_3_posts with the post_type "people". This post_type is created using the Admin Columns plugin.
How do I retrieve these?
The documentation for Posts offers filtering by categories or tags but post_type is neither of these.
https://developer.wordpress.org/rest-api/reference/posts/
Thank you :]
If I got your question the right way, you want to get posts of a custom post type with REST API.
You have to set show_in_rest and public in the arguments when you create the custom post type in wordpress.
add_action( 'init', 'my_cpt' );
function my_cpt() {
$args = array(
'public' => true,
'show_in_rest' => true,
'label' => 'My Custom Post'
);
register_post_type( 'mycustompost', $args );
}
More about this: https://developer.wordpress.org/rest-api/extending-the-rest-api/adding-rest-api-support-for-custom-content-types/
With that having set, you can get the posts of post type with using the right parameters in the url.
So if you just want to get posts, you can use:
https://yoursite.com/wp-json/wp/v2/mycustompost?per_page=10
I would suggest setting the per_page to have control if you are getting a lot of posts.
You can also have access to more data without additional HTTP requests using _embed
https://yoursite.com/wp-json/wp/v2/mycustompost?per_page=10&_embed=wp:term,wp:featuredmedia
For example, with this you get taxonomy terms and urls of different featured image sizes.
So you do not need to get all posts (and post types) of your website and then filter by post type, but just get posts of this post type instead. You can than do more filtering using global parameters:
https://developer.wordpress.org/rest-api/using-the-rest-api/global-parameters/
With VueJS (in my opinion better performance) this would look something like:
fetch("https://yoursite.com/wp-json/wp/v2/mycustompost?per_page=10")
.then(response => response.json())
.then((data => {
this.mycustompost = data;
}))
Or if using standard javascript something like:
let state = {
posts: [],
baseUrl: 'https://yoursite.com/wp-json/wp/v2/mycustompost',
perPage: '?per_page=10',
wpFetchHeaders: {
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Expose-Headers': 'x-wp-total'
}
}
}

Transactional Emails - Default Styling and Variables in Magento 1.9

I'm looking for 2 specific variables.
Wishlist - The var_message variable has some styling to it that im trying to edit.
Abandoned Carts - pulls on this extension URL : connector/email/basket/code/secret/quote_id/*****
And im unable to find the location of the file that is accessed by that URL or command.
Any assistance that can be provided would be greatly appreciated.
Also if someone could tell me how i might trace the locations of these things without "Just knowing" that would be grand too.
Kind Regards,
the correct variable name is message (not var_message)
variable message is populated in controller Mage_Wishlist_IndexController
inside method sendAction
here it is:
$emailModel = Mage::getModel('core/email_template');
$sharingCode = $wishlist->getSharingCode();
foreach ($emails as $email) {
$emailModel->sendTransactional(
Mage::getStoreConfig('wishlist/email/email_template'),
Mage::getStoreConfig('wishlist/email/email_identity'),
$email,
null,
array(
'customer' => $customer,
'salable' => $wishlist->isSalable() ? 'yes' : '',
'items' => $wishlistBlock,
'addAllLink' => Mage::getUrl('*/shared/allcart', array('code' => $sharingCode)),
'viewOnSiteLink' => Mage::getUrl('*/shared/index', array('code' => $sharingCode)),
'message' => $message
)
);
}
$wishlist->setShared(1);
$wishlist->save();
and the actual content of the message comes from a form input and gets fetched over here:
$message = nl2br(htmlspecialchars((string) $this->getRequest()->getPost('message')));
there is no actual styling or css assigned to it. In fact most of styles are defined inline in email templates

Laravel: Store error messages in database

Any one know how to send error messages to database in laravel which generate from app/exceptions/handler.php ?
I need to send what error massages generated in report() method to database.
If you are interested doing this manually, you can do something as following.
Step 1 -
Create a model to store errors that has a DB structure as following.
class Error extends Model
{
protected $fillable = ['user_id' , 'code' , 'file' , 'line' , 'message' , 'trace' ];
}
Step 2
Locate the App/Exceptions/Handler.php file, include Auth, and the Error model you created. and replace the report function with the following code.
public function report(Exception $exception) {
// Checks if a user has logged in to the system, so the error will be recorded with the user id
$userId = 0;
if (Auth::user()) {
$userId = Auth::user()->id;
}
$data = array(
'user_id' => $userId,
'code' => $exception->getCode(),
'file' => $exception->getFile(),
'line' => $exception->getLine(),
'message' => $exception->getMessage(),
'trace' => $exception->getTraceAsString(),
);
Error::create($data);
parent::report($exception);
}
(I am demonstrating this using laravel 5.6)
Because Laravel uses Monolog for handling logging it seems that writing Monolog Handler would be the cleanest way.
I was able to find something that exists already, please have a look at monolog-mysql package. I did not use it, so I don't know whether it works and if it works well, but it's definitely good starting point.

WP API Filter By Post Schema

Is it possible to return a list of posts based from the Wordpress Rest API v2 based on their schema:
For List of Schemas:
http://v2.wp-api.org/reference/posts/
I want to filter by sticky field, but the same would go for the rest of the fields.
So far I have:
/wp-json/wp/v2/posts?filter[sticky]=true
/wp-json/wp/v2/posts?filter[sticky]=1
Both return the same response as the standard endpoint:
/wp-json/wp/v2/posts
I have read other material such detailing how to sort by meta or custom taxonomies but I don't believe that's the same as this.
After going through the documentation and looking and posting issues on the WP-API Github repo, it's become clear that the filter[ignore_sticky_posts] should toggle the expected sorting behaviour, so that sticky posts are either always first (default) or ignored (by using filter[ignore_sticky_posts]=true).
However, there's currently a bug in WP API that makes the filter[ignore_sticky_posts] flag unusable.
The best way to fix it now would be to create you own custom endpoint to get the data or IDs of all the sticky posts in your database. By looking at the code discussed in this thread and in the WP-API documentation, I think adding the following code to your functions.php should do the trick:
// Sticky posts in REST - https://github.com/WP-API/WP-API/issues/2210
function get_sticky_posts() {
$posts = get_posts(
array(
'post__in' => get_option('sticky_posts')
)
);
if (empty($posts)) {
return null;
}
return $posts;
}
add_action( 'rest_api_init', function () {
register_rest_route( 'THEME_NAME/v1', '/sticky', array(
'methods' => 'GET',
'callback' => 'get_sticky_posts',
));
});
If you GET /wp-json/THEME_NAME/v1/sticky, you should get an array of all your sticky posts.
I hope this helps.
In addition to Laust Deleuran's answer (thanks Laust!), i've created an altered version of his script which allows you to use the embedded feature of the REST-api.
Although this might not be 'the cleanest' solution, it does allow you to fully use the wp-json's functionality.
function get_sticky_posts(WP_REST_Request $request) {
$request['filter'] = [
'post__in' => get_option('sticky_posts')
];
$response = new WP_REST_Posts_Controller('post');
$posts = $response->get_items($request);
return $posts;
}
add_action( 'rest_api_init', function () {
register_rest_route( 'THEME_NAME/v1', '/sticky', array(
'methods' => 'GET',
'callback' => 'get_sticky_posts',
));
});
This will output the sticky posts in the same schema as a normal /wp-json/wp/v2/posts query would respond.

Cakephp 3.0 download file

I asked a question before about file uploading. I managed to get it working and my next step is getting the file to be downloaded by a customer the files may be different formats from videos to PDFs.
I did read about media views, but they where cakephp 2.0. I have found that 2.0 seems to cause problems for me at least.
I can upload my files for uploading if it helps.
Nased on the link Alex posted, how would I call this function in my view this is the function based from the cakephp book link
public function downloadFile($id)
{
$file = $this->Attachments->getFile($id);
// a view.
$this->response->file(
$file['files/content'],
['download' => true]
);
return $this->response;
}
To get a link to that function (using the cakephp default routing) you would do this in your view:
echo $this->Html->link('Download File', ['controller' => 'Attachments', 'action' => 'download_file', $id]);
public function download(){
$file_path = WWW_ROOT.'uploads'.DS.'file_name.doc';
$this->response->file($file_path, array(
'download' => true,
'name' => 'file_name.ppt',
));
return $this->response;
}