ImportPostWp.class.php source code
Contents of file
ImportPostWp.class.php
1
<?php
2 /*
3 * ImportPostWp.class.php
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 * MA 02110-1301, USA.
19 *
20 * @author Mario Spada <spadamar@spadamar.com>
21 * @copyright Copyright (c) 2015 Mario Spada
22 * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
23 * @package ImportPostWp
24 * @version 0.1.0 2015/06/28
25 */
26
27 /**
28 * ImportPostWp
29 * This class allows to import bulk posts into Wordpress from array
30 *
31 * @author Mario Spada <spadamar@spadamar.com>
32 * @copyright Copyright (c) 2015 Mario Spada
33 * @license http://opensource.org/licenses/GPL-2.0 GNU Public License
34 * @package ImportPostWp
35 * @version 0.1.0 2015/06/28
36 */
37
38 class ImportPostWp {
39
40 /**
41 * Path of Wordpress root directory
42 * @var string
43 */
44 public $wp_path = ".";
45 /**
46 * Timezone as defined in http://php.net/manual/en/timezones.php
47 * @var string
48 */
49 public $time_zone = "Europe/Rome";
50 /**
51 * Switch on debug
52 * @var boolean
53 */
54 public $debug = false;
55 /**
56 * Total elapsed time in seconds
57 * @var int
58 */
59 protected $time_elapsed = 0;
60 /**
61 * Array containing each row number of the failed insert
62 * @var array
63 */
64 protected $insert_errors = array();
65 /**
66 * Array containing the list of the fields to insert
67 * @var array
68 */
69 protected $fields_list = array('post_title','post_content','post_name',
70 'post_status','post_type','guid','post_excerpt',
71 'post_date','post_date_gmt','ping_status',
72 'comment_status','post_author','categories');
73 /**
74 * Array containing the default field values
75 * @var array
76 */
77 protected $default_post_values = array('post_status' => 'publish',
78 'post_type'=> 'post',
79 'ping_status'=> 'closed',
80 'comment_status'=> 'closed',
81 'post_author'=> 1 );
82 /**
83 * Array containing data
84 * @var array
85 */
86 protected $posts = array();
87 /**
88 * The number of rows of data array
89 * @var int
90 */
91 protected $nPosts = 0;
92
93 /**
94 * @param array $data data array
95 * @param string $wpPath The path to Wordpress directory
96 */
97 function __construct($data,$wpPath = "."){
98 $this->wp_path = rtrim($wpPath, '/') . '/';
99 $this->posts = $data;
100 $this->nPosts = count($data);
101 require_once($this->wp_path."wp-load.php");
102 }
103
104 /**
105 * reset elapsed time
106 */
107 public function reset_time() {
108 $this->time_elapsed = 0;
109 }
110
111 /**
112 * Get elapsed time
113 */
114 public function get_elapsed_time() {
115 return $this->time_elapsed;
116 }
117 /**
118 * Return data array
119 * If $print is true, prints out data array
120 *
121 * @param bool $print
122 * @return array
123 */
124 public function get_data ($print=false) {
125 if ($print) {
126 echo "<pre>";
127 print_r($this->posts);
128 echo "</pre>";
129 }
130 return $this->posts;
131 }
132
133 /**
134 * Return default values for the optional field list
135 * If $print is true, prints out array
136 *
137 * @param bool $print
138 * @return array
139 */
140 public function get_default_post_values ($print=false) {
141 if ($print) {
142 echo "<pre>";
143 print_r($this->default_post_values);
144 echo "</pre>";
145 }
146 return $this->default_post_values;
147 }
148 /**
149 * Return an array of the not inserted rows
150 * If $print is true, prints out array
151 *
152 * @param bool $print
153 * @return array
154 */
155 public function get_insert_errors ($print=false) {
156 if ($print) {
157 echo "<pre>";
158 print_r($this->insert_errors);
159 echo "</pre>";
160 }
161 return $this->insert_errors;
162 }
163 /**
164 * Return the field name list
165 * If $print is true, prints out array
166 *
167 * @param bool $print
168 * @return array
169 */
170 public function get_field_list ($print=false) {
171 if ($print) {
172 echo "<pre>";
173 print_r($this->fields_list);
174 echo "</pre>";
175 }
176 return $this->fields_list;
177 }
178 /**
179 * Set default values for the field 'post_status'
180 * Possible values: [ 'draft' | 'publish' | 'pending'| 'future' | 'private' | custom registered status ]
181 * default = 'publish'
182 *
183 * @param string $val
184 */
185 public function set_default_post_status ($val) {
186 $this->default_post_values['post_status'] = $val;
187 }
188 /**
189 * Set default values for the field 'post_type'
190 * Possible values: [ 'post' | 'page' | 'link' | 'nav_menu_item' | custom post type ]
191 * default = 'post'
192 *
193 * @param string $val
194 */
195 public function set_default_post_type ($val) {
196 $this->default_post_values['post_type'] = $val;
197 }
198 /**
199 * Set default values for the field 'ping_status'
200 * Possible values: [ 'closed' | 'open' ]
201 * default = 'closed'
202 *
203 * @param string $val
204 */
205 public function set_default_ping_status ($val) {
206 $this->default_post_values['ping_status'] = $val;
207 }
208 /**
209 * Set default values for the field 'comment_status'
210 * Possible values: [ 'closed' | 'open' ]
211 * default = 'closed'
212 *
213 * @param string $val
214 */
215 public function set_default_comment_status ($val) {
216 $this->default_post_values['comment_status'] = $val;
217 }
218 /**
219 * Set default values for the field 'post_author'
220 * Possible values: [ <user ID> ] // The user ID number of the author.
221 * default = 1
222 *
223 * @param string $val
224 */
225 public function set_default_post_author ($val) {
226 $this->default_post_values['post_author'] = $val;
227 }
228 /**
229 * Loop through data and search ID categories on WP database.
230 * If the category doesn't exist, it will be created.
231 * Substitute all category string with IDs in the data array.
232 * If empty category is provided, the value will be the ID of the default category
233 */
234 protected function prepare_categories () {
235 require_once($this->wp_path . 'wp-admin/includes/taxonomy.php');
236 $start = microtime(true);
237 for ($i=0;$i < $this->nPosts;$i++) {
238
239 if (empty($this->posts[$i]['categories'])) {
240 $tmp = get_option('default_category');
241 $this->posts[$i]['categories'] = $tmp;
242 }
243
244 $cats = explode(",",$this->posts[$i]['categories']);
245
246 $newCats = array();
247 foreach ($cats as $cat) {
248 if (!is_numeric($cat)) {
249 $cat_ID = get_cat_ID(trim($cat));
250 if (empty($cat_ID)) {
251 $new_cat = array('cat_name' => trim($cat),
252 'category_description' => trim($cat),
253 'category_nicename' => sanitize_title(trim($cat))
254 );
255 $cat_ID = wp_insert_category($new_cat);
256 }
257 } else {
258 $cat_ID = (int) $cat;
259 }
260 $newCats[] = $cat_ID;
261 }
262 $this->posts[$i]['categories'] = implode(",",$newCats);
263 }
264 $this->time_elapsed += microtime(true) - $start;
265 }
266 /**
267 * Delete all post of a specific category. It cleans also all
268 * relationship records.
269 * Accept both category name or category ID
270 * The number of affected record will twice the number of affected posts
271 *
272 * @param int|string $cat
273 * @return int number of affected records
274 */
275 public function delete_posts($cat) {
276 $start = microtime(true);
277 $cat_ID = is_numeric($cat) ? $cat : get_cat_ID(trim($cat));
278
279 if (empty($cat_ID))
280 return 0;
281
282 $q = "delete a,b,c
283 FROM wp_posts a
284 LEFT JOIN wp_term_relationships b ON ( a.ID = b.object_id )
285 LEFT JOIN wp_postmeta c ON ( a.ID = c.post_id )
286 LEFT JOIN wp_term_taxonomy d ON ( d.term_taxonomy_id = b.term_taxonomy_id )
287 LEFT JOIN wp_terms e ON ( e.term_id = d.term_id )
288 WHERE e.term_id =".$cat_ID.";";
289
290 $q2 = "DELETE tr FROM wp_term_relationships tr
291 INNER JOIN wp_term_taxonomy tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id)
292 WHERE tt.taxonomy != 'link_category'
293 AND tr.object_id NOT IN (SELECT ID FROM wp_posts);";
294
295 global $wpdb;
296
297 if ($this->debug)
298 $wpdb->show_errors();
299
300 $wpdb->query( $q );
301 $results = $wpdb->rows_affected;
302
303 if ($results > 1) {
304 $wpdb->query( $q1 );
305 }
306 $this->time_elapsed += microtime(true) - $start;
307 return $results;
308 }
309
310 /**
311 * Insert all posts in Wordpress DB.
312 * It uses native WP function: wp_insert_post
313 * It is slow, but it performs a lot of security control before inserting
314 *
315 * @return int number of successfully inserted records
316 */
317 public function insert_posts() {
318 $this->prepare_categories();
319 $i = 0;
320 $start = microtime(true);
321 wp_suspend_cache_addition(true);
322 wp_defer_term_counting( true );
323
324 foreach ($this->posts as $key => $row) {
325 $cats = explode(",",$row['categories']);
326 $post_status = empty($row['post_status']) ? $this->default_post_values['post_status'] : $row['post_status'];
327 $post_type = empty($row['post_type']) ? $this->default_post_values['post_type'] : $row['post_type'];
328 $post_author = empty($row['post_author']) ? $this->default_post_values['post_author'] : (int) $row['post_author'];
329 $post_date = empty($row['post_date']) ? date("Y-m-d H:i:s") : $row['post_date'];
330
331 $new_post = array(
332 'post_title' => $row['post_title'],
333 'post_content' => $row['post_content'],
334 'post_status' => $post_status,
335 'post_type' => $post_type,
336 'post_date' => $post_date,
337 'post_author' => $post_author,
338 'post_category' => $cats
339 );
340
341 if (!empty($row['post_excerpt'])) {
342 $new_post['post_excerpt'] = $row['post_excerpt'];
343 }
344 if (!empty($row['comment_status']) && in_array($row['comment_status'],array('open','closed'))) {
345 $new_post['comment_status'] = $row['comment_status'];
346 } else {
347 $new_post['comment_status'] = $this->default_post_values['comment_status'];
348 }
349 if (!empty($row['ping_status']) && in_array($row['ping_status'],array('open','closed'))) {
350 $new_post['ping_status'] = $row['ping_status'];
351 } else {
352 $new_post['ping_status'] = $this->default_post_values['ping_status'];
353 }
354
355
356 $post_id = wp_insert_post( $new_post, false );
357 if (empty($post_id)){
358 $this->insert_errors[] = $key;
359 } else {
360 $i++;
361 }
362 }
363 $this->time_elapsed += microtime(true) - $start;
364 wp_suspend_cache_addition(false);
365 wp_defer_term_counting( false );
366
367 return $i;
368 }
369
370 /**
371 * Insert all posts in Wordpress DB.
372 * It uses raw SQL queries
373 * It is much faster than insert_posts, but it doesn't perform
374 * security control before inserting
375 *
376 * @return int number of successfully inserted records
377 */
378 public function raw_insert_posts () {
379 global $wpdb;
380 $this->prepare_categories();
381 if ($this->debug)
382 $wpdb->show_errors();
383 date_default_timezone_set($this->time_zone);
384 $i = 0;
385 $start = microtime(true);
386 foreach ($this->posts as $key => $row) {
387 $cats = explode(",",$row['categories']);
388
389 $post_name = sanitize_title_with_dashes($row['post_title']);
390 $guid = site_url()."/".$post_name;
391 $post_date = empty($row['post_date']) ? date("Y-m-d H:i:s") : $row['post_date'];
392 $post_date_gmt = gmdate("Y-m-d H:i:s",strtotime($post_date));
393 $post_status = empty($row['post_status']) ? $this->default_post_values['post_status'] : $row['post_status'];
394 $post_type = empty($row['post_type']) ? $this->default_post_values['post_type'] : $row['post_type'];
395 $post_author = empty($row['post_author']) ? $this->default_post_values['post_author'] : (int) $row['post_author'];
396 if (!empty($row['comment_status']) && in_array($row['comment_status'],array('open','closed'))) {
397 $comment_status = $row['comment_status'];
398 } else {
399 $comment_status = $this->default_post_values['comment_status'];
400 }
401 if (!empty($row['ping_status']) && in_array($row['ping_status'],array('open','closed'))) {
402 $ping_status = $row['ping_status'];
403 } else {
404 $ping_status = $this->default_post_values['ping_status'];
405 }
406 if (!empty($row['post_excerpt'])) {
407 $post_excerpt = $row['post_excerpt'];
408 } else {
409 $post_excerpt = "";
410 }
411 $query = "INSERT INTO $wpdb->posts
412 (post_title,post_content,post_name,post_status,
413 post_type,guid,post_author,post_date,post_date_gmt,
414 comment_status,ping_status,post_excerpt)
415 VALUES (%s, %s, %s, %s, %s, %s, %d, %s, %s, %s, %s, %s)";
416 $wpdb->query($wpdb->prepare($query,
417 $row['post_title'],
418 $row['post_content'],
419 $post_name,
420 $post_status,
421 $post_type,
422 $guid,
423 $post_author,
424 $post_date,
425 $post_date_gmt,
426 $comment_status,
427 $ping_status,
428 $post_excerpt));
429 $lastID = $wpdb->insert_id;
430 $i += (int) $wpdb->rows_affected;
431
432 $query = "INSERT INTO $wpdb->term_relationships (object_id,term_taxonomy_id) VALUES ";
433 foreach ($cats as $cat) {
434 $cat = (int) $cat;
435 $query .= "({$lastID}, {$cat}),";
436 }
437 $query = rtrim($query,",");
438 $wpdb->query($query);
439 }
440
441 $q = "UPDATE wp_term_taxonomy tt
442 SET count =
443 (SELECT count(p.ID) FROM wp_term_relationships tr
444 LEFT JOIN wp_posts p
445 ON (p.ID = tr.object_id AND p.post_type = 'post' AND p.post_status = 'publish')
446 WHERE tr.term_taxonomy_id = tt.term_taxonomy_id
447 )";
448 $wpdb->query($q);
449 $time_elapsed_secs = microtime(true) - $start;
450 return $i;
451 }
452
453 }
454
455 ?>
456