PluginProbe ʕ •ᴥ•ʔ
WP All Import – Drag & Drop Import for CSV, XML, Excel & Google Sheets / 3.2.2
WP All Import – Drag & Drop Import for CSV, XML, Excel & Google Sheets v3.2.2
4.1.1 3.9.5 3.9.6 4.0.0 4.0.1 4.1.0 trunk 2.12 2.13 2.14 3.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 3.2.0 3.2.1 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.2.7 3.2.8 3.2.9 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.4.6 3.4.7 3.4.8 3.4.9 3.5.0 3.5.1 3.5.2 3.5.3 3.5.4 3.5.5 3.5.6 3.5.7 3.5.8 3.5.9 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.6.8 3.6.9 3.7.0 3.7.1 3.7.2 3.7.3 3.7.3-beta-1.0 3.7.4 3.7.4-beta-1.0 3.7.5 3.7.6 3.7.7 3.7.8 3.7.9 3.8.0 3.9.0 3.9.1 3.9.2 3.9.3 3.9.4
wp-all-import / plugin.php
wp-all-import Last commit date
actions 11 years ago classes 11 years ago config 11 years ago controllers 11 years ago filters 11 years ago helpers 11 years ago i18n 11 years ago libraries 11 years ago models 11 years ago shortcodes 11 years ago static 11 years ago views 11 years ago banner-772x250.png 11 years ago plugin.php 11 years ago readme.txt 11 years ago schema.php 11 years ago screenshot-1.png 11 years ago screenshot-2.png 11 years ago screenshot-3.png 11 years ago screenshot-4.png 11 years ago
plugin.php
907 lines
1 <?php
2 /*
3 Plugin Name: WP All Import
4 Plugin URI: http://www.wpallimport.com/upgrade-to-pro?utm_source=wordpress.org&utm_medium=plugins-page&utm_campaign=free+plugin
5 Description: The most powerful solution for importing XML and CSV files to WordPress. Create Posts and Pages with content from any XML or CSV file. A paid upgrade to WP All Import Pro is available for support and additional features.
6 Version: 3.2.2
7 Author: Soflyy
8 */
9
10 /**
11 * Plugin root dir with forward slashes as directory separator regardless of actuall DIRECTORY_SEPARATOR value
12 * @var string
13 */
14 define('PMXI_ROOT_DIR', str_replace('\\', '/', dirname(__FILE__)));
15 /**
16 * Plugin root url for referencing static content
17 * @var string
18 */
19 define('PMXI_ROOT_URL', rtrim(plugin_dir_url(__FILE__), '/'));
20 /**
21 * Plugin prefix for making names unique (be aware that this variable is used in conjuction with naming convention,
22 * i.e. in order to change it one must not only modify this constant but also rename all constants, classes and functions which
23 * names composed using this prefix)
24 * @var string
25 */
26 define('PMXI_PREFIX', 'pmxi_');
27
28 define('PMXI_VERSION', '3.2.2');
29
30 define('PMXI_EDITION', 'free');
31
32 /**
33 * Main plugin file, Introduces MVC pattern
34 *
35 * @singletone
36 * @author Pavel Kulbakin <p.kulbakin@gmail.com>
37 */
38 final class PMXI_Plugin {
39 /**
40 * Singletone instance
41 * @var PMXI_Plugin
42 */
43 protected static $instance;
44
45 /**
46 * Plugin options
47 * @var array
48 */
49 protected $options = array();
50
51 /**
52 * Plugin root dir
53 * @var string
54 */
55 const ROOT_DIR = PMXI_ROOT_DIR;
56 /**
57 * Plugin root URL
58 * @var string
59 */
60 const ROOT_URL = PMXI_ROOT_URL;
61 /**
62 * Prefix used for names of shortcodes, action handlers, filter functions etc.
63 * @var string
64 */
65 const PREFIX = PMXI_PREFIX;
66 /**
67 * Plugin file path
68 * @var string
69 */
70 const FILE = __FILE__;
71 /**
72 * Max allowed file size (bytes) to import in default mode
73 * @var int
74 */
75 const LARGE_SIZE = 0; // all files will importing in large import mode
76
77 public static $session = null;
78
79 public static $encodings = array('UTF-8', 'UTF-16', 'Windows-1250', 'Windows-1251', 'Windows-1252', 'Windows-1253', 'Windows-1254', 'Windows-1255', 'Windows-1256', 'Windows-1257', 'Windows-1258', 'ISO-8859-1', 'ISO-8859-2', 'ISO-8859-3', 'ISO-8859-4', 'ISO-8859-5', 'ISO-8859-6', 'ISO-8859-7', 'ISO-8859-8', 'ISO-8859-9', 'ISO-8859-10', 'KOI8-R', 'KOI8-U');
80
81 public static $is_csv = false;
82
83 public static $csv_path = false;
84
85 /**
86 * Return singletone instance
87 * @return PMXI_Plugin
88 */
89 static public function getInstance() {
90 if (self::$instance == NULL) {
91 self::$instance = new self();
92 }
93 return self::$instance;
94 }
95
96 /**
97 * Common logic for requestin plugin info fields
98 */
99 public function __call($method, $args) {
100 if (preg_match('%^get(.+)%i', $method, $mtch)) {
101 $info = get_plugin_data(self::FILE);
102 if (isset($info[$mtch[1]])) {
103 return $info[$mtch[1]];
104 }
105 }
106 throw new Exception("Requested method " . get_class($this) . "::$method doesn't exist.");
107 }
108
109 /**
110 * Get path to plagin dir relative to wordpress root
111 * @param bool[optional] $noForwardSlash Whether path should be returned withot forwarding slash
112 * @return string
113 */
114 public function getRelativePath($noForwardSlash = false) {
115 $wp_root = str_replace('\\', '/', ABSPATH);
116 return ($noForwardSlash ? '' : '/') . str_replace($wp_root, '', self::ROOT_DIR);
117 }
118
119 /**
120 * Check whether plugin is activated as network one
121 * @return bool
122 */
123 public function isNetwork() {
124 if ( !is_multisite() )
125 return false;
126
127 $plugins = get_site_option('active_sitewide_plugins');
128 if (isset($plugins[plugin_basename(self::FILE)]))
129 return true;
130
131 return false;
132 }
133
134 /**
135 * Check whether permalinks is enabled
136 * @return bool
137 */
138 public function isPermalinks() {
139 global $wp_rewrite;
140
141 return $wp_rewrite->using_permalinks();
142 }
143
144 /**
145 * Return prefix for plugin database tables
146 * @return string
147 */
148 public function getTablePrefix() {
149 global $wpdb;
150
151 //return ($this->isNetwork() ? $wpdb->base_prefix : $wpdb->prefix) . self::PREFIX;
152 return $wpdb->prefix . self::PREFIX;
153 }
154
155 /**
156 * Return prefix for wordpress database tables
157 * @return string
158 */
159 public function getWPPrefix() {
160 global $wpdb;
161 return ($this->isNetwork()) ? $wpdb->base_prefix : $wpdb->prefix;
162 }
163
164 /**
165 * Class constructor containing dispatching logic
166 * @param string $rootDir Plugin root dir
167 * @param string $pluginFilePath Plugin main file
168 */
169 protected function __construct() {
170
171 $this->load_plugin_textdomain();
172
173 // regirster autoloading method
174 if (function_exists('__autoload') and ! in_array('__autoload', spl_autoload_functions())) { // make sure old way of autoloading classes is not broken
175 spl_autoload_register('__autoload');
176 }
177 spl_autoload_register(array($this, '__autoload'));
178
179 // register helpers
180 if (is_dir(self::ROOT_DIR . '/helpers')) foreach (PMXI_Helper::safe_glob(self::ROOT_DIR . '/helpers/*.php', PMXI_Helper::GLOB_RECURSE | PMXI_Helper::GLOB_PATH) as $filePath) {
181 require_once $filePath;
182 }
183
184 // create history folder
185 $uploads = wp_upload_dir();
186
187 $wpallimportDirs = array('wpallimport', 'wpallimport/logs', 'wpallimport/files', 'wpallimport/temp', 'wpallimport/uploads');
188
189 foreach ($wpallimportDirs as $dir) {
190
191 if ( !is_dir($uploads['basedir'] . '/' . $dir)) wp_mkdir_p($uploads['basedir'] . '/' . $dir);
192
193 if ( ! @file_exists($uploads['basedir'] . '/' . $dir . '/index.php') )
194 @touch( $uploads['basedir'] . '/' . $dir . '/index.php' );
195
196 }
197
198 // init plugin options
199 $option_name = get_class($this) . '_Options';
200 $options_default = PMXI_Config::createFromFile(self::ROOT_DIR . '/config/options.php')->toArray();
201 $this->options = array_intersect_key(get_option($option_name, array()), $options_default) + $options_default;
202 $this->options = array_intersect_key($options_default, array_flip(array('info_api_url'))) + $this->options; // make sure hidden options apply upon plugin reactivation
203 if ('' == $this->options['cron_job_key']) $this->options['cron_job_key'] = url_title(rand_char(12));
204
205 update_option($option_name, $this->options);
206 $this->options = get_option(get_class($this) . '_Options');
207
208 register_activation_hook(self::FILE, array($this, '__activation'));
209
210 // register action handlers
211 if (is_dir(self::ROOT_DIR . '/actions')) if (is_dir(self::ROOT_DIR . '/actions')) foreach (PMXI_Helper::safe_glob(self::ROOT_DIR . '/actions/*.php', PMXI_Helper::GLOB_RECURSE | PMXI_Helper::GLOB_PATH) as $filePath) {
212 require_once $filePath;
213 $function = $actionName = basename($filePath, '.php');
214 if (preg_match('%^(.+?)[_-](\d+)$%', $actionName, $m)) {
215 $actionName = $m[1];
216 $priority = intval($m[2]);
217 } else {
218 $priority = 10;
219 }
220 add_action($actionName, self::PREFIX . str_replace('-', '_', $function), $priority, 99); // since we don't know at this point how many parameters each plugin expects, we make sure they will be provided with all of them (it's unlikely any developer will specify more than 99 parameters in a function)
221 }
222
223 // register filter handlers
224 if (is_dir(self::ROOT_DIR . '/filters')) foreach (PMXI_Helper::safe_glob(self::ROOT_DIR . '/filters/*.php', PMXI_Helper::GLOB_RECURSE | PMXI_Helper::GLOB_PATH) as $filePath) {
225 require_once $filePath;
226 $function = $actionName = basename($filePath, '.php');
227 if (preg_match('%^(.+?)[_-](\d+)$%', $actionName, $m)) {
228 $actionName = $m[1];
229 $priority = intval($m[2]);
230 } else {
231 $priority = 10;
232 }
233 add_filter($actionName, self::PREFIX . str_replace('-', '_', $function), $priority, 99); // since we don't know at this point how many parameters each plugin expects, we make sure they will be provided with all of them (it's unlikely any developer will specify more than 99 parameters in a function)
234 }
235
236 // register shortcodes handlers
237 if (is_dir(self::ROOT_DIR . '/shortcodes')) foreach (PMXI_Helper::safe_glob(self::ROOT_DIR . '/shortcodes/*.php', PMXI_Helper::GLOB_RECURSE | PMXI_Helper::GLOB_PATH) as $filePath) {
238 $tag = strtolower(str_replace('/', '_', preg_replace('%^' . preg_quote(self::ROOT_DIR . '/shortcodes/', '%') . '|\.php$%', '', $filePath)));
239 add_shortcode($tag, array($this, 'shortcodeDispatcher'));
240 }
241
242 // register admin page pre-dispatcher
243 add_action('admin_init', array($this, '__adminInit'));
244 add_action('admin_init', array($this, '_fix_options'));
245
246 }
247
248 /**
249 * convert imports options
250 * compatibility with version 4.0
251 */
252 public function _fix_options(){
253
254 $imports = new PMXI_Import_List();
255 $post = new PMXI_Post_Record();
256
257 $templates = new PMXI_Template_List();
258 $template = new PMXI_Template_Record();
259
260 $is_migrated = get_option('pmxi_is_migrated');
261
262 $uploads = wp_upload_dir();
263
264 if ( empty($is_migrated) or version_compare($is_migrated, PMXI_VERSION) < 0 ){
265
266 if ( empty($is_migrated) ){ // plugin version less than 3.2.0
267
268 pmxi_rmdir($uploads['basedir'] . '/wpallimport_history');
269 pmxi_rmdir($uploads['basedir'] . '/wpallimport_logs');
270
271 foreach ($imports->setColumns($imports->getTable() . '.*')->getBy(array('id !=' => ''))->convertRecords() as $imp){
272
273 $imp->getById($imp->id);
274
275 if ( ! $imp->isEmpty() and ! empty($imp->template)){
276
277 $options = array_merge($imp->options, $imp->template);
278
279 $this->__ver_4_transition_fix($options);
280
281 $imp->set(array(
282 'options' => $options
283 ))->update();
284
285 if ($imp->type == 'file'){
286 $imp->set(array(
287 'path' => $uploads['basedir'] . '/wpallimport/files/' . basename($imp->path)
288 ))->update();
289 }
290 }
291 }
292
293 foreach ($templates->setColumns($templates->getTable() . '.*')->getBy(array('id !=' => ''))->convertRecords() as $tpl){
294
295 $tpl->getById($tpl->id);
296
297 if ( ! $tpl->isEmpty() and ! empty($tpl->title) ) {
298
299 $opt = ( empty($tpl->options) ) ? array() : $tpl->options;
300
301 $options = array_merge($opt, array(
302 'title' => $tpl->title,
303 'content' => $tpl->content,
304 'is_keep_linebreaks' => $tpl->is_keep_linebreaks,
305 'is_leave_html' => $tpl->is_leave_html,
306 'fix_characters' => $tpl->fix_characters
307 ));
308
309 $this->__ver_4_transition_fix($options);
310
311 $tpl->set(array(
312 'options' => $options
313 ))->update();
314
315 }
316
317 }
318
319 $this->__fix_db_schema(); // feature to version 3.2.0
320
321 }
322 else {
323
324 // migration fixes for vesions
325 switch ($is_migrated) {
326
327 case '3.2.0':
328 case '3.2.1':
329 $this->__fix_db_schema(); // feature to version 3.2.0
330 break;
331
332 default:
333 # code...
334 break;
335 }
336
337 }
338 update_option('pmxi_is_migrated', PMXI_VERSION);
339 }
340 }
341
342 public function __ver_4_transition_fix( &$options ){
343
344 $options['wizard_type'] = ($options['duplicate_matching'] == 'auto') ? 'new' : 'matching';
345
346 if ($options['download_images']){
347 $options['download_images'] = 'yes';
348 $options['download_featured_image'] = $options['featured_image'];
349 $options['featured_image'] = '';
350 $options['download_featured_delim'] = $options['featured_delim'];
351 $options['featured_delim'] = '';
352 }
353
354 if ($options['set_image_meta_data']){
355 $options['set_image_meta_title'] = 1;
356 $options['set_image_meta_caption'] = 1;
357 $options['set_image_meta_alt'] = 1;
358 $options['set_image_meta_description'] = 1;
359 }
360
361 if ("" == $options['custom_type']) $options['custom_type'] = $options['type'];
362
363 $exclude_taxonomies = (class_exists('PMWI_Plugin')) ? array('post_format', 'product_type') : array('post_format');
364 $post_taxonomies = array_diff_key(get_taxonomies_by_object_type(array($options['custom_type']), 'object'), array_flip($exclude_taxonomies));
365
366 $options['tax_logic'] = array();
367 $options['tax_assing'] = array();
368 $options['tax_multiple_xpath'] = array();
369 $options['tax_multiple_delim'] = array();
370 $options['tax_hierarchical_logic'] = array();
371
372 if ( ! empty($post_taxonomies)):
373 foreach ($post_taxonomies as $ctx):
374
375 $options['tax_logic'][$ctx->name] = ($ctx->hierarchical) ? 'hierarchical' : 'multiple';
376
377 if ($ctx->name == 'category'){
378 $options['post_taxonomies']['category'] = $options['categories'];
379 }
380 elseif ($ctx->name == 'post_tag' ){
381 $options['tax_assing']['post_tag'] = 1;
382 $options['tax_multiple_xpath']['post_tag'] = $options['tags'];
383 $options['tax_multiple_delim']['post_tag'] = $options['tags_delim'];
384 }
385
386 if ( ! empty($options['post_taxonomies'][$ctx->name])){
387
388 $taxonomies_hierarchy = json_decode($options['post_taxonomies'][$ctx->name], true);
389 $options['tax_assing'][$ctx->name] = (!empty($taxonomies_hierarchy[0]['assign'])) ? 1 : 0;
390
391 if ($options['tax_logic'][$ctx->name] == 'multiple') {
392 $options['tax_multiple_xpath'][$ctx->name] = (!empty($taxonomies_hierarchy[0]['xpath'])) ? $taxonomies_hierarchy[0]['xpath'] : '';
393 $options['tax_multiple_delim'][$ctx->name] = (!empty($taxonomies_hierarchy[0]['delim'])) ? $taxonomies_hierarchy[0]['delim'] : '';
394 }
395 else{
396
397 $options['tax_hierarchical_logic'][$ctx->name] = 'manual';
398
399 }
400 }
401
402 endforeach;
403 endif;
404 }
405
406 /**
407 * pre-dispatching logic for admin page controllers
408 */
409 public function __adminInit() {
410
411 self::$session = new PMXI_Handler();
412
413 $input = new PMXI_Input();
414 $page = strtolower($input->getpost('page', ''));
415
416 if (preg_match('%^' . preg_quote(str_replace('_', '-', self::PREFIX), '%') . '([\w-]+)$%', $page)) {
417 //$this->adminDispatcher($page, strtolower($input->getpost('action', 'index')));
418
419 $action = strtolower($input->getpost('action', 'index'));
420
421 // capitalize prefix and first letters of class name parts
422 if (function_exists('preg_replace_callback')){
423 $controllerName = preg_replace_callback('%(^' . preg_quote(self::PREFIX, '%') . '|_).%', array($this, "replace_callback"),str_replace('-', '_', $page));
424 }
425 else{
426 $controllerName = preg_replace('%(^' . preg_quote(self::PREFIX, '%') . '|_).%e', 'strtoupper("$0")', str_replace('-', '_', $page));
427 }
428 $actionName = str_replace('-', '_', $action);
429 if (method_exists($controllerName, $actionName)) {
430 $this->_admin_current_screen = (object)array(
431 'id' => $controllerName,
432 'base' => $controllerName,
433 'action' => $actionName,
434 'is_ajax' => strpos($_SERVER["HTTP_ACCEPT"], 'json') !== false,
435 'is_network' => is_network_admin(),
436 'is_user' => is_user_admin(),
437 );
438 add_filter('current_screen', array($this, 'getAdminCurrentScreen'));
439 add_filter('admin_body_class', create_function('', 'return "' . 'wpallimport-plugin";'));
440
441 $controller = new $controllerName();
442 if ( ! $controller instanceof PMXI_Controller_Admin) {
443 throw new Exception("Administration page `$page` matches to a wrong controller type.");
444 }
445
446 if ($this->_admin_current_screen->is_ajax) { // ajax request
447 $controller->$action();
448 do_action('pmxi_action_after');
449 die(); // stop processing since we want to output only what controller is randered, nothing in addition
450 } elseif ( ! $controller->isInline) {
451 @ob_start();
452 $controller->$action();
453 self::$buffer = @ob_get_clean();
454 } else {
455 self::$buffer_callback = array($controller, $action);
456 }
457 } else { // redirect to dashboard if requested page and/or action don't exist
458 wp_redirect(admin_url()); die();
459 }
460
461 }
462
463 }
464
465 /**
466 * Dispatch shorttag: create corresponding controller instance and call its index method
467 * @param array $args Shortcode tag attributes
468 * @param string $content Shortcode tag content
469 * @param string $tag Shortcode tag name which is being dispatched
470 * @return string
471 */
472 public function shortcodeDispatcher($args, $content, $tag) {
473
474 $controllerName = self::PREFIX . preg_replace('%(^|_).%e', 'strtoupper("$0")', $tag); // capitalize first letters of class name parts and add prefix
475 $controller = new $controllerName();
476 if ( ! $controller instanceof PMXI_Controller) {
477 throw new Exception("Shortcode `$tag` matches to a wrong controller type.");
478 }
479 ob_start();
480 $controller->index($args, $content);
481 return ob_get_clean();
482 }
483
484 static $buffer = NULL;
485 static $buffer_callback = NULL;
486
487 /**
488 * Dispatch admin page: call corresponding controller based on get parameter `page`
489 * The method is called twice: 1st time as handler `parse_header` action and then as admin menu item handler
490 * @param string[optional] $page When $page set to empty string ealier buffered content is outputted, otherwise controller is called based on $page value
491 */
492 public function adminDispatcher($page = '', $action = 'index') {
493 if ('' === $page) {
494 if ( ! is_null(self::$buffer)) {
495 echo '<div class="wrap">';
496 echo self::$buffer;
497 do_action('pmxi_action_after');
498 echo '</div>';
499 } elseif ( ! is_null(self::$buffer_callback)) {
500 echo '<div class="wrap">';
501 call_user_func(self::$buffer_callback);
502 do_action('pmxi_action_after');
503 echo '</div>';
504 } else {
505 throw new Exception('There is no previousely buffered content to display.');
506 }
507 }
508 }
509
510 public function replace_callback($matches){
511 return strtoupper($matches[0]);
512 }
513
514 protected $_admin_current_screen = NULL;
515 public function getAdminCurrentScreen()
516 {
517 return $this->_admin_current_screen;
518 }
519
520 /**
521 * Autoloader
522 * It's assumed class name consists of prefix folloed by its name which in turn corresponds to location of source file
523 * if `_` symbols replaced by directory path separator. File name consists of prefix folloed by last part in class name (i.e.
524 * symbols after last `_` in class name)
525 * When class has prefix it's source is looked in `models`, `controllers`, `shortcodes` folders, otherwise it looked in `core` or `library` folder
526 *
527 * @param string $className
528 * @return bool
529 */
530 public function __autoload($className) {
531 $is_prefix = false;
532 $filePath = str_replace('_', '/', preg_replace('%^' . preg_quote(self::PREFIX, '%') . '%', '', strtolower($className), 1, $is_prefix)) . '.php';
533 if ( ! $is_prefix) { // also check file with original letter case
534 $filePathAlt = $className . '.php';
535 }
536 foreach ($is_prefix ? array('models', 'controllers', 'shortcodes', 'classes') : array('libraries') as $subdir) {
537 $path = self::ROOT_DIR . '/' . $subdir . '/' . $filePath;
538 if (is_file($path)) {
539 require $path;
540 return TRUE;
541 }
542 if ( ! $is_prefix) {
543 $pathAlt = self::ROOT_DIR . '/' . $subdir . '/' . $filePathAlt;
544 if (is_file($pathAlt)) {
545 require $pathAlt;
546 return TRUE;
547 }
548 }
549 }
550
551 return FALSE;
552 }
553
554 /**
555 * Get plugin option
556 * @param string[optional] $option Parameter to return, all array of options is returned if not set
557 * @return mixed
558 */
559 public function getOption($option = NULL) {
560 if (is_null($option)) {
561 return $this->options;
562 } else if (isset($this->options[$option])) {
563 return $this->options[$option];
564 } else {
565 throw new Exception("Specified option is not defined for the plugin");
566 }
567 }
568 /**
569 * Update plugin option value
570 * @param string $option Parameter name or array of name => value pairs
571 * @param mixed[optional] $value New value for the option, if not set than 1st parameter is supposed to be array of name => value pairs
572 * @return array
573 */
574 public function updateOption($option, $value = NULL) {
575 is_null($value) or $option = array($option => $value);
576 if (array_diff_key($option, $this->options)) {
577 throw new Exception("Specified option is not defined for the plugin");
578 }
579 $this->options = $option + $this->options;
580 update_option(get_class($this) . '_Options', $this->options);
581
582 return $this->options;
583 }
584
585 /**
586 * Plugin activation logic
587 */
588 public function __activation() {
589 // uncaught exception doesn't prevent plugin from being activated, therefore replace it with fatal error so it does
590 set_exception_handler(create_function('$e', 'trigger_error($e->getMessage(), E_USER_ERROR);'));
591
592 // create plugin options
593 $option_name = get_class($this) . '_Options';
594 $options_default = PMXI_Config::createFromFile(self::ROOT_DIR . '/config/options.php')->toArray();
595 $wpai_options = get_option($option_name, false);
596 if ( ! $wpai_options ) update_option($option_name, $options_default);
597
598 // create/update required database tables
599 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
600 require self::ROOT_DIR . '/schema.php';
601 global $wpdb;
602
603 if (function_exists('is_multisite') && is_multisite()) {
604 // check if it is a network activation - if so, run the activation function for each blog id
605 if (isset($_GET['networkwide']) && ($_GET['networkwide'] == 1)) {
606 $old_blog = $wpdb->blogid;
607 // Get all blog ids
608 $blogids = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
609 foreach ($blogids as $blog_id) {
610 switch_to_blog($blog_id);
611 require self::ROOT_DIR . '/schema.php';
612 dbDelta($plugin_queries);
613
614 // sync data between plugin tables and wordpress (mostly for the case when plugin is reactivated)
615
616 $post = new PMXI_Post_Record();
617 $wpdb->query('DELETE FROM ' . $post->getTable() . ' WHERE post_id NOT IN (SELECT ID FROM ' . $wpdb->posts . ')');
618 }
619 switch_to_blog($old_blog);
620 return;
621 }
622 }
623
624 dbDelta($plugin_queries);
625
626 // sync data between plugin tables and wordpress (mostly for the case when plugin is reactivated)
627
628 $post = new PMXI_Post_Record();
629 $wpdb->query('DELETE FROM ' . $post->getTable() . ' WHERE post_id NOT IN (SELECT ID FROM ' . $wpdb->posts . ')');
630
631 }
632
633 /**
634 * Load Localisation files.
635 *
636 * Note: the first-loaded translation file overrides any following ones if the same translation is present
637 *
638 * @access public
639 * @return void
640 */
641 public function load_plugin_textdomain() {
642 $locale = apply_filters( 'plugin_locale', get_locale(), 'pmxi_plugin' );
643
644 load_plugin_textdomain( 'pmxi_plugin', false, dirname( plugin_basename( __FILE__ ) ) . "/i18n/languages" );
645 }
646
647 public function __fix_db_schema(){
648
649 $uploads = wp_upload_dir();
650
651 if ( ! is_dir($uploads['basedir'] . '/wpallimport/logs') or ! is_writable($uploads['basedir'] . '/wpallimport/logs')) {
652 die(sprintf(__('Uploads folder %s must be writable', 'pmxi_plugin'), $uploads['basedir'] . '/wpallimport/logs'));
653 }
654
655 if ( ! is_dir($uploads['basedir'] . '/wpallimport') or ! is_writable($uploads['basedir'] . '/wpallimport')) {
656 die(sprintf(__('Uploads folder %s must be writable', 'pmxi_plugin'), $uploads['basedir'] . '/wpallimport'));
657 }
658
659 $table = $table = $this->getTablePrefix() . 'files';
660 global $wpdb;
661 $tablefields = $wpdb->get_results("DESCRIBE {$table};");
662 // For every field in the table
663 foreach ($tablefields as $tablefield) {
664 if ('contents' == $tablefield->Field) {
665 $list = new PMXI_File_List();
666 for ($i = 1; $list->getBy(NULL, 'id', $i, 1)->count(); $i++) {
667 foreach ($list->convertRecords() as $file) {
668 $file->save(); // resave file for file to be stored in uploads folder
669 }
670 }
671
672 $wpdb->query("ALTER TABLE {$table} DROP " . $tablefield->Field);
673 break;
674 }
675 }
676
677 $table = $this->getTablePrefix() . 'imports';
678
679 $tablefields = $wpdb->get_results("DESCRIBE {$table};");
680 $parent_import_id = false;
681 $iteration = false;
682 $deleted = false;
683 $executing = false;
684 $canceled = false;
685 $canceled_on = false;
686 $failed = false;
687 $failed_on = false;
688 $settings_update_on = false;
689 $last_activity = false;
690
691 // Check if field exists
692 foreach ($tablefields as $tablefield) {
693 if ('parent_import_id' == $tablefield->Field) $parent_import_id = true;
694 if ('iteration' == $tablefield->Field) $iteration = true;
695 if ('deleted' == $tablefield->Field) $deleted = true;
696 if ('executing' == $tablefield->Field) $executing = true;
697 if ('canceled' == $tablefield->Field) $canceled = true;
698 if ('canceled_on' == $tablefield->Field) $canceled_on = true;
699 if ('failed' == $tablefield->Field) $failed = true;
700 if ('failed_on' == $tablefield->Field) $failed_on = true;
701 if ('settings_update_on' == $tablefield->Field) $settings_update_on = true;
702 if ('last_activity' == $tablefield->Field) $last_activity = true;
703 }
704
705 if (!$parent_import_id) $wpdb->query("ALTER TABLE {$table} ADD `parent_import_id` BIGINT(20) NOT NULL DEFAULT 0;");
706 if (!$iteration) $wpdb->query("ALTER TABLE {$table} ADD `iteration` BIGINT(20) NOT NULL DEFAULT 0;");
707 if (!$deleted) $wpdb->query("ALTER TABLE {$table} ADD `deleted` BIGINT(20) NOT NULL DEFAULT 0;");
708 if (!$executing) $wpdb->query("ALTER TABLE {$table} ADD `executing` BOOL NOT NULL DEFAULT 0;");
709 if (!$canceled) $wpdb->query("ALTER TABLE {$table} ADD `canceled` BOOL NOT NULL DEFAULT 0;");
710 if (!$canceled_on) $wpdb->query("ALTER TABLE {$table} ADD `canceled_on` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00';");
711 if (!$failed) $wpdb->query("ALTER TABLE {$table} ADD `failed` BOOL NOT NULL DEFAULT 0;");
712 if (!$failed_on) $wpdb->query("ALTER TABLE {$table} ADD `failed_on` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00';");
713 if (!$settings_update_on) $wpdb->query("ALTER TABLE {$table} ADD `settings_update_on` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00';");
714 if (!$last_activity) $wpdb->query("ALTER TABLE {$table} ADD `last_activity` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00';");
715
716 $table = $this->getTablePrefix() . 'posts';
717 $tablefields = $wpdb->get_results("DESCRIBE {$table};");
718 $iteration = false;
719
720 // Check if field exists
721 foreach ($tablefields as $tablefield) {
722 if ('iteration' == $tablefield->Field) $iteration = true;
723 }
724
725 if (!$iteration) $wpdb->query("ALTER TABLE {$table} ADD `iteration` BIGINT(20) NOT NULL DEFAULT 0;");
726
727 if ( ! empty($wpdb->charset))
728 $charset_collate = "DEFAULT CHARACTER SET $wpdb->charset";
729 if ( ! empty($wpdb->collate))
730 $charset_collate .= " COLLATE $wpdb->collate";
731
732 $table_prefix = $this->getTablePrefix();
733
734 $wpdb->query("CREATE TABLE IF NOT EXISTS {$table_prefix}history (
735 id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
736 import_id BIGINT(20) UNSIGNED NOT NULL,
737 type ENUM('manual','processing','trigger','continue','') NOT NULL DEFAULT '',
738 time_run TEXT,
739 date DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
740 summary TEXT,
741 PRIMARY KEY (id)
742 ) $charset_collate;");
743 }
744
745 /**
746 * Method returns default import options, main utility of the method is to avoid warnings when new
747 * option is introduced but already registered imports don't have it
748 */
749 public static function get_default_import_options() {
750 return array(
751 'type' => 'post',
752 'wizard_type' => 'new',
753 'custom_type' => '',
754 'featured_delim' => ',',
755 'atch_delim' => ',',
756 'post_taxonomies' => array(),
757 'parent' => 0,
758 'order' => 0,
759 'status' => 'publish',
760 'page_template' => 'default',
761 'page_taxonomies' => array(),
762 'date_type' => 'specific',
763 'date' => 'now',
764 'date_start' => 'now',
765 'date_end' => 'now',
766 'custom_name' => array(),
767 'custom_value' => array(),
768 'custom_format' => array(),
769 'custom_mapping' => array(),
770 'serialized_values' => array(),
771 'custom_mapping_rules' => array(),
772 'comment_status' => 'open',
773 'ping_status' => 'open',
774 'create_draft' => 'no',
775 'author' => '',
776 'post_excerpt' => '',
777 'post_slug' => '',
778 'attachments' => '',
779 'is_import_specified' => 0,
780 'import_specified' => '',
781 'is_delete_source' => 0,
782 'is_cloak' => 0,
783 'unique_key' => '',
784 'tmp_unique_key' => '',
785 'feed_type' => 'auto',
786
787 'create_new_records' => 1,
788 'is_delete_missing' => 0,
789 'set_missing_to_draft' => 0,
790 'is_update_missing_cf' => 0,
791 'update_missing_cf_name' => '',
792 'update_missing_cf_value' => '',
793
794 'is_keep_former_posts' => 'no',
795 'is_update_status' => 1,
796 'is_update_content' => 1,
797 'is_update_title' => 1,
798 'is_update_slug' => 1,
799 'is_update_excerpt' => 1,
800 'is_update_categories' => 1,
801 'is_update_author' => 1,
802 'update_categories_logic' => 'full_update',
803 'taxonomies_list' => array(),
804 'taxonomies_only_list' => array(),
805 'taxonomies_except_list' => array(),
806 'is_update_attachments' => 1,
807 'is_update_images' => 1,
808 'update_images_logic' => 'full_update',
809 'is_update_dates' => 1,
810 'is_update_menu_order' => 1,
811 'is_update_parent' => 1,
812 'is_keep_attachments' => 0,
813 'is_keep_imgs' => 0,
814
815 'is_update_custom_fields' => 1,
816 'update_custom_fields_logic' => 'full_update',
817 'custom_fields_list' => array(),
818 'custom_fields_only_list' => array(),
819 'custom_fields_except_list' => array(),
820
821 'duplicate_matching' => 'auto',
822 'duplicate_indicator' => 'title',
823 'custom_duplicate_name' => '',
824 'custom_duplicate_value' => '',
825 'is_update_previous' => 0,
826 'is_scheduled' => '',
827 'scheduled_period' => '',
828 'friendly_name' => '',
829 'records_per_request' => 20,
830 'auto_rename_images' => 0,
831 'auto_rename_images_suffix' => '',
832 'images_name' => 'filename',
833 'post_format' => 'standard',
834 'encoding' => 'UTF-8',
835 'delimiter' => '',
836 'image_meta_title' => '',
837 'image_meta_title_delim' => ',',
838 'image_meta_caption' => '',
839 'image_meta_caption_delim' => ',',
840 'image_meta_alt' => '',
841 'image_meta_alt_delim' => ',',
842 'image_meta_description' => '',
843 'image_meta_description_delim' => ',',
844 'status_xpath' => '',
845 'download_images' => 'yes',
846 'converted_options' => 0,
847 'update_all_data' => 'yes',
848 'is_fast_mode' => 0,
849 'chuncking' => 1,
850 'import_processing' => 'ajax',
851
852 'title' => '',
853 'content' => '',
854 'name' => '',
855 'is_keep_linebreaks' => 0,
856 'is_leave_html' => 0,
857 'fix_characters' => 0,
858
859 'featured_image' => '',
860 'download_featured_image' => '',
861 'download_featured_delim' => ',',
862 'is_featured' => 1,
863 'set_image_meta_title' => 0,
864 'set_image_meta_caption' => 0,
865 'set_image_meta_alt' => 0,
866 'set_image_meta_description' => 0,
867 'auto_set_extension' => 0,
868 'new_extension' => '',
869 'tax_logic' => array(),
870 'tax_assing' => array(),
871 'tax_single_xpath' => array(),
872 'tax_multiple_xpath' => array(),
873 'tax_hierarchical_xpath' => array(),
874 'tax_multiple_delim' => array(),
875 'tax_hierarchical_delim' => array(),
876 'tax_hierarchical_logic' => array(),
877 'tax_enable_mapping' => array(),
878 'tax_mapping' => array(),
879 'nested_files' => array()
880 );
881 }
882
883 /*
884 * Convert csv to xml
885 */
886 public static function csv_to_xml($csv_url){
887
888 include_once(self::ROOT_DIR.'/libraries/XmlImportCsvParse.php');
889
890 $csv = new PMXI_CsvParser($csv_url);
891
892 $wp_uploads = wp_upload_dir();
893 $tmpname = wp_unique_filename($wp_uploads['path'], str_replace("csv", "xml", basename($csv_url)));
894 $xml_file = $wp_uploads['path'] .'/'. $tmpname;
895 file_put_contents($xml_file, $csv->toXML());
896 return $xml_file;
897
898 }
899
900 public static function is_ajax(){
901 return strpos($_SERVER["HTTP_ACCEPT"], 'json') !== false;
902 }
903
904 }
905
906 PMXI_Plugin::getInstance();
907