Tumblr Importer - Version 0.8

Version Description

  • Fix callback handling for Tumblr OAuth. They no longer recognize the callback in the authorize URL, and instead expect a non-urlencoded callback parameter in the request-token call. This is not documented anywhere that I can find.
Download this release

Release Info

Developer Otto42
Plugin Icon 128x128 Tumblr Importer
Version 0.8
Comparing to
See all releases

Code changes from version 0.7 to 0.8

Files changed (2) hide show
  1. readme.txt +67 -64
  2. tumblr-importer.php +1033 -1032
readme.txt CHANGED
@@ -1,64 +1,67 @@
1
- === Tumblr Importer ===
2
- Contributors: wordpressdotorg, Otto42, dd32, westi, dllh
3
- Tags: tumblr, import
4
- Requires at least: 3.2
5
- Tested up to: 3.4
6
- Stable tag: 0.7
7
- License: GPLv2 or later
8
- License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
-
10
- == Description ==
11
-
12
- Imports a Tumblr blog into a WordPress blog.
13
-
14
- * Correctly handles post formats
15
- * Background importing: start it up, then come back later to see how far it's gotten
16
- * Duplicate checking, will not create duplicate imported posts
17
- * Imports posts, drafts, and pages
18
- * Media Side loading (for audio, video, and image posts)
19
-
20
- == Installation ==
21
-
22
- 1. Upload the files to the `/wp-content/plugins/tumblr-importer/` directory.
23
- 1. Activate the plugin through the 'Plugins' menu in WordPress.
24
- 1. Go to Tools->Import and use the new importer.
25
-
26
- == Upgrade Notice ==
27
-
28
- Version 0.7 fixes problems caused by Tumblr's removal of the old API, and now uses their new API.
29
-
30
- == Changelog ==
31
-
32
- = 0.7 =
33
- * Update to use new Tumblr API, many fixes and improvements.
34
-
35
- = 0.6 =
36
- * Significant improvements in the performance of the importer
37
- * Improves import of images from Tumblr - better choice of images sizes for theme display
38
- * Improved author selection logic on single author blogs
39
- * Auto refreshing to show import progress and give clearer feedback
40
- * Improves import videos from Tumble - enable auto-embedding for for content.
41
- * Block imports from Tumblr sites with mapped domains enabled because they don't work well - you have to temporarily disable the mapping.
42
-
43
- = 0.5 =
44
- * Fix edge cases for tumblr photos where tumblr isn't returning expected headers for filenames
45
-
46
- = 0.4 =
47
- * Map multi-image posts to Gallery post format
48
- * Import Tags
49
- * Import Media to server (Images, Audio, Custom uploaded Video's)
50
- * Set the date on Media imports for easier management
51
-
52
- = 0.3 =
53
- * Handle multi-image posts
54
- * Handle question/answer posts
55
- * Handle video posts somewhat better
56
- * Speedup (reduce importer delay from 3 minutes to 1 minute)
57
-
58
- = 0.2 =
59
- * The audio, video, and image formats no longer use the caption for the titles. Tumblr seems to facilitate putting all sorts of crazy stuff into the caption fields as part of their reblogging system. So instead, these types of posts will have no titles at all. Sorry, but Tumblr simply doesn't have any sort of title fields here to work with, and no data that can be used to "create" a title for them.
60
- * Minor debug error cleanup.
61
- * Sideloading now done on drafts and pages as well.
62
-
63
- = 0.1 =
64
- * First version, not meant to be used except for testing.
 
 
 
1
+ === Tumblr Importer ===
2
+ Contributors: wordpressdotorg, Otto42, dd32, westi, dllh
3
+ Tags: tumblr, import
4
+ Requires at least: 3.2
5
+ Tested up to: 4.1
6
+ Stable tag: 0.8
7
+ License: GPLv2 or later
8
+ License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
+
10
+ == Description ==
11
+
12
+ Imports a Tumblr blog into a WordPress blog.
13
+
14
+ * Correctly handles post formats
15
+ * Background importing: start it up, then come back later to see how far it's gotten
16
+ * Duplicate checking, will not create duplicate imported posts
17
+ * Imports posts, drafts, and pages
18
+ * Media Side loading (for audio, video, and image posts)
19
+
20
+ == Installation ==
21
+
22
+ 1. Upload the files to the `/wp-content/plugins/tumblr-importer/` directory.
23
+ 1. Activate the plugin through the 'Plugins' menu in WordPress.
24
+ 1. Go to Tools->Import and use the new importer.
25
+
26
+ == Upgrade Notice ==
27
+
28
+ Version 0.8 fixes a problem with authorization caused by Tumblr's undocumented change to their OAuth handling.
29
+
30
+ == Changelog ==
31
+
32
+ = 0.8 =
33
+ * Fix callback handling for Tumblr OAuth. They no longer recognize the callback in the authorize URL, and instead expect a non-urlencoded callback parameter in the request-token call. This is not documented anywhere that I can find.
34
+
35
+ = 0.7 =
36
+ * Update to use new Tumblr API, many fixes and improvements.
37
+
38
+ = 0.6 =
39
+ * Significant improvements in the performance of the importer
40
+ * Improves import of images from Tumblr - better choice of images sizes for theme display
41
+ * Improved author selection logic on single author blogs
42
+ * Auto refreshing to show import progress and give clearer feedback
43
+ * Improves import videos from Tumble - enable auto-embedding for for content.
44
+ * Block imports from Tumblr sites with mapped domains enabled because they don't work well - you have to temporarily disable the mapping.
45
+
46
+ = 0.5 =
47
+ * Fix edge cases for tumblr photos where tumblr isn't returning expected headers for filenames
48
+
49
+ = 0.4 =
50
+ * Map multi-image posts to Gallery post format
51
+ * Import Tags
52
+ * Import Media to server (Images, Audio, Custom uploaded Video's)
53
+ * Set the date on Media imports for easier management
54
+
55
+ = 0.3 =
56
+ * Handle multi-image posts
57
+ * Handle question/answer posts
58
+ * Handle video posts somewhat better
59
+ * Speedup (reduce importer delay from 3 minutes to 1 minute)
60
+
61
+ = 0.2 =
62
+ * The audio, video, and image formats no longer use the caption for the titles. Tumblr seems to facilitate putting all sorts of crazy stuff into the caption fields as part of their reblogging system. So instead, these types of posts will have no titles at all. Sorry, but Tumblr simply doesn't have any sort of title fields here to work with, and no data that can be used to "create" a title for them.
63
+ * Minor debug error cleanup.
64
+ * Sideloading now done on drafts and pages as well.
65
+
66
+ = 0.1 =
67
+ * First version, not meant to be used except for testing.
tumblr-importer.php CHANGED
@@ -1,1032 +1,1033 @@
1
- <?php
2
- /*
3
- Plugin Name: Tumblr Importer
4
- Plugin URI: http://wordpress.org/extend/plugins/tumblr-importer/
5
- Description: Import posts from a Tumblr blog.
6
- Author: wordpressdotorg
7
- Author URI: http://wordpress.org/
8
- Version: 0.7
9
- License: GPL v2 - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
10
- */
11
-
12
- if ( !defined('WP_LOAD_IMPORTERS') && !defined('DOING_CRON') )
13
- return;
14
-
15
- require_once ABSPATH . 'wp-admin/includes/import.php';
16
- require_once ABSPATH . 'wp-admin/includes/admin.php';
17
-
18
- require_once 'class-wp-importer-cron.php';
19
-
20
- /**
21
- * Tumblr Importer Initialisation routines
22
- *
23
- * @package WordPress
24
- * @subpackage Importer
25
- */
26
- function tumblr_importer_init() {
27
- global $tumblr_import;
28
- load_plugin_textdomain( 'tumblr-importer', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );
29
-
30
- $tumblr_import = new Tumblr_Import();
31
- register_importer('tumblr', __('Tumblr', 'tumblr-importer'), __('Import posts from a Tumblr blog.', 'tumblr-importer'), array ($tumblr_import, 'start'));
32
- if ( !defined('TUMBLR_MAX_IMPORT') )
33
- define ('TUMBLR_MAX_IMPORT', 20);
34
- }
35
- add_action( 'init', 'tumblr_importer_init' );
36
-
37
- /**
38
- * Tumblr Importer
39
- *
40
- * @package WordPress
41
- * @subpackage Importer
42
- */
43
- if ( class_exists( 'WP_Importer_Cron' ) ) {
44
- class Tumblr_Import extends WP_Importer_Cron {
45
-
46
- /**
47
- * Constructor
48
- */
49
- function __construct() {
50
- add_action( 'tumblr_importer_metadata', array( $this, 'tumblr_importer_metadata' ) );
51
- add_filter( 'tumblr_importer_format_post', array( $this, 'filter_format_post' ) );
52
- add_filter( 'tumblr_importer_get_consumer_key', array( $this, 'get_consumer_key' ) );
53
- add_filter( 'wp_insert_post_empty_content', array( $this, 'filter_allow_empty_content' ), 10, 2 );
54
- parent::__construct();
55
- }
56
-
57
- // Figures out what to do, then does it.
58
- function start() {
59
- if ( isset($_POST['restart']) )
60
- $this->restart();
61
-
62
- if ( !isset($this->error) ) $this->error = null;
63
-
64
- $this->consumerkey = defined ('TUMBLR_CONSUMER_KEY') ? TUMBLR_CONSUMER_KEY : ( !empty($_POST['consumerkey']) ? $_POST['consumerkey'] : $this->consumerkey );
65
- $this->secretkey = defined ('TUMBLR_SECRET_KEY') ? TUMBLR_SECRET_KEY : ( !empty($_POST['secretkey']) ? $_POST['secretkey'] : $this->secretkey );
66
-
67
- // if we have access tokens, verify that they work
68
- if ( !empty( $this->access_tokens ) ) {
69
- // TODO
70
- } else if ( isset( $_GET['oauth_verifier'] ) ) {
71
- $this->check_permissions();
72
- } else if ( !empty( $this->consumerkey ) && !empty( $this->secretkey ) ) {
73
- $this->check_credentials();
74
- }
75
- if ( isset( $_POST['blogurl'] ) ) {
76
- $this->start_blog_import();
77
- }
78
- if ( isset( $this->blogs ) ) {
79
- $this->show_blogs($this->error);
80
- } else {
81
- $this->greet($this->error);
82
- }
83
-
84
- unset ($this->error);
85
-
86
- if ( !isset($_POST['restart']) ) $saved = $this->save_vars();
87
-
88
- if ( $saved && !isset($_GET['noheader']) ) {
89
- ?>
90
- <p><?php _e('We have saved some information about your Tumblr account in your WordPress database. Clearing this information will allow you to start over. Restarting will not affect any posts you have already imported. If you attempt to re-import a blog, duplicate posts will be skipped.', 'tumblr-importer'); ?></p>
91
- <p><?php _e('Note: This will stop any import currently in progress.', 'tumblr-importer'); ?></p>
92
- <form method='post' action='?import=tumblr&amp;noheader=true'>
93
- <p class='submit' style='text-align:left;'>
94
- <input type='submit' class='button' value='<?php esc_attr_e('Clear account information', 'tumblr-importer'); ?>' name='restart' />
95
- </p>
96
- </form>
97
- <?php
98
- }
99
- }
100
-
101
- function greet($error=null) {
102
-
103
- if ( !empty( $error ) )
104
- echo "<div class='error'><p>{$error}</p></div>";
105
- ?>
106
-
107
- <div class='wrap'><?php echo screen_icon(); ?>
108
- <h2><?php _e('Import Tumblr', 'tumblr-importer'); ?></h2>
109
- <?php if ( empty($this->request_tokens) ) { ?>
110
- <p><?php _e('Howdy! This importer allows you to import posts from your Tumblr account into your WordPress site.', 'tumblr-importer'); ?></p>
111
- <p><?php _e("First, you will need to create an 'app' on Tumblr. The app provides a connection point between your blog and Tumblr's servers.", 'tumblr-importer'); ?></p>
112
-
113
- <p><?php _e('To create an app, visit this page:', 'tumblr-importer'); ?><a href="http://www.tumblr.com/oauth/apps">http://www.tumblr.com/oauth/apps</a></p>
114
- <ol>
115
- <li><?php _e('Click the large green "Register Application" button.','tumblr-importer'); ?></li>
116
- <li><?php _e('You need to fill in the "Application Name", "Application Website", and "Default Callback URL" fields. All the rest can be left blank.','tumblr-importer'); ?></li>
117
- <li><?php _e('For the "Application Website" and "Default Callback URL" fields, please put in this URL: ','tumblr-importer'); echo '<strong>'.home_url().'</strong>'; ?></li>
118
- <li><?php _e('Note: It is important that you put in that URL <em>exactly as given</em>.','tumblr-importer'); ?></li>
119
- </ol>
120
-
121
- <p><?php _e('After creating the application, copy and paste the "OAuth Consumer Key" and "Secret Key" into the given fields below.', 'tumblr-importer'); ?></p>
122
-
123
- <form action='?import=tumblr' method='post'>
124
- <table class="form-table">
125
- <tr>
126
- <th scope="row"><label for='consumerkey'><?php _e('OAuth Consumer Key:','tumblr-importer'); ?></label></label></th>
127
- <td><input type='text' class="regular-text" name='consumerkey' value='<?php if (isset($this->consumerkey)) echo esc_attr($this->consumerkey); ?>' /></td>
128
- </tr>
129
- <tr>
130
- <th scope="row"><label for='secretkey'><?php _e('Secret Key:','tumblr-importer'); ?></label></label></th>
131
- <td><input type='text' class="regular-text" name='secretkey' value='<?php if (isset($this->secretkey)) echo esc_attr($this->secretkey); ?>' /></td>
132
- </tr>
133
- </table>
134
- <p class='submit'>
135
- <input type='submit' class='button' value="<?php _e('Connect to Tumblr','tumblr-importer'); ?>" />
136
- </p>
137
- </form>
138
- </div>
139
- <?php } else {
140
- ?>
141
- <p><?php _e("Everything seems to be in order, so now you need to tell Tumblr to allow the plugin to access your account.", 'tumblr-importer'); ?></p>
142
- <p><?php _e("To do this, click the Authorize link below. You will be redirected back to this page when you've granted the permission.", 'tumblr-importer'); ?></p>
143
-
144
- <p><a href="<?php echo $this->authorize_url; ?>"><?php _e('Authorize the Application','tumblr-importer'); ?></a></p>
145
- <?php
146
- }
147
- }
148
-
149
- function check_credentials() {
150
- if ( !( $response = $this->oauth_get_request_token() ) )
151
- return;
152
-
153
- if ( is_wp_error( $response ) || 200 != wp_remote_retrieve_response_code( $response ) ) {
154
- $this->error = __('Tumblr returned an error: ', 'tumblr-importer') . wp_remote_retrieve_response_code( $response ) .' '. wp_remote_retrieve_body( $response );
155
- return;
156
- }
157
- // parse the body
158
- $this->request_tokens = array();
159
- wp_parse_str( wp_remote_retrieve_body( $response ), $this->request_tokens);
160
- $this->authorize_url = add_query_arg(array(
161
- 'oauth_token' => $this->request_tokens ['oauth_token'],
162
- 'oauth_callback' => urlencode( self_admin_url('admin.php?import=tumblr') ),
163
- ), 'http://www.tumblr.com/oauth/authorize');
164
-
165
- return;
166
- }
167
-
168
- function check_permissions() {
169
- $verifier = $_GET['oauth_verifier'];
170
- $token = $_GET['oauth_token'];
171
-
172
- // get the access_tokens
173
- $url = 'http://www.tumblr.com/oauth/access_token';
174
-
175
- $params = array('oauth_consumer_key' => $this->consumerkey,
176
- "oauth_nonce" => time().rand(),
177
- "oauth_timestamp" => time(),
178
- "oauth_token" => $this->request_tokens['oauth_token'],
179
- "oauth_signature_method" => "HMAC-SHA1",
180
- "oauth_verifier" => $verifier,
181
- "oauth_version" => "1.0",
182
- );
183
-
184
- $params['oauth_signature'] = $this->oauth_signature(array($this->secretkey,$this->request_tokens['oauth_token_secret']), 'GET', $url, $params);
185
-
186
- $url = add_query_arg( array_map('urlencode', $params), $url);
187
- $response = wp_remote_get( $url );
188
- unset($this->request_tokens);
189
- if ( is_wp_error( $response ) || 200 != wp_remote_retrieve_response_code( $response ) ) {
190
- $this->error = __('Tumblr returned an error: ', 'tumblr-importer') . wp_remote_retrieve_response_code( $response ) .' '. wp_remote_retrieve_body( $response );
191
- return;
192
- } else {
193
- $this->access_tokens = array();
194
- wp_parse_str( wp_remote_retrieve_body( $response ), $this->access_tokens);
195
- }
196
-
197
- // try to get the list of blogs on the account
198
-
199
- $blogs = $this->get_blogs();
200
- if ( is_wp_error ($blogs) ) {
201
- $this->error = $blogs->get_error_message();
202
- } else {
203
- $this->blogs = $blogs;
204
- }
205
- return;
206
- }
207
-
208
- function show_blogs($error=null) {
209
-
210
- if ( !empty( $error ) )
211
- echo "<div class='error'><p>{$error}</p></div>";
212
-
213
- $authors = get_users( array('who' => 'authors') );
214
- ?>
215
- <div class='wrap'><?php echo screen_icon(); ?>
216
- <h2><?php _e('Import Tumblr', 'tumblr-importer'); ?></h2>
217
- <p><?php _e('Please select the Tumblr blog you would like to import into your WordPress site and then click on the "Import this Blog" button to continue.'); ?></p>
218
- <p><?php _e('If your import gets stuck for a long time or you would like to import from a different Tumblr account instead then click on the "Clear account information" button below to reset the importer.','tumblr-importer'); ?></p>
219
- <?php if ( 1 < count( $authors ) ) : ?>
220
- <p><?php _e('As Tumblr does not expose the "author", even from multi-author blogs you will need to select which WordPress user will be listed as the author of the imported posts.','tumblr-importer'); ?></p>
221
- <?php endif; ?>
222
- <table class="widefat" cellspacing="0"><thead>
223
- <tr>
224
- <th><?php _e('Tumblr Blog','tumblr-importer'); ?></th>
225
- <th><?php _e('URL','tumblr-importer'); ?></th>
226
- <th><?php _e('Posts Imported','tumblr-importer'); ?></th>
227
- <th><?php _e('Drafts Imported','tumblr-importer'); ?></th>
228
- <!--<th><?php _e('Queued Imported','tumblr-importer'); ?></th>-->
229
- <th><?php _e('Pages Imported','tumblr-importer'); ?></th>
230
- <th><?php _e('Author','tumblr-importer'); ?></th>
231
- <th><?php _e('Action/Status','tumblr-importer'); ?></th>
232
- </tr></thead>
233
- <tbody>
234
- <?php
235
- $style = '';
236
- $custom_domains = false;
237
- foreach ($this->blogs as $blog) {
238
- $url = $blog['url'];
239
- $style = ( 'alternate' == $style ) ? '' : 'alternate';
240
- if ( !isset( $this->blog[$url] ) ) {
241
- $this->blog[$url]['posts_complete'] = 0;
242
- $this->blog[$url]['drafts_complete'] = 0;
243
- $this->blog[$url]['queued_complete'] = 0;
244
- $this->blog[$url]['pages_complete'] = 0;
245
- $this->blog[$url]['total_posts'] = $blog['posts'];
246
- $this->blog[$url]['total_drafts'] = $blog['drafts'];
247
- $this->blog[$url]['total_queued'] = $blog['queued'];
248
- $this->blog[$url]['name'] = $blog['name'];
249
- }
250
-
251
- if ( empty( $this->blog[$url]['progress'] ) ) {
252
- $submit = "<input type='submit' value='". __('Import this blog','tumblr-importer') ."' />";
253
- } else if ( $this->blog[$url]['progress'] == 'finish' ) {
254
- $submit = '<img src="' . admin_url( 'images/yes.png' ) . '" style="vertical-align: top; padding: 0 4px;" alt="' . __( 'Finished!', 'tumblr-importer' ) . '" title="' . __( 'Finished!', 'tumblr-importer' ) . '" /><span>' . __( 'Finished!', 'tumblr-importer' ) . '</span>';
255
- } else {
256
- $submit = '<img src="' . admin_url( 'images/loading.gif' ) . '" style="vertical-align: top; padding: 0 4px;" alt="' . __( 'In Progress', 'tumblr-importer' ) . '" title="' . __( 'In Progress', 'tumblr-importer' ) . '" /><span>' . __( 'In Progress', 'tumblr-importer' ) . '</span>';
257
- // Just a little js page reload to show progress if we're in the in-progress phase of the import.
258
- $submit .= "<script type='text/javascript'>setTimeout( 'window.location.href = window.location.href', 15000);</script>";
259
- }
260
-
261
- // Check to see if this url is a custom domain. The API doesn't play nicely with these
262
- // (intermittently returns 408 status), so make the user disable the custom domain
263
- // before importing.
264
- if ( !preg_match( '|tumblr.com/$|', $url ) ) {
265
- $submit = '<nobr><img src="' . admin_url( 'images/no.png' ) . '" style="vertical-align:top; padding: 0 4px;" alt="' . __( 'Tumblr Blogs with Custom Domains activated cannot be imported, please disable the custom domain first.', 'tumblr-importer' ) . '" title="' . __( 'Tumblr Blogs with Custom Domains activated cannot be imported, please disable the custom domain first.', 'tumblr-importer' ) . '" /><span style="cursor: pointer;" title="' . __( 'Tumblr Blogs with Custom Domains activated cannot be imported, please disable the custom domain first.' ) . '">' . __( 'Custom Domain', 'tumblr-importer' ) . '</nobr></span>';
266
- $custom_domains = true;
267
- }
268
-
269
- // Build an author selector / static name depending on number
270
- if ( 1 == count( $authors ) ) {
271
- $author_selection = "<input type='hidden' value='{$authors[0]->ID}' name='post_author' />{$authors[0]->display_name}";
272
- } else {
273
- $args = array('who' => 'authors', 'name' => 'post_author', 'echo' => false );
274
- if ( isset( $this->blog[$url]['post_author'] ) )
275
- $args['selected'] = $this->blog[$url]['post_author'];
276
- $author_selection = wp_dropdown_users( $args );
277
- }
278
- ?>
279
- <tr class="<?php echo $style; ?>">
280
- <form action='?import=tumblr' method='post'>
281
- <?php wp_nonce_field( 'tumblr-import' ); ?>
282
- <input type='hidden' name='blogurl' value='<?php echo esc_attr($blog['url']); ?>' />
283
-
284
- <td><?php echo esc_html($blog['title']); ?></td>
285
- <td><?php echo esc_html($blog['url']); ?></td>
286
- <td><?php echo $this->blog[$url]['posts_complete'] . ' / ' . $this->blog[$url]['total_posts']; ?></td>
287
- <td><?php echo $this->blog[$url]['drafts_complete'] . ' / ' . $this->blog[$url]['total_drafts']; ?></td>
288
- <!--<td><?php echo $this->blog[$url]['queued_complete']; ?></td>-->
289
- <td><?php echo $this->blog[$url]['pages_complete']; ?></td>
290
- <td><?php echo $author_selection ?></td>
291
- <td><?php echo $submit; ?></td>
292
- </form>
293
- </tr>
294
- <?php
295
- }
296
- ?>
297
- </tbody>
298
- </table>
299
- <?php if ( $custom_domains ) : ?>
300
- <p><strong>
301
- <?php _e( 'As one or more of your Tumblr blogs has a Custom Domain mapped to it. If you would like to import one of these sites you will need to temporarily remove the custom domain mapping and clear the account information from the importer to import. Once the import is completed you can re-enable the custom domain for your site.' ); ?>
302
- </strong></p>
303
- <?php endif; ?>
304
- <p><?php _e("Importing your Tumblr blog can take a while so the importing process happens in the background and you may not see immediate results here. Come back to this page later to check on the importer's progress.",'tumblr-importer'); ?></p>
305
- </div>
306
- <?php
307
- }
308
-
309
- function start_blog_import() {
310
- check_admin_referer( 'tumblr-import' );
311
- $url = $_POST['blogurl'];
312
-
313
- if ( !isset( $this->blog[$url] ) ) {
314
- $this->error = __('The specified blog cannot be found.', 'tumblr-importer');
315
- return;
316
- }
317
-
318
- if ( !empty($this->blog[$url]['progress']) ) {
319
- $this->error = __('This blog is currently being imported.', 'tumblr-importer');
320
- return;
321
- }
322
-
323
- $this->blog[$url]['progress'] = 'start';
324
- $this->blog[$url]['post_author'] = (int) $_POST['post_author'];
325
-
326
- $this->schedule_import_job( 'do_blog_import', array($url) );
327
- }
328
-
329
- function restart() {
330
- delete_option(get_class($this));
331
- wp_redirect('?import=tumblr');
332
- }
333
-
334
- function do_blog_import($url) {
335
-
336
- // default to the done state
337
- $done = true;
338
-
339
- $this->error=null;
340
- if ( !empty( $this->blog[$url]['progress'] ) ) {
341
- $done = false;
342
- do {
343
- switch ($this->blog[$url]['progress']) {
344
- case 'start':
345
- case 'posts':
346
- $this->do_posts_import($url);
347
- break;
348
- case 'drafts':
349
- $this->do_drafts_import($url);
350
- break;
351
- case 'queued':
352
- // TODO Tumblr's API is broken for queued posts
353
- $this->blog[$url]['progress'] = 'pages';
354
- //$this->do_queued_import($url);
355
- break;
356
- case 'pages':
357
- // TODO Tumblr's new API has no way to retrieve pages that I can find
358
- $this->blog[$url]['progress'] = 'finish';
359
- //$this->do_pages_import($url);
360
- break;
361
- case 'finish':
362
- default:
363
- $done = true;
364
- break;
365
- }
366
- $this->save_vars();
367
- } while ( empty($this->error) && !$done && $this->have_time() );
368
- }
369
-
370
- return $done;
371
- }
372
-
373
- function do_posts_import($url) {
374
- $start = $this->blog[$url]['posts_complete'];
375
- $total = $this->blog[$url]['total_posts'];
376
-
377
- // check for posts completion
378
- if ( $start >= $total ) {
379
- $this->blog[$url]['progress'] = 'drafts';
380
- return;
381
- }
382
-
383
- // get the already imported posts to prevent dupes
384
- $dupes = $this->get_imported_posts( 'tumblr', $this->blog[$url]['name'] );
385
-
386
- if ($this->blog[$url]['posts_complete'] + TUMBLR_MAX_IMPORT > $total) $count = $total - $start;
387
- else $count = TUMBLR_MAX_IMPORT;
388
-
389
- $imported_posts = $this->fetch_posts($url, $start, $count, $this->email, $this->password );
390
-
391
- if ( false === $imported_posts ) {
392
- $this->error = __('Problem communicating with Tumblr, retrying later','tumblr-importer');
393
- return;
394
- }
395
-
396
- if ( is_array($imported_posts) && !empty($imported_posts) ) {
397
- reset($imported_posts);
398
- $post = current($imported_posts);
399
- do {
400
- // skip dupes
401
- if ( !empty( $dupes[$post['tumblr_url']] ) ) {
402
- $this->blog[$url]['posts_complete']++;
403
- $this->save_vars();
404
- continue;
405
- }
406
-
407
- if ( isset( $post['private'] ) ) $post['post_status'] = 'private';
408
- else $post['post_status']='publish';
409
-
410
- $post['post_author'] = $this->blog[$url]['post_author'];
411
-
412
- do_action( 'tumblr_importing_post', $post );
413
- $id = wp_insert_post( $post );
414
-
415
- if ( !is_wp_error( $id ) ) {
416
- $post['ID'] = $id; // Allows for the media importing to wp_update_post()
417
- if ( isset( $post['format'] ) ) set_post_format($id, $post['format']);
418
-
419
- // @todo: Add basename of the permalink as a 404 redirect handler for when a custom domain has been brought accross
420
- add_post_meta( $id, 'tumblr_'.$this->blog[$url]['name'].'_permalink', $post['tumblr_url'] );
421
- add_post_meta( $id, 'tumblr_'.$this->blog[$url]['name'].'_id', $post['tumblr_id'] );
422
-
423
- $import_result = $this->handle_sideload($post);
424
-
425
- // Handle failed imports.. If empty content and failed to import media..
426
- if ( is_wp_error($import_result) ) {
427
- if ( empty($post['post_content']) ) {
428
- wp_delete_post($id, true);
429
- }
430
- }
431
- }
432
-
433
- $this->blog[$url]['posts_complete']++;
434
- $this->save_vars();
435
-
436
- } while ( false != ($post = next($imported_posts) ) && $this->have_time() );
437
- }
438
- }
439
-
440
- function get_draft_post_type( $post_type ) {
441
- return 'draft';
442
- }
443
-
444
- function do_drafts_import($url) {
445
- $start = $this->blog[$url]['drafts_complete'];
446
- $total = $this->blog[$url]['total_drafts'];
447
-
448
- // check for posts completion
449
- if ( $start >= $total ) {
450
- $this->blog[$url]['progress'] = 'queued';
451
- return;
452
- }
453
-
454
- // get the already imported posts to prevent dupes
455
- $dupes = $this->get_imported_posts( 'tumblr', $this->blog[$url]['name'] );
456
-
457
- if ($this->blog[$url]['posts_complete'] + TUMBLR_MAX_IMPORT > $total) $count = $total - $start;
458
- else $count = TUMBLR_MAX_IMPORT;
459
-
460
- add_filter( 'tumblr_post_type', array( $this, 'get_draft_post_type' ) );
461
- $imported_posts = $this->fetch_posts($url, $start, $count, $this->email, $this->password, 'draft' );
462
-
463
- if ( empty($imported_posts) ) {
464
- $this->error = __('Problem communicating with Tumblr, retrying later','tumblr-importer');
465
- return;
466
- }
467
-
468
- if ( is_array($imported_posts) && !empty($imported_posts) ) {
469
- reset($imported_posts);
470
- $post = current($imported_posts);
471
- do {
472
- // skip dupes
473
- if ( !empty( $dupes[$post['tumblr_url']] ) ) {
474
- $this->blog[$url]['drafts_complete']++;
475
- $this->save_vars();
476
- continue;
477
- }
478
-
479
- $post['post_status'] = 'draft';
480
- $post['post_author'] = $this->blog[$url]['post_author'];
481
-
482
- do_action( 'tumblr_importing_post', $post );
483
- $id = wp_insert_post( $post );
484
- if ( !is_wp_error( $id ) ) {
485
- $post['ID'] = $id;
486
- if ( isset( $post['format'] ) ) set_post_format($id, $post['format']);
487
-
488
- add_post_meta( $id, 'tumblr_'.$this->blog[$url]['name'].'_permalink', $post['tumblr_url'] );
489
- add_post_meta( $id, 'tumblr_'.$this->blog[$url]['name'].'_id', $post['tumblr_id'] );
490
-
491
- $this->handle_sideload($post);
492
- }
493
-
494
- $this->blog[$url]['drafts_complete']++;
495
- $this->save_vars();
496
- } while ( false != ($post = next($imported_posts) ) && $this->have_time() );
497
- }
498
- }
499
-
500
- function do_pages_import($url) {
501
- $start = $this->blog[$url]['pages_complete'];
502
-
503
- // get the already imported posts to prevent dupes
504
- $dupes = $this->get_imported_posts( 'tumblr', $this->blog[$url]['name'] );
505
-
506
- $imported_pages = $this->fetch_pages($url, $this->email, $this->password );
507
-
508
- if ( false === $imported_pages ) {
509
- $this->error = __('Problem communicating with Tumblr, retrying later','tumblr-importer');
510
- return;
511
- }
512
-
513
- if ( is_array($imported_pages) && !empty($imported_pages) ) {
514
- reset($imported_pages);
515
- $post = current($imported_pages);
516
- do {
517
- // skip dupes
518
- if ( !empty( $dupes[$post['tumblr_url']] ) ) {
519
- continue;
520
- }
521
-
522
- $post['post_type'] = 'page';
523
- $post['post_status'] = 'publish';
524
- $post['post_author'] = $this->blog[$url]['post_author'];
525
-
526
- $id = wp_insert_post( $post );
527
- if ( !is_wp_error( $id ) ) {
528
- add_post_meta( $id, 'tumblr_'.$this->blog[$url]['name'].'_permalink', $post['tumblr_url'] );
529
- $post['ID'] = $id;
530
- $this->handle_sideload($post);
531
- }
532
-
533
- $this->blog[$url]['pages_complete']++;
534
- $this->save_vars();
535
- } while ( false != ($post = next($imported_pages) ) );
536
- }
537
- $this->blog[$url]['progress'] = 'finish';
538
- }
539
-
540
- function handle_sideload_import($post, $source, $description = '', $filename = false) {
541
- // Make a HEAD request to get the filename:
542
- if ( empty($filename) ) {
543
- $head = wp_remote_request( $source, array('method' => 'HEAD') );
544
- if ( !empty($head['headers']['location']) ) {
545
- $source = $head['headers']['location'];
546
- $filename = preg_replace('!\?.*!', '', basename($source) ); // Strip off the Query vars
547
- }
548
- }
549
-
550
- // still empty? Darned inconsistent tumblr...
551
- if ( empty($filename) ) {
552
- $path = parse_url($source,PHP_URL_PATH);
553
- $filename = basename($path);
554
- }
555
- // Download file to temp location
556
- $tmp = download_url( $source );
557
- if ( is_wp_error($tmp) )
558
- return $tmp;
559
-
560
- $file_array['name'] = !empty($filename) ? $filename : basename($tmp);
561
- $file_array['tmp_name'] = $tmp;
562
- // do the validation and storage stuff
563
- $id = media_handle_sideload( $file_array, $post['ID'], $description, array( 'post_excerpt' => $description ) );
564
-
565
- if ( $id && ! is_wp_error($id) ) {
566
- // Update the date/time on the attachment to that of the Tumblr post.
567
- $attachment = get_post($id, ARRAY_A);
568
- foreach ( array('post_date', 'post_date_gmt', 'post_modified', 'post_modified_gmt') as $field ) {
569
- if ( isset($post[ $field]) )
570
- $attachment[ $field ] = $post[ $field ];
571
- }
572
- wp_update_post($attachment);
573
- }
574
-
575
- // If error storing permanently, unlink
576
- if ( is_wp_error($id) )
577
- @unlink($file_array['tmp_name']);
578
- return $id;
579
- }
580
-
581
- function handle_sideload($post) {
582
-
583
- if ( empty( $post['format'] ) )
584
- return; // Nothing to import.
585
-
586
- switch ( $post['format'] ) {
587
- case 'gallery':
588
- if ( !empty( $post['gallery'] ) ) {
589
- foreach ( $post['gallery'] as $i => $photo ) {
590
- $id = $this->handle_sideload_import( $post, (string)$photo['src'], (string)$photo['caption']);
591
- if ( is_wp_error($id) )
592
- return $id;
593
- }
594
- $post['post_content'] = "[gallery]\n" . $post['post_content'];
595
- $post = apply_filters( 'tumblr_importer_format_post', $post );
596
- do_action( 'tumblr_importer_metadata', $post );
597
- wp_update_post($post);
598
- break; // If we processed a gallery, break, otherwise let it fall through to the Image handler
599
- }
600
-
601
- case 'image':
602
- if ( isset( $post['media']['src'] ) ) {
603
- $id = $this->handle_sideload_import( $post, (string)$post['media']['src'], (string)$post['post_title']);
604
- if ( is_wp_error($id) )
605
- return $id;
606
-
607
- $link = !empty($post['media']['link']) ? $post['media']['link'] : null;
608
- // image_send_to_editor has a filter to wrap in a shortcode.
609
- $post_content = $post['post_content'];
610
- $post['post_content'] = get_image_send_to_editor($id, (string)$post['post_title'], (string)$post['post_title'], 'none', $link, true, 'full' );
611
- $post['post_content'] .= $post_content;
612
- $post['meta']['attribution'] = $link;
613
- $post = apply_filters( 'tumblr_importer_format_post', $post );
614
- do_action( 'tumblr_importer_metadata', $post );
615
- //$post['post_content'] .= "\n" . $post['post_content']; // the [caption] shortcode doesn't allow HTML, but this might have some extra markup
616
- wp_update_post($post);
617
- }
618
-
619
- break;
620
-
621
- case 'audio':
622
- // Handle Tumblr Hosted Audio
623
- if ( isset( $post['media']['audio'] ) ) {
624
- $id = $this->handle_sideload_import( $post, (string)$post['media']['audio'], $post['post_title'], (string)$post['media']['filename'] );
625
- if ( is_wp_error($id) )
626
- return $id;
627
- $post['post_content'] = wp_get_attachment_link($id) . "\n" . $post['post_content'];
628
- } else {
629
- // Try to work out a "source" link to display Tumblr-style.
630
- preg_match( '/(http[^ "<>\']+)/', $post['post_content'], $matches );
631
- if ( isset( $matches[1] ) ) {
632
- $url_parts = parse_url( $matches[1] );
633
- $post['meta']['attribution'] = $url_parts['scheme'] . "://" . $url_parts['host'] . "/";
634
- }
635
- }
636
- $post = apply_filters( 'tumblr_importer_format_post', $post );
637
- do_action( 'tumblr_importer_metadata', $post );
638
- wp_update_post($post);
639
- break;
640
-
641
- case 'video':
642
- // Handle Tumblr hosted video
643
- if ( isset( $post['media']['video'] ) ) {
644
- $id = $this->handle_sideload_import( $post, (string)$post['media']['video'], $post['post_title'], (string)$post['media']['filename'] );
645
- if ( is_wp_error($id) )
646
- return $id;
647
-
648
- // @TODO: Check/change this to embed the imported video.
649
- $link = wp_get_attachment_link($id) . "\n" . $post['post_content'];
650
- $post['post_content'] = $link;
651
- $post['meta']['attribution'] = $link;
652
- } else {
653
- // Try to work out a "source" link to mimic Tumblr's post formatting.
654
- preg_match( '/(http[^ "<>\']+)/', $post['post_content'], $matches );
655
- if ( isset( $matches[1] ) ) {
656
- $url_parts = parse_url( $matches[1] );
657
- $post['meta']['attribution'] = $url_parts['scheme'] . "://" . $url_parts['host'] . "/";
658
- }
659
- }
660
- $post = apply_filters( 'tumblr_importer_format_post', $post );
661
- do_action( 'tumblr_importer_metadata', $post );
662
- wp_update_post($post);
663
-
664
- // Else, Check to see if the url embedded is handled by oEmbed (or not)
665
- break;
666
- }
667
-
668
- return true; // all processed
669
- }
670
-
671
-
672
- /**
673
- * Get a request token from the OAuth endpoint (also serves as a test)
674
- *
675
- */
676
- function oauth_get_request_token() {
677
- if ( empty($this->consumerkey) || empty ($this->secretkey) )
678
- return false;
679
-
680
- $url = 'http://www.tumblr.com/oauth/request_token';
681
-
682
- $params = array('oauth_callback' => urlencode( self_admin_url('admin.php?import=tumblr') ),
683
- 'oauth_consumer_key' => $this->consumerkey,
684
- "oauth_version" => "1.0",
685
- "oauth_nonce" => time(),
686
- "oauth_timestamp" => time(),
687
- "oauth_signature_method" => "HMAC-SHA1",
688
- );
689
-
690
- $params['oauth_signature'] = $this->oauth_signature(array($this->secretkey,''), 'POST', $url, $params);
691
-
692
- $response = wp_remote_post( $url, array('body' => $params));
693
-
694
- return $response;
695
- }
696
-
697
- /**
698
- * Fetch a list of blogs for a user
699
- *
700
- * @param $email
701
- * @param $password
702
- * @returns array of blog info or a WP_Error
703
- */
704
- function get_blogs() {
705
- $url = 'http://api.tumblr.com/v2/user/info';
706
- $response = $this->oauth_get_request($url);
707
-
708
- switch ( $response->meta->status ) {
709
- case 403: // Bad Username / Password
710
- do_action( 'tumblr_importer_handle_error', 'get_blogs_403' );
711
- return new WP_Error('tumblr_error', __('Tumblr says that the the app is not authorized. Please check the settings and try to connect again.', 'tumblr-importer' ) );
712
- case 200: // OK
713
- break;
714
- default:
715
- $_error = sprintf( __( 'Tumblr replied with an error: %s', 'tumblr-importer' ), $response->meta->msg );
716
- do_action( 'tumblr_importer_handle_error', 'response_' . $response->meta->status );
717
- return new WP_Error('tumblr_error', $_error );
718
- }
719
-
720
- $blogs = array();
721
- foreach ( $response->response->user->blogs as $tblog ) {
722
- $blog = array();
723
- $blog['title'] = (string) $tblog->title;
724
- $blog['posts'] = (int) $tblog->posts;
725
- $blog['drafts'] = (int) $tblog->drafts;
726
- $blog['queued'] = (int) $tblog->queue;
727
- $blog['avatar'] = '';
728
- $blog['url'] = (string) $tblog->url;
729
- $blog['name'] = (string) $tblog->name;
730
-
731
- $blogs[] = $blog;
732
- }
733
- $this->blogs = $blogs;
734
- return $this->blogs;
735
- }
736
-
737
- function get_consumer_key() {
738
- return $this->consumerkey;
739
- }
740
-
741
- /**
742
- * Fetch a subset of posts from a tumblr blog
743
- *
744
- * @param $start index to start at
745
- * @param $count how many posts to get (max 50)
746
- * @param $state can be empty for normal posts, or "draft", "queue", or "submission" to get those posts
747
- * @returns false on error, array of posts on success
748
- */
749
- function fetch_posts($url, $start=0, $count = 50, $email = null, $password = null, $state = null ) {
750
- $url = parse_url( $url, PHP_URL_HOST );
751
- $post_type = apply_filters( 'tumblr_post_type', '' );
752
- $url = trailingslashit( "http://api.tumblr.com/v2/blog/$url/posts/$post_type" );
753
-
754
- do_action( 'tumblr_importer_pre_fetch_posts' );
755
-
756
- // These extra params hose up the auth if passed for oauth requests e.g. for drafts, so use them only for normal posts.
757
- if ( '' == $post_type ) {
758
- $params = array(
759
- 'offset' => $start,
760
- 'limit' => $count,
761
- 'api_key' => apply_filters( 'tumblr_importer_get_consumer_key', '' ),
762
- );
763
- $url = add_query_arg( $params, $url );
764
- }
765
-
766
- $response = $this->oauth_get_request($url);
767
-
768
- switch ( $response->meta->status ) {
769
- case 200: // OK
770
- break;
771
- default:
772
- $_error = sprintf( __( 'Tumblr replied with an error: %s', 'tumblr-importer' ), $response->meta->msg );
773
- do_action( 'tumblr_importer_handle_error', 'response_' . $response->meta->status );
774
- return new WP_Error('tumblr_error', $_error );
775
- }
776
-
777
- $posts = array();
778
- $tposts = $response->response->posts;
779
- foreach( $tposts as $tpost ) {
780
- $post = array();
781
- $post['tumblr_id'] = (string) $tpost->id;
782
- $post['tumblr_url'] = (string) $tpost->post_url;
783
- $post['post_date'] = date( 'Y-m-d H:i:s', strtotime ( (string) $tpost->date ) );
784
- $post['post_date_gmt'] = date( 'Y-m-d H:i:s', strtotime ( (string) $tpost->date ) );
785
- $post['post_name'] = (string) $tpost->slug;
786
- if ( 'private' == $tpost->state )
787
- $post['private'] = (string) $tpost->state;
788
- if ( isset( $tpost->tags ) ) {
789
- $post['tags_input'] = array();
790
- foreach ( $tpost->tags as $tag )
791
- $post['tags_input'][] = rtrim( (string) $tag, ','); // Strip trailing Commas off it too.
792
- }
793
-
794
- switch ( (string) $tpost->type ) {
795
- case 'photo':
796
- $post['format'] = 'image';
797
- $post['media']['src'] = (string) $tpost->photos[0]->original_size->url;
798
- $post['media']['link'] = '';//TODO: Find out what to use here.(string) $tpost->{'photo-link-url'};
799
- $post['media']['width'] = (string) $tpost->photos[0]->original_size->width;
800
- $post['media']['height'] = (string) $tpost->photos[0]->original_size->height;
801
- $post['post_content'] = (string) $tpost->caption;
802
- if ( ! empty( $tpost->photos ) ) {
803
- $post['format'] = 'gallery';
804
- foreach ( $tpost->photos as $photo ) {
805
- $post['gallery'][] = array (
806
- 'src' => $photo->original_size->url,
807
- 'width' => $photo->original_size->width,
808
- 'height' => $photo->original_size->height,
809
- 'caption' => $photo->caption,
810
- );
811
- }
812
- }
813
- break;
814
- case 'quote':
815
- $post['format'] = 'quote';
816
- $post['post_content'] = '<blockquote>' . (string) $tpost->text . '</blockquote>';
817
- $post['post_content'] .= "\n\n<div class='attribution'>" . (string) $tpost->source . '</div>';
818
- break;
819
- case 'link':
820
- $post['format'] = 'link';
821
- $linkurl = (string) $tpost->url;
822
- $linktext = (string) $tpost->title;
823
- $post['post_content'] = "<a href='$linkurl'>$linktext</a>";
824
- if ( ! empty( $tpost->description ) )
825
- $post['post_content'] .= '<div class="link_description">' . (string) $tpost->description . '</div>';
826
- $post['post_title'] = (string) $tpost->title;
827
- break;
828
- case 'chat':
829
- $post['format'] = 'chat';
830
- $post['post_title'] = (string) $tpost->title;
831
- $post['post_content'] = (string) $tpost->body;
832
- break;
833
- case 'audio':
834
- $post['format'] = 'audio';
835
- $post['media']['filename'] = basename( (string) $tpost->audio_url );
836
- // If no .mp3 extension, add one so that sideloading works.
837
- if ( ! preg_match( '/\.mp3$/', $post['media']['filename'] ) )
838
- $post['media']['filename'] .= '.mp3';
839
- $post['media']['audio'] = (string) $tpost->audio_url .'?plead=please-dont-download-this-or-our-lawyers-wont-let-us-host-audio';
840
- $post['post_content'] = (string) $tpost->player . "\n" . (string) $tpost->caption;
841
- break;
842
- case 'video':
843
- $post['format'] = 'video';
844
- $post['post_content'] = '';
845
-
846
- $video = array_shift( $tpost->player );
847
-
848
- if ( false !== strpos( (string) $video->embed_code, 'embed' ) ) {
849
- if ( preg_match_all('/<embed (.+?)>/', (string) $video->embed_code, $matches) ) {
850
- foreach ($matches[1] as $match) {
851
- foreach ( wp_kses_hair( $match, array( 'http' ) ) as $attr )
852
- $embed[ $attr['name'] ] = $attr['value'];
853
- }
854
-
855
- // special case for weird youtube vids
856
- $embed['src'] = preg_replace( '|http://www.youtube.com/v/([a-zA-Z0-9_]+).*|i', 'http://www.youtube.com/watch?v=$1', $embed['src'] );
857
-
858
- // TODO find other special cases, since tumblr is full of them
859
- $post['post_content'] = $embed['src'];
860
- }
861
-
862
- // Sometimes, video-source contains iframe markup.
863
- if ( preg_match( '/<iframe/', $video->embed_code ) ) {
864
- $embed['src'] = preg_replace( '|<iframe.*src="http://www.youtube.com/embed/([a-zA-Z0-9_\-]+)\??.*".*</iframe>|', 'http://www.youtube.com/watch?v=$1', $video->embed_code );
865
- $post['post_content'] = $embed['src'];
866
- }
867
- } elseif ( preg_match( '/<iframe.*vimeo/', $video->embed_code ) ) {
868
- $embed['src'] = preg_replace( '|<iframe.*src="(http://player.vimeo.com/video/([a-zA-Z0-9_\-]+))\??.*".*</iframe>.*|', 'http://vimeo.com/$2', $video->embed_code );
869
- $post['post_content'] = $embed['src'];
870
- } else {
871
- // @todo: See if the video source is going to be oEmbed'able before adding the flash player
872
- $post['post_content'] .= $video->embed_code;
873
- }
874
-
875
- $post['post_content'] .= "\n" . (string) $tpost->caption;
876
- break;
877
- case 'answer':
878
- // TODO: Include asking_name and asking_url values?
879
- $post['post_title'] = (string) $tpost->question;
880
- $post['post_content'] = (string) $tpost->answer;
881
- break;
882
- case 'regular':
883
- case 'text':
884
- default:
885
- $post['post_title'] = (string) $tpost->title;
886
- $post['post_content'] = (string) $tpost->body;
887
- break;
888
- }
889
- $posts[] = $post;
890
- }
891
-
892
- return $posts;
893
- }
894
-
895
- /**
896
- * Fetch the Pages from a tumblr blog
897
- *
898
- * @returns false on error, array of page contents on success
899
- */
900
- function fetch_pages($url, $email = null, $password = null) {
901
- $tumblrurl = trailingslashit($url).'api/pages';
902
- $params = array(
903
- 'email'=>$email,
904
- 'password'=>$password,
905
- );
906
- $options = array( 'body' => $params );
907
-
908
- // fetch the pages
909
- $out = wp_remote_post($tumblrurl,$options);
910
- if (wp_remote_retrieve_response_code($out) != 200) return false;
911
- $body = wp_remote_retrieve_body($out);
912
-
913
- // parse the XML into something useful
914
- $xml = simplexml_load_string($body);
915
-
916
- if (!isset($xml->pages)) return false;
917
-
918
- $tpages = $xml->pages;
919
- $pages = array();
920
- foreach($tpages->page as $tpage) {
921
- if ( !empty($tpage['title']) )
922
- $page['post_title'] = (string) $tpage['title'];
923
- else if (!empty($tpage['link-title']) )
924
- $page['post_title'] = (string) $tpage['link-title'];
925
- else
926
- $page['post_title'] = '';
927
- $page['post_name'] = str_replace( $url, '', (string) $tpage['url'] );
928
- $page['post_content'] = (string) $tpage;
929
- $page['tumblr_url'] = (string) $tpage['url'];
930
- $pages[] = $page;
931
- }
932
-
933
- return $pages;
934
- }
935
-
936
- function filter_format_post( $_post ) {
937
- if ( isset( $_post['meta']['attribution'] ) ) {
938
- $attribution = $_post['meta']['attribution'];
939
- if ( preg_match( '/^http[^ ]+$/', $_post['meta']['attribution'] ) )
940
- $attribution = sprintf( '<a href="%s">%s</a>', $_post['meta']['attribution'], $_post['meta']['attribution'] );
941
- $_post['post_content'] .= sprintf( '<div class="attribution">(<span>' . __( 'Source:', 'tumblr-importer' ) . '</span> %s)</div>', $attribution );
942
- }
943
-
944
- return $_post;
945
- }
946
-
947
- function tumblr_importer_metadata( $_post ) {
948
- if ( isset( $_post['meta'] ) ) {
949
- foreach ( $_post['meta'] as $key => $val ) {
950
- add_post_meta( $_post['ID'], 'tumblr_' . $key, $val );
951
- }
952
- }
953
- }
954
-
955
- /*
956
- * When galleries have no caption, the post_content field is empty, which
957
- * along with empty title and excerpt causes the post not to insert.
958
- * Here we override the default behavior.
959
- */
960
- function filter_allow_empty_content( $maybe_empty, $_post ) {
961
- if ( 'gallery' == $_post['format'] )
962
- return false;
963
-
964
- return $maybe_empty;
965
- }
966
-
967
-
968
- /**
969
- * OAuth Signature creation
970
- */
971
- function oauth_signature($secret, $method, $url, $params = array()) {
972
- uksort($params, 'strcmp');
973
- foreach ($params as $k => $v) {
974
- $pairs[] = $this->_urlencode_rfc3986($k).'='.$this->_urlencode_rfc3986($v);
975
- }
976
- $concatenatedParams = implode('&', $pairs);
977
- $baseString= $method."&". $this->_urlencode_rfc3986($url)."&".$this->_urlencode_rfc3986($concatenatedParams);
978
- if (!is_array($secret)) {
979
- $secret[0] = $secret;
980
- $secret[1] = '';
981
- }
982
- $secret = $this->_urlencode_rfc3986($secret[0])."&".$this->_urlencode_rfc3986($secret[1]);
983
- $oauth_signature = base64_encode(hash_hmac('sha1', $baseString, $secret, TRUE));
984
- return $oauth_signature;
985
- }
986
-
987
- /**
988
- * Helper function for OAuth Signature creation
989
- */
990
- function _urlencode_rfc3986($input)
991
- {
992
- if (is_array($input)) {
993
- return array_map(array($this, '_urlencode_rfc3986'), $input);
994
- } else if (is_scalar($input)) {
995
- return str_replace(array('+', '%7E'), array(' ', '~'), rawurlencode($input));
996
- } else {
997
- return '';
998
- }
999
- }
1000
-
1001
- /**
1002
- * Do a GET request with the access tokens
1003
- */
1004
- function oauth_get_request($url) {
1005
- if ( empty( $this->access_tokens ) )
1006
- return false;
1007
-
1008
- $params = array('oauth_consumer_key' => $this->get_consumer_key(),
1009
- "oauth_nonce" => time(),
1010
- "oauth_timestamp" => time(),
1011
- "oauth_token" => $this->access_tokens['oauth_token'],
1012
- "oauth_signature_method" => "HMAC-SHA1",
1013
- "oauth_version" => "1.0",
1014
- );
1015
-
1016
- $params['oauth_signature'] = $this->oauth_signature(array($this->secretkey,$this->access_tokens['oauth_token_secret']), 'GET', $url, $params);
1017
-
1018
- $url = add_query_arg( array_map('urlencode', $params), $url);
1019
-
1020
- $response = wp_remote_get( $url );
1021
-
1022
- if ( is_wp_error( $response ) || 200 != wp_remote_retrieve_response_code( $response ) ) {
1023
- return false;
1024
- } else {
1025
- $body = wp_remote_retrieve_body( $response );
1026
- return json_decode($body);
1027
- }
1028
- }
1029
-
1030
-
1031
- }
1032
- }
 
1
+ <?php
2
+ /*
3
+ Plugin Name: Tumblr Importer
4
+ Plugin URI: http://wordpress.org/extend/plugins/tumblr-importer/
5
+ Description: Import posts from a Tumblr blog.
6
+ Author: wordpressdotorg
7
+ Author URI: http://wordpress.org/
8
+ Version: 0.8
9
+ License: GPL v2 - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
10
+ Text Domain: tumblr-importer
11
+ Domain Path: /languages
12
+ */
13
+
14
+ if ( !defined('WP_LOAD_IMPORTERS') && !defined('DOING_CRON') )
15
+ return;
16
+
17
+ require_once ABSPATH . 'wp-admin/includes/import.php';
18
+ require_once ABSPATH . 'wp-admin/includes/admin.php';
19
+
20
+ require_once 'class-wp-importer-cron.php';
21
+
22
+ /**
23
+ * Tumblr Importer Initialisation routines
24
+ *
25
+ * @package WordPress
26
+ * @subpackage Importer
27
+ */
28
+ function tumblr_importer_init() {
29
+ global $tumblr_import;
30
+ load_plugin_textdomain( 'tumblr-importer', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );
31
+
32
+ $tumblr_import = new Tumblr_Import();
33
+ register_importer('tumblr', __('Tumblr', 'tumblr-importer'), __('Import posts from a Tumblr blog.', 'tumblr-importer'), array ($tumblr_import, 'start'));
34
+ if ( !defined('TUMBLR_MAX_IMPORT') )
35
+ define ('TUMBLR_MAX_IMPORT', 20);
36
+ }
37
+ add_action( 'init', 'tumblr_importer_init' );
38
+
39
+ /**
40
+ * Tumblr Importer
41
+ *
42
+ * @package WordPress
43
+ * @subpackage Importer
44
+ */
45
+ if ( class_exists( 'WP_Importer_Cron' ) ) {
46
+ class Tumblr_Import extends WP_Importer_Cron {
47
+
48
+ /**
49
+ * Constructor
50
+ */
51
+ function __construct() {
52
+ add_action( 'tumblr_importer_metadata', array( $this, 'tumblr_importer_metadata' ) );
53
+ add_filter( 'tumblr_importer_format_post', array( $this, 'filter_format_post' ) );
54
+ add_filter( 'tumblr_importer_get_consumer_key', array( $this, 'get_consumer_key' ) );
55
+ add_filter( 'wp_insert_post_empty_content', array( $this, 'filter_allow_empty_content' ), 10, 2 );
56
+ parent::__construct();
57
+ }
58
+
59
+ // Figures out what to do, then does it.
60
+ function start() {
61
+ if ( isset($_POST['restart']) )
62
+ $this->restart();
63
+
64
+ if ( !isset($this->error) ) $this->error = null;
65
+
66
+ @ $this->consumerkey = defined ('TUMBLR_CONSUMER_KEY') ? TUMBLR_CONSUMER_KEY : ( !empty($_POST['consumerkey']) ? $_POST['consumerkey'] : $this->consumerkey );
67
+ @ $this->secretkey = defined ('TUMBLR_SECRET_KEY') ? TUMBLR_SECRET_KEY : ( !empty($_POST['secretkey']) ? $_POST['secretkey'] : $this->secretkey );
68
+
69
+ // if we have access tokens, verify that they work
70
+ if ( !empty( $this->access_tokens ) ) {
71
+ // TODO
72
+ } else if ( isset( $_GET['oauth_verifier'] ) ) {
73
+ $this->check_permissions();
74
+ } else if ( !empty( $this->consumerkey ) && !empty( $this->secretkey ) ) {
75
+ $this->check_credentials();
76
+ }
77
+ if ( isset( $_POST['blogurl'] ) ) {
78
+ $this->start_blog_import();
79
+ }
80
+ if ( isset( $this->blogs ) ) {
81
+ $this->show_blogs($this->error);
82
+ } else {
83
+ $this->greet($this->error);
84
+ }
85
+
86
+ unset ($this->error);
87
+
88
+ if ( !isset($_POST['restart']) ) $saved = $this->save_vars();
89
+
90
+ if ( $saved && !isset($_GET['noheader']) ) {
91
+ ?>
92
+ <p><?php _e('We have saved some information about your Tumblr account in your WordPress database. Clearing this information will allow you to start over. Restarting will not affect any posts you have already imported. If you attempt to re-import a blog, duplicate posts will be skipped.', 'tumblr-importer'); ?></p>
93
+ <p><?php _e('Note: This will stop any import currently in progress.', 'tumblr-importer'); ?></p>
94
+ <form method='post' action='?import=tumblr&amp;noheader=true'>
95
+ <p class='submit' style='text-align:left;'>
96
+ <input type='submit' class='button' value='<?php esc_attr_e('Clear account information', 'tumblr-importer'); ?>' name='restart' />
97
+ </p>
98
+ </form>
99
+ <?php
100
+ }
101
+ }
102
+
103
+ function greet($error=null) {
104
+
105
+ if ( !empty( $error ) )
106
+ echo "<div class='error'><p>{$error}</p></div>";
107
+ ?>
108
+
109
+ <div class='wrap'><?php echo screen_icon(); ?>
110
+ <h2><?php _e('Import Tumblr', 'tumblr-importer'); ?></h2>
111
+ <?php if ( empty($this->request_tokens) ) { ?>
112
+ <p><?php _e('Howdy! This importer allows you to import posts from your Tumblr account into your WordPress site.', 'tumblr-importer'); ?></p>
113
+ <p><?php _e("First, you will need to create an 'app' on Tumblr. The app provides a connection point between your blog and Tumblr's servers.", 'tumblr-importer'); ?></p>
114
+
115
+ <p><?php _e('To create an app, visit this page:', 'tumblr-importer'); ?><a href="https://www.tumblr.com/oauth/apps">https://www.tumblr.com/oauth/apps</a></p>
116
+ <ol>
117
+ <li><?php _e('Click the large green "Register Application" button.','tumblr-importer'); ?></li>
118
+ <li><?php _e('You need to fill in the "Application Name", "Application Website", and "Default Callback URL" fields. All the rest can be left blank.','tumblr-importer'); ?></li>
119
+ <li><?php _e('For the "Application Website" and "Default Callback URL" fields, please put in this URL: ','tumblr-importer'); echo '<strong>'.home_url().'</strong>'; ?></li>
120
+ <li><?php _e('Note: It is important that you put in that URL <em>exactly as given</em>.','tumblr-importer'); ?></li>
121
+ </ol>
122
+
123
+ <p><?php _e('After creating the application, copy and paste the "OAuth Consumer Key" and "Secret Key" into the given fields below.', 'tumblr-importer'); ?></p>
124
+
125
+ <form action='?import=tumblr' method='post'>
126
+ <table class="form-table">
127
+ <tr>
128
+ <th scope="row"><label for='consumerkey'><?php _e('OAuth Consumer Key:','tumblr-importer'); ?></label></label></th>
129
+ <td><input type='text' class="regular-text" name='consumerkey' value='<?php if (isset($this->consumerkey)) echo esc_attr($this->consumerkey); ?>' /></td>
130
+ </tr>
131
+ <tr>
132
+ <th scope="row"><label for='secretkey'><?php _e('Secret Key:','tumblr-importer'); ?></label></label></th>
133
+ <td><input type='text' class="regular-text" name='secretkey' value='<?php if (isset($this->secretkey)) echo esc_attr($this->secretkey); ?>' /></td>
134
+ </tr>
135
+ </table>
136
+ <p class='submit'>
137
+ <input type='submit' class='button' value="<?php _e('Connect to Tumblr','tumblr-importer'); ?>" />
138
+ </p>
139
+ </form>
140
+ </div>
141
+ <?php } else {
142
+ ?>
143
+ <p><?php _e("Everything seems to be in order, so now you need to tell Tumblr to allow the plugin to access your account.", 'tumblr-importer'); ?></p>
144
+ <p><?php _e("To do this, click the Authorize link below. You will be redirected back to this page when you've granted the permission.", 'tumblr-importer'); ?></p>
145
+
146
+ <p><a href="<?php echo $this->authorize_url; ?>"><?php _e('Authorize the Application','tumblr-importer'); ?></a></p>
147
+ <?php
148
+ }
149
+ }
150
+
151
+ function check_credentials() {
152
+ if ( !( $response = $this->oauth_get_request_token() ) )
153
+ return;
154
+
155
+ if ( is_wp_error( $response ) || 200 != wp_remote_retrieve_response_code( $response ) ) {
156
+ $this->error = __('Tumblr returned an error: ', 'tumblr-importer') . wp_remote_retrieve_response_code( $response ) .' '. wp_remote_retrieve_body( $response );
157
+ return;
158
+ }
159
+ // parse the body
160
+ $this->request_tokens = array();
161
+ wp_parse_str( wp_remote_retrieve_body( $response ), $this->request_tokens);
162
+ $this->authorize_url = add_query_arg(array(
163
+ 'oauth_token' => $this->request_tokens ['oauth_token'],
164
+ ), 'https://www.tumblr.com/oauth/authorize');
165
+
166
+ return;
167
+ }
168
+
169
+ function check_permissions() {
170
+ $verifier = $_GET['oauth_verifier'];
171
+ $token = $_GET['oauth_token'];
172
+
173
+ // get the access_tokens
174
+ $url = 'https://www.tumblr.com/oauth/access_token';
175
+
176
+ $params = array('oauth_consumer_key' => $this->consumerkey,
177
+ "oauth_nonce" => time().rand(),
178
+ "oauth_timestamp" => time(),
179
+ "oauth_token" => $this->request_tokens['oauth_token'],
180
+ "oauth_signature_method" => "HMAC-SHA1",
181
+ "oauth_verifier" => $verifier,
182
+ "oauth_version" => "1.0",
183
+ );
184
+
185
+ $params['oauth_signature'] = $this->oauth_signature(array($this->secretkey,$this->request_tokens['oauth_token_secret']), 'GET', $url, $params);
186
+
187
+ $url = add_query_arg( array_map('urlencode', $params), $url);
188
+ $response = wp_remote_get( $url );
189
+ unset($this->request_tokens);
190
+ if ( is_wp_error( $response ) || 200 != wp_remote_retrieve_response_code( $response ) ) {
191
+ $this->error = __('Tumblr returned an error: ', 'tumblr-importer') . wp_remote_retrieve_response_code( $response ) .' '. wp_remote_retrieve_body( $response );
192
+ return;
193
+ } else {
194
+ $this->access_tokens = array();
195
+ wp_parse_str( wp_remote_retrieve_body( $response ), $this->access_tokens);
196
+ }
197
+
198
+ // try to get the list of blogs on the account
199
+
200
+ $blogs = $this->get_blogs();
201
+ if ( is_wp_error ($blogs) ) {
202
+ $this->error = $blogs->get_error_message();
203
+ } else {
204
+ $this->blogs = $blogs;
205
+ }
206
+ return;
207
+ }
208
+
209
+ function show_blogs($error=null) {
210
+
211
+ if ( !empty( $error ) )
212
+ echo "<div class='error'><p>{$error}</p></div>";
213
+
214
+ $authors = get_users( array('who' => 'authors') );
215
+ ?>
216
+ <div class='wrap'><?php echo screen_icon(); ?>
217
+ <h2><?php _e('Import Tumblr', 'tumblr-importer'); ?></h2>
218
+ <p><?php _e('Please select the Tumblr blog you would like to import into your WordPress site and then click on the "Import this Blog" button to continue.'); ?></p>
219
+ <p><?php _e('If your import gets stuck for a long time or you would like to import from a different Tumblr account instead then click on the "Clear account information" button below to reset the importer.','tumblr-importer'); ?></p>
220
+ <?php if ( 1 < count( $authors ) ) : ?>
221
+ <p><?php _e('As Tumblr does not expose the "author", even from multi-author blogs you will need to select which WordPress user will be listed as the author of the imported posts.','tumblr-importer'); ?></p>
222
+ <?php endif; ?>
223
+ <table class="widefat" cellspacing="0"><thead>
224
+ <tr>
225
+ <th><?php _e('Tumblr Blog','tumblr-importer'); ?></th>
226
+ <th><?php _e('URL','tumblr-importer'); ?></th>
227
+ <th><?php _e('Posts Imported','tumblr-importer'); ?></th>
228
+ <th><?php _e('Drafts Imported','tumblr-importer'); ?></th>
229
+ <!--<th><?php _e('Queued Imported','tumblr-importer'); ?></th>-->
230
+ <th><?php _e('Pages Imported','tumblr-importer'); ?></th>
231
+ <th><?php _e('Author','tumblr-importer'); ?></th>
232
+ <th><?php _e('Action/Status','tumblr-importer'); ?></th>
233
+ </tr></thead>
234
+ <tbody>
235
+ <?php
236
+ $style = '';
237
+ $custom_domains = false;
238
+ foreach ($this->blogs as $blog) {
239
+ $url = $blog['url'];
240
+ $style = ( 'alternate' == $style ) ? '' : 'alternate';
241
+ if ( !isset( $this->blog[$url] ) ) {
242
+ $this->blog[$url]['posts_complete'] = 0;
243
+ $this->blog[$url]['drafts_complete'] = 0;
244
+ $this->blog[$url]['queued_complete'] = 0;
245
+ $this->blog[$url]['pages_complete'] = 0;
246
+ $this->blog[$url]['total_posts'] = $blog['posts'];
247
+ $this->blog[$url]['total_drafts'] = $blog['drafts'];
248
+ $this->blog[$url]['total_queued'] = $blog['queued'];
249
+ $this->blog[$url]['name'] = $blog['name'];
250
+ }
251
+
252
+ if ( empty( $this->blog[$url]['progress'] ) ) {
253
+ $submit = "<input type='submit' value='". __('Import this blog','tumblr-importer') ."' />";
254
+ } else if ( $this->blog[$url]['progress'] == 'finish' ) {
255
+ $submit = '<img src="' . admin_url( 'images/yes.png' ) . '" style="vertical-align: top; padding: 0 4px;" alt="' . __( 'Finished!', 'tumblr-importer' ) . '" title="' . __( 'Finished!', 'tumblr-importer' ) . '" /><span>' . __( 'Finished!', 'tumblr-importer' ) . '</span>';
256
+ } else {
257
+ $submit = '<img src="' . admin_url( 'images/loading.gif' ) . '" style="vertical-align: top; padding: 0 4px;" alt="' . __( 'In Progress', 'tumblr-importer' ) . '" title="' . __( 'In Progress', 'tumblr-importer' ) . '" /><span>' . __( 'In Progress', 'tumblr-importer' ) . '</span>';
258
+ // Just a little js page reload to show progress if we're in the in-progress phase of the import.
259
+ $submit .= "<script type='text/javascript'>setTimeout( 'window.location.href = window.location.href', 15000);</script>";
260
+ }
261
+
262
+ // Check to see if this url is a custom domain. The API doesn't play nicely with these
263
+ // (intermittently returns 408 status), so make the user disable the custom domain
264
+ // before importing.
265
+ if ( !preg_match( '|tumblr.com/$|', $url ) ) {
266
+ $submit = '<nobr><img src="' . admin_url( 'images/no.png' ) . '" style="vertical-align:top; padding: 0 4px;" alt="' . __( 'Tumblr Blogs with Custom Domains activated cannot be imported, please disable the custom domain first.', 'tumblr-importer' ) . '" title="' . __( 'Tumblr Blogs with Custom Domains activated cannot be imported, please disable the custom domain first.', 'tumblr-importer' ) . '" /><span style="cursor: pointer;" title="' . __( 'Tumblr Blogs with Custom Domains activated cannot be imported, please disable the custom domain first.' ) . '">' . __( 'Custom Domain', 'tumblr-importer' ) . '</nobr></span>';
267
+ $custom_domains = true;
268
+ }
269
+
270
+ // Build an author selector / static name depending on number
271
+ if ( 1 == count( $authors ) ) {
272
+ $author_selection = "<input type='hidden' value='{$authors[0]->ID}' name='post_author' />{$authors[0]->display_name}";
273
+ } else {
274
+ $args = array('who' => 'authors', 'name' => 'post_author', 'echo' => false );
275
+ if ( isset( $this->blog[$url]['post_author'] ) )
276
+ $args['selected'] = $this->blog[$url]['post_author'];
277
+ $author_selection = wp_dropdown_users( $args );
278
+ }
279
+ ?>
280
+ <tr class="<?php echo $style; ?>">
281
+ <form action='?import=tumblr' method='post'>
282
+ <?php wp_nonce_field( 'tumblr-import' ); ?>
283
+ <input type='hidden' name='blogurl' value='<?php echo esc_attr($blog['url']); ?>' />
284
+
285
+ <td><?php echo esc_html($blog['title']); ?></td>
286
+ <td><?php echo esc_html($blog['url']); ?></td>
287
+ <td><?php echo $this->blog[$url]['posts_complete'] . ' / ' . $this->blog[$url]['total_posts']; ?></td>
288
+ <td><?php echo $this->blog[$url]['drafts_complete'] . ' / ' . $this->blog[$url]['total_drafts']; ?></td>
289
+ <!--<td><?php echo $this->blog[$url]['queued_complete']; ?></td>-->
290
+ <td><?php echo $this->blog[$url]['pages_complete']; ?></td>
291
+ <td><?php echo $author_selection ?></td>
292
+ <td><?php echo $submit; ?></td>
293
+ </form>
294
+ </tr>
295
+ <?php
296
+ }
297
+ ?>
298
+ </tbody>
299
+ </table>
300
+ <?php if ( $custom_domains ) : ?>
301
+ <p><strong>
302
+ <?php _e( 'As one or more of your Tumblr blogs has a Custom Domain mapped to it. If you would like to import one of these sites you will need to temporarily remove the custom domain mapping and clear the account information from the importer to import. Once the import is completed you can re-enable the custom domain for your site.' ); ?>
303
+ </strong></p>
304
+ <?php endif; ?>
305
+ <p><?php _e("Importing your Tumblr blog can take a while so the importing process happens in the background and you may not see immediate results here. Come back to this page later to check on the importer's progress.",'tumblr-importer'); ?></p>
306
+ </div>
307
+ <?php
308
+ }
309
+
310
+ function start_blog_import() {
311
+ check_admin_referer( 'tumblr-import' );
312
+ $url = $_POST['blogurl'];
313
+
314
+ if ( !isset( $this->blog[$url] ) ) {
315
+ $this->error = __('The specified blog cannot be found.', 'tumblr-importer');
316
+ return;
317
+ }
318
+
319
+ if ( !empty($this->blog[$url]['progress']) ) {
320
+ $this->error = __('This blog is currently being imported.', 'tumblr-importer');
321
+ return;
322
+ }
323
+
324
+ $this->blog[$url]['progress'] = 'start';
325
+ $this->blog[$url]['post_author'] = (int) $_POST['post_author'];
326
+
327
+ $this->schedule_import_job( 'do_blog_import', array($url) );
328
+ }
329
+
330
+ function restart() {
331
+ delete_option(get_class($this));
332
+ wp_redirect('?import=tumblr');
333
+ }
334
+
335
+ function do_blog_import($url) {
336
+
337
+ // default to the done state
338
+ $done = true;
339
+
340
+ $this->error=null;
341
+ if ( !empty( $this->blog[$url]['progress'] ) ) {
342
+ $done = false;
343
+ do {
344
+ switch ($this->blog[$url]['progress']) {
345
+ case 'start':
346
+ case 'posts':
347
+ $this->do_posts_import($url);
348
+ break;
349
+ case 'drafts':
350
+ $this->do_drafts_import($url);
351
+ break;
352
+ case 'queued':
353
+ // TODO Tumblr's API is broken for queued posts
354
+ $this->blog[$url]['progress'] = 'pages';
355
+ //$this->do_queued_import($url);
356
+ break;
357
+ case 'pages':
358
+ // TODO Tumblr's new API has no way to retrieve pages that I can find
359
+ $this->blog[$url]['progress'] = 'finish';
360
+ //$this->do_pages_import($url);
361
+ break;
362
+ case 'finish':
363
+ default:
364
+ $done = true;
365
+ break;
366
+ }
367
+ $this->save_vars();
368
+ } while ( empty($this->error) && !$done && $this->have_time() );
369
+ }
370
+
371
+ return $done;
372
+ }
373
+
374
+ function do_posts_import($url) {
375
+ $start = $this->blog[$url]['posts_complete'];
376
+ $total = $this->blog[$url]['total_posts'];
377
+
378
+ // check for posts completion
379
+ if ( $start >= $total ) {
380
+ $this->blog[$url]['progress'] = 'drafts';
381
+ return;
382
+ }
383
+
384
+ // get the already imported posts to prevent dupes
385
+ $dupes = $this->get_imported_posts( 'tumblr', $this->blog[$url]['name'] );
386
+
387
+ if ($this->blog[$url]['posts_complete'] + TUMBLR_MAX_IMPORT > $total) $count = $total - $start;
388
+ else $count = TUMBLR_MAX_IMPORT;
389
+
390
+ $imported_posts = $this->fetch_posts($url, $start, $count, $this->email, $this->password );
391
+
392
+ if ( false === $imported_posts ) {
393
+ $this->error = __('Problem communicating with Tumblr, retrying later','tumblr-importer');
394
+ return;
395
+ }
396
+
397
+ if ( is_array($imported_posts) && !empty($imported_posts) ) {
398
+ reset($imported_posts);
399
+ $post = current($imported_posts);
400
+ do {
401
+ // skip dupes
402
+ if ( !empty( $dupes[$post['tumblr_url']] ) ) {
403
+ $this->blog[$url]['posts_complete']++;
404
+ $this->save_vars();
405
+ continue;
406
+ }
407
+
408
+ if ( isset( $post['private'] ) ) $post['post_status'] = 'private';
409
+ else $post['post_status']='publish';
410
+
411
+ $post['post_author'] = $this->blog[$url]['post_author'];
412
+
413
+ do_action( 'tumblr_importing_post', $post );
414
+ $id = wp_insert_post( $post );
415
+
416
+ if ( !is_wp_error( $id ) ) {
417
+ $post['ID'] = $id; // Allows for the media importing to wp_update_post()
418
+ if ( isset( $post['format'] ) ) set_post_format($id, $post['format']);
419
+
420
+ // @todo: Add basename of the permalink as a 404 redirect handler for when a custom domain has been brought accross
421
+ add_post_meta( $id, 'tumblr_'.$this->blog[$url]['name'].'_permalink', $post['tumblr_url'] );
422
+ add_post_meta( $id, 'tumblr_'.$this->blog[$url]['name'].'_id', $post['tumblr_id'] );
423
+
424
+ $import_result = $this->handle_sideload($post);
425
+
426
+ // Handle failed imports.. If empty content and failed to import media..
427
+ if ( is_wp_error($import_result) ) {
428
+ if ( empty($post['post_content']) ) {
429
+ wp_delete_post($id, true);
430
+ }
431
+ }
432
+ }
433
+
434
+ $this->blog[$url]['posts_complete']++;
435
+ $this->save_vars();
436
+
437
+ } while ( false != ($post = next($imported_posts) ) && $this->have_time() );
438
+ }
439
+ }
440
+
441
+ function get_draft_post_type( $post_type ) {
442
+ return 'draft';
443
+ }
444
+
445
+ function do_drafts_import($url) {
446
+ $start = $this->blog[$url]['drafts_complete'];
447
+ $total = $this->blog[$url]['total_drafts'];
448
+
449
+ // check for posts completion
450
+ if ( $start >= $total ) {
451
+ $this->blog[$url]['progress'] = 'queued';
452
+ return;
453
+ }
454
+
455
+ // get the already imported posts to prevent dupes
456
+ $dupes = $this->get_imported_posts( 'tumblr', $this->blog[$url]['name'] );
457
+
458
+ if ($this->blog[$url]['posts_complete'] + TUMBLR_MAX_IMPORT > $total) $count = $total - $start;
459
+ else $count = TUMBLR_MAX_IMPORT;
460
+
461
+ add_filter( 'tumblr_post_type', array( $this, 'get_draft_post_type' ) );
462
+ $imported_posts = $this->fetch_posts($url, $start, $count, $this->email, $this->password, 'draft' );
463
+
464
+ if ( empty($imported_posts) ) {
465
+ $this->error = __('Problem communicating with Tumblr, retrying later','tumblr-importer');
466
+ return;
467
+ }
468
+
469
+ if ( is_array($imported_posts) && !empty($imported_posts) ) {
470
+ reset($imported_posts);
471
+ $post = current($imported_posts);
472
+ do {
473
+ // skip dupes
474
+ if ( !empty( $dupes[$post['tumblr_url']] ) ) {
475
+ $this->blog[$url]['drafts_complete']++;
476
+ $this->save_vars();
477
+ continue;
478
+ }
479
+
480
+ $post['post_status'] = 'draft';
481
+ $post['post_author'] = $this->blog[$url]['post_author'];
482
+
483
+ do_action( 'tumblr_importing_post', $post );
484
+ $id = wp_insert_post( $post );
485
+ if ( !is_wp_error( $id ) ) {
486
+ $post['ID'] = $id;
487
+ if ( isset( $post['format'] ) ) set_post_format($id, $post['format']);
488
+
489
+ add_post_meta( $id, 'tumblr_'.$this->blog[$url]['name'].'_permalink', $post['tumblr_url'] );
490
+ add_post_meta( $id, 'tumblr_'.$this->blog[$url]['name'].'_id', $post['tumblr_id'] );
491
+
492
+ $this->handle_sideload($post);
493
+ }
494
+
495
+ $this->blog[$url]['drafts_complete']++;
496
+ $this->save_vars();
497
+ } while ( false != ($post = next($imported_posts) ) && $this->have_time() );
498
+ }
499
+ }
500
+
501
+ function do_pages_import($url) {
502
+ $start = $this->blog[$url]['pages_complete'];
503
+
504
+ // get the already imported posts to prevent dupes
505
+ $dupes = $this->get_imported_posts( 'tumblr', $this->blog[$url]['name'] );
506
+
507
+ $imported_pages = $this->fetch_pages($url, $this->email, $this->password );
508
+
509
+ if ( false === $imported_pages ) {
510
+ $this->error = __('Problem communicating with Tumblr, retrying later','tumblr-importer');
511
+ return;
512
+ }
513
+
514
+ if ( is_array($imported_pages) && !empty($imported_pages) ) {
515
+ reset($imported_pages);
516
+ $post = current($imported_pages);
517
+ do {
518
+ // skip dupes
519
+ if ( !empty( $dupes[$post['tumblr_url']] ) ) {
520
+ continue;
521
+ }
522
+
523
+ $post['post_type'] = 'page';
524
+ $post['post_status'] = 'publish';
525
+ $post['post_author'] = $this->blog[$url]['post_author'];
526
+
527
+ $id = wp_insert_post( $post );
528
+ if ( !is_wp_error( $id ) ) {
529
+ add_post_meta( $id, 'tumblr_'.$this->blog[$url]['name'].'_permalink', $post['tumblr_url'] );
530
+ $post['ID'] = $id;
531
+ $this->handle_sideload($post);
532
+ }
533
+
534
+ $this->blog[$url]['pages_complete']++;
535
+ $this->save_vars();
536
+ } while ( false != ($post = next($imported_pages) ) );
537
+ }
538
+ $this->blog[$url]['progress'] = 'finish';
539
+ }
540
+
541
+ function handle_sideload_import($post, $source, $description = '', $filename = false) {
542
+ // Make a HEAD request to get the filename:
543
+ if ( empty($filename) ) {
544
+ $head = wp_remote_request( $source, array('method' => 'HEAD') );
545
+ if ( !empty($head['headers']['location']) ) {
546
+ $source = $head['headers']['location'];
547
+ $filename = preg_replace('!\?.*!', '', basename($source) ); // Strip off the Query vars
548
+ }
549
+ }
550
+
551
+ // still empty? Darned inconsistent tumblr...
552
+ if ( empty($filename) ) {
553
+ $path = parse_url($source,PHP_URL_PATH);
554
+ $filename = basename($path);
555
+ }
556
+ // Download file to temp location
557
+ $tmp = download_url( $source );
558
+ if ( is_wp_error($tmp) )
559
+ return $tmp;
560
+
561
+ $file_array['name'] = !empty($filename) ? $filename : basename($tmp);
562
+ $file_array['tmp_name'] = $tmp;
563
+ // do the validation and storage stuff
564
+ $id = media_handle_sideload( $file_array, $post['ID'], $description, array( 'post_excerpt' => $description ) );
565
+
566
+ if ( $id && ! is_wp_error($id) ) {
567
+ // Update the date/time on the attachment to that of the Tumblr post.
568
+ $attachment = get_post($id, ARRAY_A);
569
+ foreach ( array('post_date', 'post_date_gmt', 'post_modified', 'post_modified_gmt') as $field ) {
570
+ if ( isset($post[ $field]) )
571
+ $attachment[ $field ] = $post[ $field ];
572
+ }
573
+ wp_update_post($attachment);
574
+ }
575
+
576
+ // If error storing permanently, unlink
577
+ if ( is_wp_error($id) )
578
+ @unlink($file_array['tmp_name']);
579
+ return $id;
580
+ }
581
+
582
+ function handle_sideload($post) {
583
+
584
+ if ( empty( $post['format'] ) )
585
+ return; // Nothing to import.
586
+
587
+ switch ( $post['format'] ) {
588
+ case 'gallery':
589
+ if ( !empty( $post['gallery'] ) ) {
590
+ foreach ( $post['gallery'] as $i => $photo ) {
591
+ $id = $this->handle_sideload_import( $post, (string)$photo['src'], (string)$photo['caption']);
592
+ if ( is_wp_error($id) )
593
+ return $id;
594
+ }
595
+ $post['post_content'] = "[gallery]\n" . $post['post_content'];
596
+ $post = apply_filters( 'tumblr_importer_format_post', $post );
597
+ do_action( 'tumblr_importer_metadata', $post );
598
+ wp_update_post($post);
599
+ break; // If we processed a gallery, break, otherwise let it fall through to the Image handler
600
+ }
601
+
602
+ case 'image':
603
+ if ( isset( $post['media']['src'] ) ) {
604
+ $id = $this->handle_sideload_import( $post, (string)$post['media']['src'], (string)$post['post_title']);
605
+ if ( is_wp_error($id) )
606
+ return $id;
607
+
608
+ $link = !empty($post['media']['link']) ? $post['media']['link'] : null;
609
+ // image_send_to_editor has a filter to wrap in a shortcode.
610
+ $post_content = $post['post_content'];
611
+ $post['post_content'] = get_image_send_to_editor($id, (string)$post['post_title'], (string)$post['post_title'], 'none', $link, true, 'full' );
612
+ $post['post_content'] .= $post_content;
613
+ $post['meta']['attribution'] = $link;
614
+ $post = apply_filters( 'tumblr_importer_format_post', $post );
615
+ do_action( 'tumblr_importer_metadata', $post );
616
+ //$post['post_content'] .= "\n" . $post['post_content']; // the [caption] shortcode doesn't allow HTML, but this might have some extra markup
617
+ wp_update_post($post);
618
+ }
619
+
620
+ break;
621
+
622
+ case 'audio':
623
+ // Handle Tumblr Hosted Audio
624
+ if ( isset( $post['media']['audio'] ) ) {
625
+ $id = $this->handle_sideload_import( $post, (string)$post['media']['audio'], $post['post_title'], (string)$post['media']['filename'] );
626
+ if ( is_wp_error($id) )
627
+ return $id;
628
+ $post['post_content'] = wp_get_attachment_link($id) . "\n" . $post['post_content'];
629
+ } else {
630
+ // Try to work out a "source" link to display Tumblr-style.
631
+ preg_match( '/(http[^ "<>\']+)/', $post['post_content'], $matches );
632
+ if ( isset( $matches[1] ) ) {
633
+ $url_parts = parse_url( $matches[1] );
634
+ $post['meta']['attribution'] = $url_parts['scheme'] . "://" . $url_parts['host'] . "/";
635
+ }
636
+ }
637
+ $post = apply_filters( 'tumblr_importer_format_post', $post );
638
+ do_action( 'tumblr_importer_metadata', $post );
639
+ wp_update_post($post);
640
+ break;
641
+
642
+ case 'video':
643
+ // Handle Tumblr hosted video
644
+ if ( isset( $post['media']['video'] ) ) {
645
+ $id = $this->handle_sideload_import( $post, (string)$post['media']['video'], $post['post_title'], (string)$post['media']['filename'] );
646
+ if ( is_wp_error($id) )
647
+ return $id;
648
+
649
+ // @TODO: Check/change this to embed the imported video.
650
+ $link = wp_get_attachment_link($id) . "\n" . $post['post_content'];
651
+ $post['post_content'] = $link;
652
+ $post['meta']['attribution'] = $link;
653
+ } else {
654
+ // Try to work out a "source" link to mimic Tumblr's post formatting.
655
+ preg_match( '/(http[^ "<>\']+)/', $post['post_content'], $matches );
656
+ if ( isset( $matches[1] ) ) {
657
+ $url_parts = parse_url( $matches[1] );
658
+ $post['meta']['attribution'] = $url_parts['scheme'] . "://" . $url_parts['host'] . "/";
659
+ }
660
+ }
661
+ $post = apply_filters( 'tumblr_importer_format_post', $post );
662
+ do_action( 'tumblr_importer_metadata', $post );
663
+ wp_update_post($post);
664
+
665
+ // Else, Check to see if the url embedded is handled by oEmbed (or not)
666
+ break;
667
+ }
668
+
669
+ return true; // all processed
670
+ }
671
+
672
+
673
+ /**
674
+ * Get a request token from the OAuth endpoint (also serves as a test)
675
+ *
676
+ */
677
+ function oauth_get_request_token() {
678
+ if ( empty($this->consumerkey) || empty ($this->secretkey) )
679
+ return false;
680
+
681
+ $url = 'https://www.tumblr.com/oauth/request_token';
682
+
683
+ $params = array('oauth_callback' => self_admin_url('admin.php?import=tumblr'),
684
+ 'oauth_consumer_key' => $this->consumerkey,
685
+ "oauth_version" => "1.0",
686
+ "oauth_nonce" => time(),
687
+ "oauth_timestamp" => time(),
688
+ "oauth_signature_method" => "HMAC-SHA1",
689
+ );
690
+
691
+ $params['oauth_signature'] = $this->oauth_signature(array($this->secretkey,''), 'POST', $url, $params);
692
+
693
+ $response = wp_remote_post( $url, array('body' => $params));
694
+
695
+ return $response;
696
+ }
697
+
698
+ /**
699
+ * Fetch a list of blogs for a user
700
+ *
701
+ * @param $email
702
+ * @param $password
703
+ * @returns array of blog info or a WP_Error
704
+ */
705
+ function get_blogs() {
706
+ $url = 'https://api.tumblr.com/v2/user/info';
707
+ $response = $this->oauth_get_request($url);
708
+
709
+ switch ( $response->meta->status ) {
710
+ case 403: // Bad Username / Password
711
+ do_action( 'tumblr_importer_handle_error', 'get_blogs_403' );
712
+ return new WP_Error('tumblr_error', __('Tumblr says that the the app is not authorized. Please check the settings and try to connect again.', 'tumblr-importer' ) );
713
+ case 200: // OK
714
+ break;
715
+ default:
716
+ $_error = sprintf( __( 'Tumblr replied with an error: %s', 'tumblr-importer' ), $response->meta->msg );
717
+ do_action( 'tumblr_importer_handle_error', 'response_' . $response->meta->status );
718
+ return new WP_Error('tumblr_error', $_error );
719
+ }
720
+
721
+ $blogs = array();
722
+ foreach ( $response->response->user->blogs as $tblog ) {
723
+ $blog = array();
724
+ $blog['title'] = (string) $tblog->title;
725
+ $blog['posts'] = (int) $tblog->posts;
726
+ $blog['drafts'] = (int) $tblog->drafts;
727
+ $blog['queued'] = (int) $tblog->queue;
728
+ $blog['avatar'] = '';
729
+ $blog['url'] = (string) $tblog->url;
730
+ $blog['name'] = (string) $tblog->name;
731
+
732
+ $blogs[] = $blog;
733
+ }
734
+ $this->blogs = $blogs;
735
+ return $this->blogs;
736
+ }
737
+
738
+ function get_consumer_key() {
739
+ return $this->consumerkey;
740
+ }
741
+
742
+ /**
743
+ * Fetch a subset of posts from a tumblr blog
744
+ *
745
+ * @param $start index to start at
746
+ * @param $count how many posts to get (max 50)
747
+ * @param $state can be empty for normal posts, or "draft", "queue", or "submission" to get those posts
748
+ * @returns false on error, array of posts on success
749
+ */
750
+ function fetch_posts($url, $start=0, $count = 50, $email = null, $password = null, $state = null ) {
751
+ $url = parse_url( $url, PHP_URL_HOST );
752
+ $post_type = apply_filters( 'tumblr_post_type', '' );
753
+ $url = trailingslashit( "https://api.tumblr.com/v2/blog/$url/posts/$post_type" );
754
+
755
+ do_action( 'tumblr_importer_pre_fetch_posts' );
756
+
757
+ // These extra params hose up the auth if passed for oauth requests e.g. for drafts, so use them only for normal posts.
758
+ if ( '' == $post_type ) {
759
+ $params = array(
760
+ 'offset' => $start,
761
+ 'limit' => $count,
762
+ 'api_key' => apply_filters( 'tumblr_importer_get_consumer_key', '' ),
763
+ );
764
+ $url = add_query_arg( $params, $url );
765
+ }
766
+
767
+ $response = $this->oauth_get_request($url);
768
+
769
+ switch ( $response->meta->status ) {
770
+ case 200: // OK
771
+ break;
772
+ default:
773
+ $_error = sprintf( __( 'Tumblr replied with an error: %s', 'tumblr-importer' ), $response->meta->msg );
774
+ do_action( 'tumblr_importer_handle_error', 'response_' . $response->meta->status );
775
+ return new WP_Error('tumblr_error', $_error );
776
+ }
777
+
778
+ $posts = array();
779
+ $tposts = $response->response->posts;
780
+ foreach( $tposts as $tpost ) {
781
+ $post = array();
782
+ $post['tumblr_id'] = (string) $tpost->id;
783
+ $post['tumblr_url'] = (string) $tpost->post_url;
784
+ $post['post_date'] = date( 'Y-m-d H:i:s', strtotime ( (string) $tpost->date ) );
785
+ $post['post_date_gmt'] = date( 'Y-m-d H:i:s', strtotime ( (string) $tpost->date ) );
786
+ $post['post_name'] = (string) $tpost->slug;
787
+ if ( 'private' == $tpost->state )
788
+ $post['private'] = (string) $tpost->state;
789
+ if ( isset( $tpost->tags ) ) {
790
+ $post['tags_input'] = array();
791
+ foreach ( $tpost->tags as $tag )
792
+ $post['tags_input'][] = rtrim( (string) $tag, ','); // Strip trailing Commas off it too.
793
+ }
794
+
795
+ switch ( (string) $tpost->type ) {
796
+ case 'photo':
797
+ $post['format'] = 'image';
798
+ $post['media']['src'] = (string) $tpost->photos[0]->original_size->url;
799
+ $post['media']['link'] = '';//TODO: Find out what to use here.(string) $tpost->{'photo-link-url'};
800
+ $post['media']['width'] = (string) $tpost->photos[0]->original_size->width;
801
+ $post['media']['height'] = (string) $tpost->photos[0]->original_size->height;
802
+ $post['post_content'] = (string) $tpost->caption;
803
+ if ( ! empty( $tpost->photos ) ) {
804
+ $post['format'] = 'gallery';
805
+ foreach ( $tpost->photos as $photo ) {
806
+ $post['gallery'][] = array (
807
+ 'src' => $photo->original_size->url,
808
+ 'width' => $photo->original_size->width,
809
+ 'height' => $photo->original_size->height,
810
+ 'caption' => $photo->caption,
811
+ );
812
+ }
813
+ }
814
+ break;
815
+ case 'quote':
816
+ $post['format'] = 'quote';
817
+ $post['post_content'] = '<blockquote>' . (string) $tpost->text . '</blockquote>';
818
+ $post['post_content'] .= "\n\n<div class='attribution'>" . (string) $tpost->source . '</div>';
819
+ break;
820
+ case 'link':
821
+ $post['format'] = 'link';
822
+ $linkurl = (string) $tpost->url;
823
+ $linktext = (string) $tpost->title;
824
+ $post['post_content'] = "<a href='$linkurl'>$linktext</a>";
825
+ if ( ! empty( $tpost->description ) )
826
+ $post['post_content'] .= '<div class="link_description">' . (string) $tpost->description . '</div>';
827
+ $post['post_title'] = (string) $tpost->title;
828
+ break;
829
+ case 'chat':
830
+ $post['format'] = 'chat';
831
+ $post['post_title'] = (string) $tpost->title;
832
+ $post['post_content'] = (string) $tpost->body;
833
+ break;
834
+ case 'audio':
835
+ $post['format'] = 'audio';
836
+ $post['media']['filename'] = basename( (string) $tpost->audio_url );
837
+ // If no .mp3 extension, add one so that sideloading works.
838
+ if ( ! preg_match( '/\.mp3$/', $post['media']['filename'] ) )
839
+ $post['media']['filename'] .= '.mp3';
840
+ $post['media']['audio'] = (string) $tpost->audio_url .'?plead=please-dont-download-this-or-our-lawyers-wont-let-us-host-audio';
841
+ $post['post_content'] = (string) $tpost->player . "\n" . (string) $tpost->caption;
842
+ break;
843
+ case 'video':
844
+ $post['format'] = 'video';
845
+ $post['post_content'] = '';
846
+
847
+ $video = array_shift( $tpost->player );
848
+
849
+ if ( false !== strpos( (string) $video->embed_code, 'embed' ) ) {
850
+ if ( preg_match_all('/<embed (.+?)>/', (string) $video->embed_code, $matches) ) {
851
+ foreach ($matches[1] as $match) {
852
+ foreach ( wp_kses_hair( $match, array( 'http' ) ) as $attr )
853
+ $embed[ $attr['name'] ] = $attr['value'];
854
+ }
855
+
856
+ // special case for weird youtube vids
857
+ $embed['src'] = preg_replace( '|http://www.youtube.com/v/([a-zA-Z0-9_]+).*|i', 'http://www.youtube.com/watch?v=$1', $embed['src'] );
858
+
859
+ // TODO find other special cases, since tumblr is full of them
860
+ $post['post_content'] = $embed['src'];
861
+ }
862
+
863
+ // Sometimes, video-source contains iframe markup.
864
+ if ( preg_match( '/<iframe/', $video->embed_code ) ) {
865
+ $embed['src'] = preg_replace( '|<iframe.*src="http://www.youtube.com/embed/([a-zA-Z0-9_\-]+)\??.*".*</iframe>|', 'http://www.youtube.com/watch?v=$1', $video->embed_code );
866
+ $post['post_content'] = $embed['src'];
867
+ }
868
+ } elseif ( preg_match( '/<iframe.*vimeo/', $video->embed_code ) ) {
869
+ $embed['src'] = preg_replace( '|<iframe.*src="(http://player.vimeo.com/video/([a-zA-Z0-9_\-]+))\??.*".*</iframe>.*|', 'http://vimeo.com/$2', $video->embed_code );
870
+ $post['post_content'] = $embed['src'];
871
+ } else {
872
+ // @todo: See if the video source is going to be oEmbed'able before adding the flash player
873
+ $post['post_content'] .= $video->embed_code;
874
+ }
875
+
876
+ $post['post_content'] .= "\n" . (string) $tpost->caption;
877
+ break;
878
+ case 'answer':
879
+ // TODO: Include asking_name and asking_url values?
880
+ $post['post_title'] = (string) $tpost->question;
881
+ $post['post_content'] = (string) $tpost->answer;
882
+ break;
883
+ case 'regular':
884
+ case 'text':
885
+ default:
886
+ $post['post_title'] = (string) $tpost->title;
887
+ $post['post_content'] = (string) $tpost->body;
888
+ break;
889
+ }
890
+ $posts[] = $post;
891
+ }
892
+
893
+ return $posts;
894
+ }
895
+
896
+ /**
897
+ * Fetch the Pages from a tumblr blog
898
+ *
899
+ * @returns false on error, array of page contents on success
900
+ */
901
+ function fetch_pages($url, $email = null, $password = null) {
902
+ $tumblrurl = trailingslashit($url).'api/pages';
903
+ $params = array(
904
+ 'email'=>$email,
905
+ 'password'=>$password,
906
+ );
907
+ $options = array( 'body' => $params );
908
+
909
+ // fetch the pages
910
+ $out = wp_remote_post($tumblrurl,$options);
911
+ if (wp_remote_retrieve_response_code($out) != 200) return false;
912
+ $body = wp_remote_retrieve_body($out);
913
+
914
+ // parse the XML into something useful
915
+ $xml = simplexml_load_string($body);
916
+
917
+ if (!isset($xml->pages)) return false;
918
+
919
+ $tpages = $xml->pages;
920
+ $pages = array();
921
+ foreach($tpages->page as $tpage) {
922
+ if ( !empty($tpage['title']) )
923
+ $page['post_title'] = (string) $tpage['title'];
924
+ else if (!empty($tpage['link-title']) )
925
+ $page['post_title'] = (string) $tpage['link-title'];
926
+ else
927
+ $page['post_title'] = '';
928
+ $page['post_name'] = str_replace( $url, '', (string) $tpage['url'] );
929
+ $page['post_content'] = (string) $tpage;
930
+ $page['tumblr_url'] = (string) $tpage['url'];
931
+ $pages[] = $page;
932
+ }
933
+
934
+ return $pages;
935
+ }
936
+
937
+ function filter_format_post( $_post ) {
938
+ if ( isset( $_post['meta']['attribution'] ) ) {
939
+ $attribution = $_post['meta']['attribution'];
940
+ if ( preg_match( '/^http[^ ]+$/', $_post['meta']['attribution'] ) )
941
+ $attribution = sprintf( '<a href="%s">%s</a>', $_post['meta']['attribution'], $_post['meta']['attribution'] );
942
+ $_post['post_content'] .= sprintf( '<div class="attribution">(<span>' . __( 'Source:', 'tumblr-importer' ) . '</span> %s)</div>', $attribution );
943
+ }
944
+
945
+ return $_post;
946
+ }
947
+
948
+ function tumblr_importer_metadata( $_post ) {
949
+ if ( isset( $_post['meta'] ) ) {
950
+ foreach ( $_post['meta'] as $key => $val ) {
951
+ add_post_meta( $_post['ID'], 'tumblr_' . $key, $val );
952
+ }
953
+ }
954
+ }
955
+
956
+ /*
957
+ * When galleries have no caption, the post_content field is empty, which
958
+ * along with empty title and excerpt causes the post not to insert.
959
+ * Here we override the default behavior.
960
+ */
961
+ function filter_allow_empty_content( $maybe_empty, $_post ) {
962
+ if ( 'gallery' == $_post['format'] )
963
+ return false;
964
+
965
+ return $maybe_empty;
966
+ }
967
+
968
+
969
+ /**
970
+ * OAuth Signature creation
971
+ */
972
+ function oauth_signature($secret, $method, $url, $params = array()) {
973
+ uksort($params, 'strcmp');
974
+ foreach ($params as $k => $v) {
975
+ $pairs[] = $this->_urlencode_rfc3986($k).'='.$this->_urlencode_rfc3986($v);
976
+ }
977
+ $concatenatedParams = implode('&', $pairs);
978
+ $baseString= $method."&". $this->_urlencode_rfc3986($url)."&".$this->_urlencode_rfc3986($concatenatedParams);
979
+ if (!is_array($secret)) {
980
+ $secret[0] = $secret;
981
+ $secret[1] = '';
982
+ }
983
+ $secret = $this->_urlencode_rfc3986($secret[0])."&".$this->_urlencode_rfc3986($secret[1]);
984
+ $oauth_signature = base64_encode(hash_hmac('sha1', $baseString, $secret, TRUE));
985
+ return $oauth_signature;
986
+ }
987
+
988
+ /**
989
+ * Helper function for OAuth Signature creation
990
+ */
991
+ function _urlencode_rfc3986($input)
992
+ {
993
+ if (is_array($input)) {
994
+ return array_map(array($this, '_urlencode_rfc3986'), $input);
995
+ } else if (is_scalar($input)) {
996
+ return str_replace(array('+', '%7E'), array(' ', '~'), rawurlencode($input));
997
+ } else {
998
+ return '';
999
+ }
1000
+ }
1001
+
1002
+ /**
1003
+ * Do a GET request with the access tokens
1004
+ */
1005
+ function oauth_get_request($url) {
1006
+ if ( empty( $this->access_tokens ) )
1007
+ return false;
1008
+
1009
+ $params = array('oauth_consumer_key' => $this->get_consumer_key(),
1010
+ "oauth_nonce" => time(),
1011
+ "oauth_timestamp" => time(),
1012
+ "oauth_token" => $this->access_tokens['oauth_token'],
1013
+ "oauth_signature_method" => "HMAC-SHA1",
1014
+ "oauth_version" => "1.0",
1015
+ );
1016
+
1017
+ $params['oauth_signature'] = $this->oauth_signature(array($this->secretkey,$this->access_tokens['oauth_token_secret']), 'GET', $url, $params);
1018
+
1019
+ $url = add_query_arg( array_map('urlencode', $params), $url);
1020
+
1021
+ $response = wp_remote_get( $url );
1022
+
1023
+ if ( is_wp_error( $response ) || 200 != wp_remote_retrieve_response_code( $response ) ) {
1024
+ return false;
1025
+ } else {
1026
+ $body = wp_remote_retrieve_body( $response );
1027
+ return json_decode($body);
1028
+ }
1029
+ }
1030
+
1031
+
1032
+ }
1033
+ }