PluginProbe ʕ •ᴥ•ʔ
WP All Import – Drag & Drop Import for CSV, XML, Excel & Google Sheets / 4.0.0
WP All Import – Drag & Drop Import for CSV, XML, Excel & Google Sheets v4.0.0
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
acc 3 years ago actions 9 months ago classes 7 months ago config 2 years ago controllers 7 months ago filters 9 months ago helpers 9 months ago i18n 9 months ago libraries 9 months ago models 9 months ago shortcodes 11 years ago src 9 months ago static 7 months ago vendor 7 months ago views 7 months ago banner-772x250.png 4 years ago composer.json 7 months ago composer.lock 7 months ago plugin.php 7 months ago readme.txt 5 months ago schema.php 1 year 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
1514 lines
1 <?php
2 /*
3 Plugin Name: WP All Import
4 Plugin URI: https://www.wpallimport.com/wordpress-xml-csv-import/?utm_source=import-plugin-free&utm_medium=wp-plugins-page&utm_campaign=upgrade-to-pro
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: 4.0.0
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('WP_ALL_IMPORT_ROOT_DIR', str_replace('\\', '/', dirname(__FILE__)));
15 /**
16 * Plugin root url for referencing static content
17 * @var string
18 */
19 define('WP_ALL_IMPORT_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('WP_ALL_IMPORT_PREFIX', 'pmxi_');
27
28 define('PMXI_VERSION', '4.0.0');
29
30 define('PMXI_EDITION', 'free');
31
32 /**
33 * Plugin root uploads folder name
34 * @var string
35 */
36 define('WP_ALL_IMPORT_UPLOADS_BASE_DIRECTORY', 'wpallimport');
37 /**
38 * Plugin logs folder name
39 * @var string
40 */
41 define('WP_ALL_IMPORT_LOGS_DIRECTORY', WP_ALL_IMPORT_UPLOADS_BASE_DIRECTORY . DIRECTORY_SEPARATOR . 'logs');
42 /**
43 * Plugin files folder name
44 * @var string
45 */
46 define('WP_ALL_IMPORT_FILES_DIRECTORY', WP_ALL_IMPORT_UPLOADS_BASE_DIRECTORY . DIRECTORY_SEPARATOR . 'files');
47 /**
48 * Plugin uploads folder name
49 * @var string
50 */
51 define('WP_ALL_IMPORT_UPLOADS_DIRECTORY', WP_ALL_IMPORT_UPLOADS_BASE_DIRECTORY . DIRECTORY_SEPARATOR . 'uploads');
52 /**
53 * Plugin history folder name
54 * @var string
55 */
56 define('WP_ALL_IMPORT_HISTORY_DIRECTORY', WP_ALL_IMPORT_UPLOADS_BASE_DIRECTORY . DIRECTORY_SEPARATOR . 'history');
57 /**
58 * Plugin temp folder name
59 * @var string
60 */
61 define('WP_ALL_IMPORT_TEMP_DIRECTORY', WP_ALL_IMPORT_UPLOADS_BASE_DIRECTORY . DIRECTORY_SEPARATOR . 'temp');
62
63 /**
64 * Main plugin file, Introduces MVC pattern
65 *
66 * @singletone
67 * @author Maksym Tsypliakov <maksym.tsypliakov@gmail.com>
68 */
69 final class PMXI_Plugin {
70 /**
71 * Singletone instance
72 * @var PMXI_Plugin
73 */
74 protected static $instance;
75
76 /**
77 * Plugin options
78 * @var array
79 */
80 protected $options = array();
81
82 /**
83 * Plugin root dir
84 * @var string
85 */
86 const ROOT_DIR = WP_ALL_IMPORT_ROOT_DIR;
87 /**
88 * Plugin root URL
89 * @var string
90 */
91 const ROOT_URL = WP_ALL_IMPORT_ROOT_URL;
92 /**
93 * Prefix used for names of shortcodes, action handlers, filter functions etc.
94 * @var string
95 */
96 const PREFIX = WP_ALL_IMPORT_PREFIX;
97 /**
98 * Plugin file path
99 * @var string
100 */
101 const FILE = __FILE__;
102 /**
103 * Max allowed file size (bytes) to import in default mode
104 * @var int
105 */
106 const LARGE_SIZE = 0; // all files will importing in large import mode
107
108 public static $session = null;
109
110 public static $is_csv = false;
111
112 public static $csv_path = false;
113
114 /**
115 * @var bool
116 */
117 public static $is_php_allowed = true;
118
119 public static $capabilities = 'setup_network';
120
121 /**
122 * WP All Import logs folder
123 * @var string
124 */
125 const LOGS_DIRECTORY = WP_ALL_IMPORT_LOGS_DIRECTORY;
126 /**
127 * WP All Import files folder
128 * @var string
129 */
130 const FILES_DIRECTORY = WP_ALL_IMPORT_FILES_DIRECTORY;
131 /**
132 * WP All Import temp folder
133 * @var string
134 */
135 const TEMP_DIRECTORY = WP_ALL_IMPORT_TEMP_DIRECTORY;
136 /**
137 * WP All Import uploads folder
138 * @var string
139 */
140 const UPLOADS_DIRECTORY = WP_ALL_IMPORT_UPLOADS_DIRECTORY;
141
142 /**
143 * WP All Import history folder
144 * @var string
145 */
146 const HISTORY_DIRECTORY = WP_ALL_IMPORT_HISTORY_DIRECTORY;
147
148 /**
149 * Language domain key.
150 */
151 const LANGUAGE_DOMAIN = 'wp_all_import_plugin';
152
153 /**
154 * Return singletone instance
155 * @return PMXI_Plugin
156 */
157 static public function getInstance() {
158 if (self::$instance == NULL) {
159 self::$instance = new self();
160 }
161 return self::$instance;
162 }
163
164 static public function getEddName(){
165 return 'WP All Import';
166 }
167
168 /**
169 * Common logic for requestin plugin info fields
170 */
171 public function __call($method, $args) {
172 if (preg_match('%^get(.+)%i', $method, $mtch)) {
173 $info = get_plugin_data(self::FILE);
174 if (isset($info[$mtch[1]])) {
175 return $info[$mtch[1]];
176 }
177 }
178 throw new Exception("Requested method " . get_class($this) . "::$method doesn't exist.");
179 }
180
181 /**
182 * Get path to plagin dir relative to wordpress root
183 * @param bool[optional] $noForwardSlash Whether path should be returned withot forwarding slash
184 * @return string
185 */
186 public function getRelativePath($noForwardSlash = false) {
187 $wp_root = str_replace('\\', '/', ABSPATH);
188 return ($noForwardSlash ? '' : '/') . str_replace($wp_root, '', self::ROOT_DIR);
189 }
190
191 /**
192 * Check whether plugin is activated as network one
193 * @return bool
194 */
195 public function isNetwork() {
196 if ( !is_multisite() )
197 return false;
198
199 $plugins = get_site_option('active_sitewide_plugins');
200 if (isset($plugins[plugin_basename(self::FILE)]))
201 return true;
202
203 return false;
204 }
205
206 /**
207 * Check whether permalinks is enabled
208 * @return bool
209 */
210 public function isPermalinks() {
211 global $wp_rewrite;
212
213 return $wp_rewrite->using_permalinks();
214 }
215
216 /**
217 * Return prefix for plugin database tables
218 * @return string
219 */
220 public function getTablePrefix() {
221 global $wpdb;
222
223 //return ($this->isNetwork() ? $wpdb->base_prefix : $wpdb->prefix) . self::PREFIX;
224 return $wpdb->prefix . self::PREFIX;
225 }
226
227 /**
228 * Return prefix for wordpress database tables
229 * @return string
230 */
231 public function getWPPrefix() {
232 global $wpdb;
233 return ($this->isNetwork()) ? $wpdb->base_prefix : $wpdb->prefix;
234 }
235
236 /**
237 * Class constructor containing dispatching logic
238 * @param string $rootDir Plugin root dir
239 * @param string $pluginFilePath Plugin main file
240 */
241 protected function __construct() {
242
243 if(defined('WPAI_WPAE_ALLOW_INSECURE_MULTISITE') && 1 === WPAI_WPAE_ALLOW_INSECURE_MULTISITE){
244 self::$capabilities = 'manage_options';
245 }
246
247 // register autoloading method
248 spl_autoload_register(array($this, 'autoload'));
249 require_once 'vendor/autoload.php';
250
251 // require acc code
252 if (is_dir(self::ROOT_DIR . '/acc')) foreach (PMXI_Helper::safe_glob(self::ROOT_DIR . '/acc/*.php', PMXI_Helper::GLOB_RECURSE | PMXI_Helper::GLOB_PATH) as $filePath) {
253 require_once $filePath;
254 }
255
256 // register helpers
257 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) {
258 require_once $filePath;
259 }
260
261 // init plugin options
262 $option_name = get_class($this) . '_Options';
263 $options_default = PMXI_Config::createFromFile(self::ROOT_DIR . '/config/options.php')->toArray();
264 $current_options = get_option($option_name, array());
265 if (empty($current_options)) {
266 $current_options = array();
267 }
268
269 $this->options = array_intersect_key($current_options, $options_default) + $options_default;
270 $this->options = array_intersect_key($options_default, array_flip(array('info_api_url'))) + $this->options; // make sure hidden options apply upon plugin reactivation
271 if ('' == $this->options['cron_job_key']) {
272 $this->options['cron_job_key'] = wp_all_import_url_title(wp_all_import_rand_char(12));
273 }
274
275 if ($current_options !== $this->options) {
276 update_option($option_name, $this->options, false);
277 }
278
279 register_activation_hook(self::FILE, array($this, 'activation'));
280
281 // register action handlers
282 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) {
283 require_once $filePath;
284 $function = $actionName = basename($filePath, '.php');
285 if (preg_match('%^(.+?)[_-](\d+)$%', $actionName, $m)) {
286 $actionName = $m[1];
287 $priority = intval($m[2]);
288 } else {
289 $priority = 10;
290 }
291 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)
292 }
293
294 // register filter handlers
295 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) {
296 require_once $filePath;
297 $function = $actionName = basename($filePath, '.php');
298 if (preg_match('%^(.+?)[_-](\d+)$%', $actionName, $m)) {
299 $actionName = $m[1];
300 $priority = intval($m[2]);
301 } else {
302 $priority = 10;
303 }
304 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)
305 }
306
307 // register admin page pre-dispatcher
308 add_action('admin_init', array($this, 'adminInit'));
309 add_action('admin_init', array($this, 'fix_options'));
310 add_action('init', array($this, 'init'));
311
312 add_action( 'plugins_loaded', array( $this, 'setup_allimport_dir' ) );
313
314 }
315
316 /**
317 * Determines is process running from cli.
318 *
319 * @return bool
320 */
321 public function isCli() {
322 return php_sapi_name() === 'cli';
323 }
324
325 /**
326 * Setup required directory.
327 */
328 public function setup_allimport_dir() {
329 // create history folder
330 $uploads = wp_upload_dir();
331
332 $wpallimportDirs = array( WP_ALL_IMPORT_UPLOADS_BASE_DIRECTORY, self::LOGS_DIRECTORY, self::FILES_DIRECTORY, self::TEMP_DIRECTORY, self::UPLOADS_DIRECTORY, self::HISTORY_DIRECTORY);
333
334 foreach ($wpallimportDirs as $destination) {
335
336 $dir = $uploads['basedir'] . DIRECTORY_SEPARATOR . $destination;
337
338 if ( !is_dir($dir)) wp_mkdir_p($dir);
339
340 if ( ! @file_exists($dir . DIRECTORY_SEPARATOR . 'index.php') ) @touch( $dir . DIRECTORY_SEPARATOR . 'index.php' );
341
342 }
343 }
344
345 public function init(){
346 $this->load_plugin_textdomain();
347 self::$is_php_allowed = apply_filters('wp_all_import_is_php_allowed', self::wpai_determine_php_allowed());
348 }
349
350 /**
351 * Determine if PHP execution should be allowed based on WordPress security constants.
352 *
353 * Only restricts PHP execution when BOTH DISALLOW_FILE_EDIT and DISALLOW_FILE_MODS are set to true.
354 * This is the only configuration that creates a true security boundary where the plugin would
355 * grant NEW code execution capabilities that don't already exist.
356 *
357 * @return bool True if PHP execution is allowed, false otherwise.
358 */
359 public static function wpai_determine_php_allowed() {
360 // Only restrict if BOTH security constants are set
361 // This is the only configuration that creates a true security boundary
362 if (defined('DISALLOW_FILE_EDIT') && DISALLOW_FILE_EDIT &&
363 defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS) {
364 return false;
365 }
366
367 // Otherwise allow - user has other code execution vectors anyway
368 // - If only DISALLOW_FILE_EDIT is set: admin can still install plugins (file manager, code snippets, etc.)
369 // - If only DISALLOW_FILE_MODS is set: admin can still edit theme/plugin files directly
370 // - If neither is set: admin has full code execution capabilities
371 return true;
372 }
373
374 public function plugin_row_meta($links, $file)
375 {
376 if ( $file == plugin_basename( __FILE__ ) ) {
377 $row_meta = array(
378 'pro' => '<a href="http://www.wpallimport.com" target="_blank" title="' . esc_attr( __( 'WP All Import Pro Version', 'wp_all_import_plugin' ) ) . '">' . __( 'Pro Version', 'wp_all_import_plugin' ) . '</a>',
379 );
380
381 return array_merge( $links, $row_meta );
382 }
383
384 return (array) $links;
385 }
386
387
388 /**
389 * convert imports options
390 * compatibility with version 3.2.3
391 */
392 public function fix_options(){
393
394 global $wpdb;
395
396 $imports = new PMXI_Import_List();
397 $post = new PMXI_Post_Record();
398
399 $templates = new PMXI_Template_List();
400 $template = new PMXI_Template_Record();
401
402 $is_migrated = get_option('pmxi_is_migrated');
403
404 $uploads = wp_upload_dir();
405
406 if ( empty($is_migrated) or version_compare($is_migrated, PMXI_VERSION) < 0 ){ //PMXI_VERSION
407
408 $commit_migration = true;
409
410 if ( empty($is_migrated) ){ // plugin version less than 4.0.0
411
412 if ( is_dir($uploads['basedir'] . '/wpallimport_history') ) {
413 wp_all_import_rmdir($uploads['basedir'] . '/wpallimport_history');
414 }
415 if ( is_dir($uploads['basedir'] . '/wpallimport_logs') ) {
416 wp_all_import_rmdir($uploads['basedir'] . '/wpallimport_logs');
417 }
418
419 foreach ($imports->setColumns($imports->getTable() . '.*')->getBy(array('id !=' => ''))->convertRecords() as $imp){
420
421 $imp->getById($imp->id);
422
423 if ( ! $imp->isEmpty() and ! empty($imp->template)){
424
425 $options = array_merge($imp->options, $imp->template);
426
427 $this->ver_4_transition_fix($options);
428
429 $imp->set(array(
430 'options' => $options
431 ))->update();
432
433 if ($imp->type == 'file'){
434 $imp->set(array(
435 'path' => $uploads['basedir'] . DIRECTORY_SEPARATOR . self::FILES_DIRECTORY . DIRECTORY_SEPARATOR . basename($imp->path)
436 ))->update();
437 }
438 }
439 }
440
441 foreach ($templates->setColumns($templates->getTable() . '.*')->getBy(array('id !=' => ''))->convertRecords() as $tpl){
442
443 $tpl->getById($tpl->id);
444
445 if ( ! $tpl->isEmpty() and ! empty($tpl->title) ) {
446
447 $opt = ( empty($tpl->options) ) ? array() : $tpl->options;
448
449 $options = array_merge($opt, array(
450 'title' => $tpl->title,
451 'content' => $tpl->content,
452 'is_keep_linebreaks' => $tpl->is_keep_linebreaks,
453 'is_leave_html' => $tpl->is_leave_html,
454 'fix_characters' => $tpl->fix_characters
455 ));
456
457 $this->ver_4_transition_fix($options);
458
459 $tpl->set(array(
460 'options' => $options
461 ))->update();
462
463 }
464
465 }
466
467 $commit_migration = $this->fix_db_schema(); // feature to version 4.0.0
468
469 }
470 else {
471
472 $commit_migration = $this->fix_db_schema();
473
474 foreach ($imports->setColumns($imports->getTable() . '.*')->getBy(array('id !=' => ''))->convertRecords() as $imp){
475
476 $imp->getById($imp->id);
477
478 if ( ! $imp->isEmpty() ){
479
480 $options = $imp->options;
481
482 $this->ver_4x_transition_fix($options, $is_migrated);
483
484 $imp->set(array(
485 'options' => $options
486 ))->update();
487 }
488 }
489
490 foreach ($templates->setColumns($templates->getTable() . '.*')->getBy(array('id !=' => ''))->convertRecords() as $tpl){
491
492 $tpl->getById($tpl->id);
493
494 if ( ! $tpl->isEmpty() ) {
495
496 $options = ( empty($tpl->options) ) ? array() : $tpl->options;
497
498 $this->ver_4x_transition_fix($options, $is_migrated);
499
500 $tpl->set(array(
501 'options' => $options
502 ))->update();
503
504 }
505
506 }
507 }
508 if ($commit_migration) update_option('pmxi_is_migrated', PMXI_VERSION);
509 }
510 }
511
512 public function ver_4_transition_fix( &$options ){
513
514 $options['wizard_type'] = ($options['duplicate_matching'] == 'auto') ? 'new' : 'matching';
515
516 if ($options['download_images']){
517 $options['download_images'] = 'yes';
518 $options['download_featured_image'] = $options['featured_image'];
519 $options['featured_image'] = '';
520 $options['download_featured_delim'] = $options['featured_delim'];
521 $options['featured_delim'] = '';
522 }
523
524 if ($options['set_image_meta_data']){
525 $options['set_image_meta_title'] = 1;
526 $options['set_image_meta_caption'] = 1;
527 $options['set_image_meta_alt'] = 1;
528 $options['set_image_meta_description'] = 1;
529 }
530
531 if ("" == $options['custom_type']) $options['custom_type'] = $options['type'];
532
533 $exclude_taxonomies = (class_exists('PMWI_Plugin')) ? array('post_format', 'product_type') : array('post_format');
534 $post_taxonomies = array_diff_key(get_taxonomies_by_object_type(array($options['custom_type']), 'object'), array_flip($exclude_taxonomies));
535
536 $options['tax_logic'] = array();
537 $options['tax_assing'] = array();
538 $options['tax_multiple_xpath'] = array();
539 $options['tax_multiple_delim'] = array();
540 $options['tax_hierarchical_logic_entire'] = array();
541 $options['tax_hierarchical_logic_manual'] = array();
542
543 if ( ! empty($post_taxonomies)):
544 foreach ($post_taxonomies as $ctx):
545
546 $options['tax_logic'][$ctx->name] = ($ctx->hierarchical) ? 'hierarchical' : 'multiple';
547
548 if ($ctx->name == 'category'){
549 $options['post_taxonomies']['category'] = $options['categories'];
550 }
551 elseif ($ctx->name == 'post_tag' ){
552 $options['tax_assing']['post_tag'] = 1;
553 $options['tax_multiple_xpath']['post_tag'] = $options['tags'];
554 $options['tax_multiple_delim']['post_tag'] = $options['tags_delim'];
555 }
556
557 if ( ! empty($options['post_taxonomies'][$ctx->name])){
558
559 $taxonomies_hierarchy = json_decode($options['post_taxonomies'][$ctx->name], true);
560 $options['tax_assing'][$ctx->name] = (!empty($taxonomies_hierarchy[0]['assign'])) ? 1 : 0;
561
562 if ($options['tax_logic'][$ctx->name] == 'multiple') {
563 $options['tax_multiple_xpath'][$ctx->name] = (!empty($taxonomies_hierarchy[0]['xpath'])) ? $taxonomies_hierarchy[0]['xpath'] : '';
564 $options['tax_multiple_delim'][$ctx->name] = (!empty($taxonomies_hierarchy[0]['delim'])) ? $taxonomies_hierarchy[0]['delim'] : '';
565 }
566 else{
567 $options['tax_hierarchical_logic_manual'][$ctx->name] = 1;
568 }
569 }
570
571 endforeach;
572 endif;
573 }
574
575 public function ver_4x_transition_fix(&$options, $version){
576 if ( version_compare($version, '3.7.2') < 0 ) {
577 $options['delete_missing_logic'] = 'import';
578 $options['is_send_removed_to_trash'] = 0;
579 $options['status_of_removed_products'] = 'outofstock';
580 if (empty($options['is_delete_missing']) || (!empty($options['is_update_missing_cf']) || !empty($options['set_missing_to_draft']) || !empty($options['missing_records_stock_status']))) {
581 $options['delete_missing_action'] = 'keep';
582 if ($options['set_missing_to_draft']) {
583 $options['is_change_post_status_of_removed'] = 1;
584 $options['status_of_removed'] = 'draft';
585 }
586 } else {
587 $options['delete_missing_action'] = 'remove';
588 }
589 // Set default option if no other options selected.
590 if (empty($options['is_update_missing_cf']) && empty($options['is_change_post_status_of_removed']) && empty($options['missing_records_stock_status'])) {
591 $options['is_send_removed_to_trash'] = 1;
592 }
593 $options['is_delete_attachments'] = !$options['is_keep_attachments'];
594 $options['is_delete_imgs'] = !$options['is_keep_imgs'];
595 }
596 }
597
598 /**
599 * pre-dispatching logic for admin page controllers
600 */
601 public function adminInit() {
602
603 self::$session = new PMXI_Handler();
604
605 $input = new PMXI_Input();
606 $page = strtolower($input->getpost('page', ''));
607
608 if (preg_match('%^' . preg_quote(str_replace('_', '-', self::PREFIX), '%') . '([\w-]+)$%', $page)) {
609 //$this->adminDispatcher($page, strtolower($input->getpost('action', 'index')));
610
611 $action = strtolower($input->getpost('action', 'index'));
612
613 // capitalize prefix and first letters of class name parts
614 $controllerName = preg_replace_callback('%(^' . preg_quote(self::PREFIX, '%') . '|_).%', array($this, "replace_callback"),str_replace('-', '_', $page));
615 $actionName = str_replace('-', '_', $action);
616 if (method_exists($controllerName, $actionName)) {
617
618 @ini_set("max_input_time", PMXI_Plugin::getInstance()->getOption('max_input_time'));
619 @ini_set("max_execution_time", str_replace('-1','0',PMXI_Plugin::getInstance()->getOption('max_execution_time')));
620
621 if ( ! get_current_user_id() or ! current_user_can( self::$capabilities )) {
622 // This nonce is not valid.
623 die( 'Security check' );
624
625 } else {
626
627 $this->_admin_current_screen = (object)array(
628 'id' => $controllerName,
629 'base' => $controllerName,
630 'action' => $actionName,
631 'is_ajax' => (isset($_SERVER["HTTP_ACCEPT"]) && strpos($_SERVER["HTTP_ACCEPT"], 'json')) !== false,
632 'is_network' => is_network_admin(),
633 'is_user' => is_user_admin(),
634 );
635 add_filter('current_screen', array($this, 'getAdminCurrentScreen'));
636 add_filter('admin_body_class', array($this, 'getAdminBodyClass'), 10, 1);
637
638 $controller = new $controllerName();
639 if ( ! $controller instanceof PMXI_Controller_Admin) {
640 throw new Exception("Administration page `$page` matches to a wrong controller type.");
641 }
642
643 $reviewsUI = new \Wpai\Reviews\ReviewsUI();
644 add_action('admin_notices', [$reviewsUI, 'render']);
645
646 if ($this->_admin_current_screen->is_ajax) { // ajax request
647 $controller->$action();
648 do_action('pmxi_action_after');
649 wp_die(); // stop processing since we want to output only what controller is randered, nothing in addition
650 } elseif ( ! $controller->isInline) {
651 @ob_start();
652 $controller->$action();
653 self::$buffer = @ob_get_clean();
654 } else {
655 self::$buffer_callback = array($controller, $action);
656 }
657
658 }
659
660 } else { // redirect to dashboard if requested page and/or action don't exist
661 wp_redirect(admin_url()); die();
662 }
663 }
664 }
665
666 public function getAdminBodyClass($class){
667 return $class . ' wpallimport-plugin';
668 }
669
670 /**
671 * Dispatch shorttag: create corresponding controller instance and call its index method
672 * @param array $args Shortcode tag attributes
673 * @param string $content Shortcode tag content
674 * @param string $tag Shortcode tag name which is being dispatched
675 * @return string
676 */
677 public function shortcodeDispatcher($args, $content, $tag) {
678
679 $controllerName = self::PREFIX . preg_replace_callback('%(^|_).%', array($this, "replace_callback"), $tag);// capitalize first letters of class name parts and add prefix
680 $controller = new $controllerName();
681 if ( ! $controller instanceof PMXI_Controller) {
682 throw new Exception("Shortcode `$tag` matches to a wrong controller type.");
683 }
684 ob_start();
685 $controller->index($args, $content);
686 return ob_get_clean();
687 }
688
689 static $buffer = NULL;
690 static $buffer_callback = NULL;
691
692 /**
693 * Dispatch admin page: call corresponding controller based on get parameter `page`
694 * The method is called twice: 1st time as handler `parse_header` action and then as admin menu item handler
695 * @param string[optional] $page When $page set to empty string ealier buffered content is outputted, otherwise controller is called based on $page value
696 */
697 public function adminDispatcher($page = '', $action = 'index') {
698
699 if ('' === $page) {
700 if ( ! is_null(self::$buffer)) {
701 echo '<div class="wrap">';
702
703 echo self::$buffer;
704
705 do_action('pmxi_action_after');
706 echo '</div>';
707 } elseif ( ! is_null(self::$buffer_callback)) {
708 echo '<div class="wrap">';
709 call_user_func(self::$buffer_callback);
710 do_action('pmxi_action_after');
711 echo '</div>';
712 } else {
713 throw new Exception('There is no previousely buffered content to display.');
714 }
715 }
716
717 }
718
719 public function replace_callback($matches){
720 return strtoupper($matches[0]);
721 }
722
723 protected $_admin_current_screen = NULL;
724 public function getAdminCurrentScreen()
725 {
726 return $this->_admin_current_screen;
727 }
728
729 /**
730 * Autoloader
731 * It's assumed class name consists of prefix folloed by its name which in turn corresponds to location of source file
732 * if `_` symbols replaced by directory path separator. File name consists of prefix folloed by last part in class name (i.e.
733 * symbols after last `_` in class name)
734 * When class has prefix it's source is looked in `models`, `controllers`, `shortcodes` folders, otherwise it looked in `core` or `library` folder
735 *
736 * @param string $className
737 * @return bool
738 */
739 public function autoload($className) {
740 $is_prefix = false;
741 $filePath = str_replace('_', '/', preg_replace('%^' . preg_quote(self::PREFIX, '%') . '%', '', strtolower($className), 1, $is_prefix)) . '.php';
742 if ( ! $is_prefix) { // also check file with original letter case
743 $filePathAlt = $className . '.php';
744 }
745 foreach ($is_prefix ? array('models', 'controllers', 'shortcodes', 'classes') : array('libraries') as $subdir) {
746 $path = self::ROOT_DIR . '/' . $subdir . '/' . $filePath;
747 if (is_file($path)) {
748 require $path;
749 return TRUE;
750 }
751 if ( ! $is_prefix) {
752 $pathAlt = self::ROOT_DIR . '/' . $subdir . '/' . $filePathAlt;
753 if (is_file($pathAlt)) {
754 require $pathAlt;
755 return TRUE;
756 }
757 }
758 }
759
760 if(strpos($className, '\\') !== false){
761
762 // project-specific namespace prefix
763 $prefix = 'Wpai\\';
764
765 // base directory for the namespace prefix
766 $base_dir = self::ROOT_DIR . '/src/';
767
768 // does the class use the namespace prefix?
769 $len = strlen($prefix);
770 if (strncmp($prefix, $className, $len) !== 0) {
771 // no, move to the next registered autoloader
772 return false;
773 }
774
775 // get the relative class name
776 $relative_class = substr($className, $len);
777
778 // replace the namespace prefix with the base directory, replace namespace
779 // separators with directory separators in the relative class name, append
780 // with .php
781 $file = $base_dir . str_replace('\\', '/', $relative_class) . '.php';
782
783 // if the file exists, require it
784 if (file_exists($file)) {
785 require_once $file;
786 return true;
787 }
788 }
789
790 return FALSE;
791 }
792
793 /**
794 * Get plugin option
795 * @param string[optional] $option Parameter to return, all array of options is returned if not set
796 * @return mixed
797 */
798 public function getOption($option = NULL) {
799 $options = apply_filters('wp_all_import_config_options', $this->options);
800 if (is_null($option)) {
801 return $options;
802 } else if (isset($options[$option])) {
803 return $options[$option];
804 } else {
805 throw new Exception("Specified option is not defined for the plugin");
806 }
807 }
808 /**
809 * Update plugin option value
810 * @param string $option Parameter name or array of name => value pairs
811 * @param mixed[optional] $value New value for the option, if not set than 1st parameter is supposed to be array of name => value pairs
812 * @return array
813 */
814 public function updateOption($option, $value = NULL) {
815 is_null($value) or $option = array($option => $value);
816 if (array_diff_key($option, $this->options)) {
817 throw new Exception("Specified option is not defined for the plugin");
818 }
819 $this->options = $option + $this->options;
820 update_option(get_class($this) . '_Options', $this->options);
821
822 return $this->options;
823 }
824
825 /**
826 * Plugin activation logic
827 */
828 public function activation() {
829 // uncaught exception doesn't prevent plugin from being activated, therefore replace it with fatal error so it does
830 if (version_compare(phpversion(), '7.2' , "<")){
831 $exception_handler = create_function('$e', 'trigger_error($e->getMessage(), E_USER_ERROR);');
832 }
833 else{
834 $exception_handler = function($e){
835 trigger_error($e->getMessage(), E_USER_ERROR);
836 };
837 }
838 set_exception_handler($exception_handler);
839
840 // create plugin options
841 $option_name = get_class($this) . '_Options';
842 $options_default = PMXI_Config::createFromFile(self::ROOT_DIR . '/config/options.php')->toArray();
843 $wpai_options = get_option($option_name, false);
844 if ( ! $wpai_options ) update_option($option_name, $options_default);
845
846 // create/update required database tables
847 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
848 require self::ROOT_DIR . '/schema.php';
849 global $wpdb;
850
851 if (function_exists('is_multisite') && is_multisite()) {
852 // check if it is a network activation - if so, run the activation function for each blog id
853 if (isset($_GET['networkwide']) && (intval($_GET['networkwide']) == 1)) {
854 $old_blog = $wpdb->blogid;
855 // Get all blog ids
856 $blogids = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
857 foreach ($blogids as $blog_id) {
858 switch_to_blog($blog_id);
859 require self::ROOT_DIR . '/schema.php';
860 dbDelta($plugin_queries);
861
862 // sync data between plugin tables and wordpress (mostly for the case when plugin is reactivated)
863
864 //$post = new PMXI_Post_Record();
865 //$wpdb->query('DELETE FROM ' . $post->getTable() . ' WHERE post_id NOT IN (SELECT ID FROM ' . $wpdb->posts . ')');
866 $post = new PMXI_Post_Record();
867 $import = new PMXI_Import_Record();
868 $imports_list = $wpdb->get_results('SELECT id FROM ' . $import->getTable() . '');
869
870 if ( ! empty($imports_list) ) {
871
872 $user_imports = array();
873 $post_imports = array();
874
875 foreach ($imports_list as $import_entry) {
876 $import_id = $import_entry->id;
877 $import = $import->getById($import_id);
878 $import_options = \pmxi_maybe_unserialize($import->options);
879 $import_type = $import_options['custom_type'];
880 if ( in_array($import_type, array('import_users', 'shop_customer')) ) {
881 $user_imports[] = $import_id;
882 } else {
883 $post_imports[] = $import_id;
884 }
885 }
886
887 if ( ! empty($user_imports) ) {
888 $user_table = $wpdb->base_prefix . 'users';
889 $user_query = 'DELETE FROM ' . $post->getTable() . ' WHERE import_id IN (' . implode(',', $user_imports) . ') AND post_id NOT IN (SELECT ID FROM ' . $user_table . ')';
890 $wpdb->query($user_query);
891 }
892
893 if ( ! empty($post_imports) ) {
894 $post_query = 'DELETE FROM ' . $post->getTable() . ' WHERE import_id IN (' . implode(',', $post_imports) . ') AND post_id NOT IN (SELECT ID FROM ' . $wpdb->posts . ')';
895 $wpdb->query($post_query);
896 }
897
898 }
899
900 }
901 switch_to_blog($old_blog);
902 return;
903 }
904 }
905
906 dbDelta($plugin_queries);
907
908 // sync data between plugin tables and wordpress (mostly for the case when plugin is reactivated)
909
910 //$post = new PMXI_Post_Record();
911 //$wpdb->query('DELETE FROM ' . $post->getTable() . ' WHERE post_id NOT IN (SELECT ID FROM ' . $wpdb->posts . ')');
912
913 $post = new PMXI_Post_Record();
914 $import = new PMXI_Import_Record();
915 $imports_list = $wpdb->get_results('SELECT id FROM ' . $import->getTable() . '');
916
917 if ( ! empty($imports_list) ) {
918
919 $user_imports = array();
920 $post_imports = array();
921
922 foreach ($imports_list as $import_entry) {
923 $import_id = $import_entry->id;
924 $import = $import->getById($import_id);
925 $import_options = \pmxi_maybe_unserialize($import->options);
926 $import_type = $import_options['custom_type'];
927 if ( in_array($import_type, array('import_users', 'shop_customer')) ) {
928 $user_imports[] = $import_id;
929 } else {
930 $post_imports[] = $import_id;
931 }
932 }
933
934 if ( ! empty($user_imports) ) {
935 $user_table = $wpdb->base_prefix . 'users';
936 $user_query = 'DELETE FROM ' . $post->getTable() . ' WHERE import_id IN (' . implode(',', $user_imports) . ') AND post_id NOT IN (SELECT ID FROM ' . $user_table . ')';
937 $wpdb->query($user_query);
938 }
939
940 if ( ! empty($post_imports) ) {
941 $post_query = 'DELETE FROM ' . $post->getTable() . ' WHERE import_id IN (' . implode(',', $post_imports) . ') AND post_id NOT IN (SELECT ID FROM ' . $wpdb->posts . ')';
942 $wpdb->query($post_query);
943 }
944
945 }
946
947 }
948
949 /**
950 * Load Localisation files.
951 *
952 * Note: the first-loaded translation file overrides any following ones if the same translation is present
953 *
954 * @access public
955 * @return void
956 */
957 public function load_plugin_textdomain() {
958 $locale = apply_filters( 'plugin_locale', get_locale(), 'wp_all_import_plugin' );
959
960 load_plugin_textdomain( 'wp_all_import_plugin', false, dirname( plugin_basename( __FILE__ ) ) . "/i18n/languages" );
961 }
962
963 public function fix_db_schema(){
964
965 $uploads = wp_upload_dir();
966
967 if ( ! is_dir($uploads['basedir'] . DIRECTORY_SEPARATOR . self::LOGS_DIRECTORY) or ! is_writable($uploads['basedir'] . DIRECTORY_SEPARATOR . self::LOGS_DIRECTORY)) {
968 die(sprintf(__('Uploads folder %s must be writable', 'wp_all_import_plugin'), esc_attr($uploads['basedir'] . DIRECTORY_SEPARATOR . self::LOGS_DIRECTORY)));
969 }
970
971 if ( ! is_dir($uploads['basedir'] . DIRECTORY_SEPARATOR . WP_ALL_IMPORT_UPLOADS_BASE_DIRECTORY) or ! is_writable($uploads['basedir'] . DIRECTORY_SEPARATOR . WP_ALL_IMPORT_UPLOADS_BASE_DIRECTORY)) {
972 die(sprintf(__('Uploads folder %s must be writable', 'wp_all_import_plugin'), esc_attr($uploads['basedir'] . DIRECTORY_SEPARATOR . WP_ALL_IMPORT_UPLOADS_BASE_DIRECTORY)));
973 }
974
975 // create/update required database tables
976 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
977 require self::ROOT_DIR . '/schema.php';
978 global $wpdb;
979
980 if (function_exists('is_multisite') && is_multisite()) {
981 // check if it is a network activation - if so, run the activation function for each blog id
982 if (isset($_GET['networkwide']) && (intval($_GET['networkwide']) == 1)) {
983 $old_blog = $wpdb->blogid;
984 // Get all blog ids
985 $blogids = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
986 foreach ($blogids as $blog_id) {
987 switch_to_blog($blog_id);
988 require self::ROOT_DIR . '/schema.php';
989 dbDelta($plugin_queries);
990
991 // sync data between plugin tables and wordpress (mostly for the case when plugin is reactivated)
992
993 $post = new PMXI_Post_Record();
994 $wpdb->query('DELETE FROM ' . $post->getTable() . ' WHERE post_id NOT IN (SELECT ID FROM ' . $wpdb->posts .') AND post_id NOT IN ( SELECT ID FROM ' . $wpdb->users . ') AND post_id NOT IN ( SELECT term_taxonomy_id FROM ' . $wpdb->term_taxonomy . ')');
995 }
996 switch_to_blog($old_blog);
997 return;
998 }
999 }
1000
1001 dbDelta($plugin_queries);
1002
1003 // do not execute ALTER TABLE queries if sql user doesn't have ALTER privileges
1004 $grands = $wpdb->get_results("SELECT * FROM information_schema.user_privileges WHERE grantee LIKE \"'" . DB_USER . "'%\" AND PRIVILEGE_TYPE = 'ALTER' AND IS_GRANTABLE = 'YES';");
1005
1006 $table = $table = $this->getTablePrefix() . 'files';
1007
1008 $tablefields = $wpdb->get_results("DESCRIBE {$table};");
1009 // For every field in the table
1010 foreach ($tablefields as $tablefield) {
1011 if ('contents' == $tablefield->Field) {
1012 $list = new PMXI_File_List();
1013 for ($i = 1; $list->getBy(NULL, 'id', $i, 1)->count(); $i++) {
1014 foreach ($list->convertRecords() as $file) {
1015 $file->save(); // resave file for file to be stored in uploads folder
1016 }
1017 }
1018
1019 if (!empty($grands)) $wpdb->query("ALTER TABLE {$table} DROP " . $tablefield->Field);
1020
1021 break;
1022 }
1023 }
1024
1025 // alter images table
1026 $table = $this->getTablePrefix() . 'images';
1027 $tablefields = $wpdb->get_results("DESCRIBE {$table};");
1028 $fields_to_alter = array(
1029 'image_url',
1030 'image_filename'
1031 );
1032
1033 // Check if field exists
1034 foreach ($tablefields as $tablefield) {
1035 if (in_array($tablefield->Field, $fields_to_alter)){
1036 $fields_to_alter = array_diff($fields_to_alter, array($tablefield->Field));
1037 }
1038 }
1039
1040 if ( ! empty($fields_to_alter) ){
1041
1042 if (empty($grands)) return false;
1043
1044 foreach ($fields_to_alter as $field) {
1045 switch ($field) {
1046 case 'image_url':
1047 $wpdb->query("ALTER TABLE {$table} ADD `image_url` TEXT;");
1048 break;
1049 case 'image_filename':
1050 $wpdb->query("ALTER TABLE {$table} ADD `image_filename` TEXT;");
1051 break;
1052 default:
1053 # code...
1054 break;
1055 }
1056 }
1057 }
1058
1059 $table = $this->getTablePrefix() . 'imports';
1060 $tablefields = $wpdb->get_results("DESCRIBE {$table};");
1061 $fields_to_alter = array(
1062 'parent_import_id',
1063 'iteration',
1064 'deleted',
1065 'changed_missing',
1066 'executing',
1067 'canceled',
1068 'canceled_on',
1069 'failed',
1070 'failed_on',
1071 'settings_update_on',
1072 'last_activity'
1073 );
1074
1075 // Check if field exists
1076 foreach ($tablefields as $tablefield) {
1077 if (in_array($tablefield->Field, $fields_to_alter)){
1078 $fields_to_alter = array_diff($fields_to_alter, array($tablefield->Field));
1079 }
1080 }
1081
1082 if ( ! empty($fields_to_alter) ){
1083
1084 if (empty($grands)) return false;
1085
1086 foreach ($fields_to_alter as $field) {
1087 switch ($field) {
1088 case 'parent_import_id':
1089 $wpdb->query("ALTER TABLE {$table} ADD `parent_import_id` BIGINT(20) NOT NULL DEFAULT 0;");
1090 break;
1091 case 'iteration':
1092 $wpdb->query("ALTER TABLE {$table} ADD `iteration` BIGINT(20) NOT NULL DEFAULT 0;");
1093 break;
1094 case 'deleted':
1095 $wpdb->query("ALTER TABLE {$table} ADD `deleted` BIGINT(20) NOT NULL DEFAULT 0;");
1096 break;
1097 case 'changed_missing':
1098 $wpdb->query("ALTER TABLE {$table} ADD `changed_missing` BIGINT(20) NOT NULL DEFAULT 0;");
1099 break;
1100 case 'executing':
1101 $wpdb->query("ALTER TABLE {$table} ADD `executing` BOOL NOT NULL DEFAULT 0;");
1102 break;
1103 case 'canceled':
1104 $wpdb->query("ALTER TABLE {$table} ADD `canceled` BOOL NOT NULL DEFAULT 0;");
1105 break;
1106 case 'canceled_on':
1107 $wpdb->query("ALTER TABLE {$table} ADD `canceled_on` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00';");
1108 break;
1109 case 'failed':
1110 $wpdb->query("ALTER TABLE {$table} ADD `failed` BOOL NOT NULL DEFAULT 0;");
1111 break;
1112 case 'failed_on':
1113 $wpdb->query("ALTER TABLE {$table} ADD `failed_on` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00';");
1114 break;
1115 case 'settings_update_on':
1116 $wpdb->query("ALTER TABLE {$table} ADD `settings_update_on` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00';");
1117 break;
1118 case 'last_activity':
1119 $wpdb->query("ALTER TABLE {$table} ADD `last_activity` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00';");
1120 break;
1121
1122 default:
1123 # code...
1124 break;
1125 }
1126 }
1127 }
1128
1129 $table = $this->getTablePrefix() . 'posts';
1130 $tablefields = $wpdb->get_results("DESCRIBE {$table};");
1131 $iteration = false;
1132 $specified = false;
1133
1134 // Check if field exists
1135 foreach ($tablefields as $tablefield) {
1136 if ('iteration' == $tablefield->Field) $iteration = true;
1137 if ('specified' == $tablefield->Field) $specified = true;
1138 }
1139
1140 if (!$iteration){
1141
1142 if (empty($grands)) {
1143 ?>
1144 <div class="error"><p>
1145 <?php printf(
1146 __('<b>%s Plugin</b>: Current sql user %s doesn\'t have ALTER privileges', 'pmwi_plugin'),
1147 esc_attr(self::getInstance()->getName()), esc_attr(DB_USER)
1148 ) ?>
1149 </p></div>
1150 <?php
1151 return false;
1152 }
1153
1154 $wpdb->query("ALTER TABLE {$table} ADD `iteration` BIGINT(20) NOT NULL DEFAULT 0;");
1155
1156 // Add indexing to pmxi_posts.post_id and pmxi_posts.import_id fields.
1157 $wpdb->query("ALTER TABLE {$table} ADD INDEX `post_id`(`post_id`);");
1158 $wpdb->query("ALTER TABLE {$table} ADD INDEX `import_id`(`import_id`)");
1159 }
1160
1161 if (!$specified and !empty($grands))
1162 {
1163 $wpdb->query("ALTER TABLE {$table} ADD `specified` BOOL NOT NULL DEFAULT 0;");
1164 }
1165
1166 if ( ! empty($wpdb->charset))
1167 $charset_collate = "DEFAULT CHARACTER SET $wpdb->charset";
1168 if ( ! empty($wpdb->collate))
1169 $charset_collate .= " COLLATE $wpdb->collate";
1170
1171 $table_prefix = $this->getTablePrefix();
1172
1173 $wpdb->query("CREATE TABLE IF NOT EXISTS {$table_prefix}history (
1174 id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
1175 import_id BIGINT(20) UNSIGNED NOT NULL,
1176 type ENUM('manual','processing','trigger','continue','') NOT NULL DEFAULT '',
1177 time_run TEXT,
1178 date DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
1179 summary TEXT,
1180 PRIMARY KEY (id)
1181 ) $charset_collate;");
1182
1183 return true;
1184 }
1185
1186 /**
1187 * Method returns default import options, main utility of the method is to avoid warnings when new
1188 * option is introduced but already registered imports don't have it
1189 */
1190 public static function get_default_import_options() {
1191 return array(
1192 'type' => 'post',
1193 'is_override_post_type' => 0,
1194 'post_type_xpath' => '',
1195 'deligate' => '',
1196 'wizard_type' => 'new',
1197 'ftp_host' => '',
1198 'ftp_path' => '',
1199 'ftp_root' => '/',
1200 'ftp_port' => 21,
1201 'ftp_username' => '',
1202 'ftp_password' => '',
1203 'ftp_private_key' => '',
1204 'custom_type' => '',
1205 'featured_delim' => ',',
1206 'atch_delim' => ',',
1207 'is_search_existing_attach' => 0,
1208 'post_taxonomies' => array(),
1209 'parent' => 0,
1210 'is_multiple_page_parent' => 'yes',
1211 'single_page_parent' => '',
1212 'order' => 0,
1213 'status' => 'publish',
1214 'page_template' => 'default',
1215 'is_multiple_page_template' => 'yes',
1216 'single_page_template' => '',
1217 'page_taxonomies' => array(),
1218 'date_type' => 'specific',
1219 'date' => 'now',
1220 'date_start' => 'now',
1221 'date_end' => 'now',
1222 'custom_name' => array(),
1223 'custom_value' => array(),
1224 'custom_format' => array(),
1225 'custom_mapping' => array(),
1226 'serialized_values' => array(),
1227 'custom_mapping_rules' => array(),
1228 'comment_status' => 'open',
1229 'comment_status_xpath' => '',
1230 'ping_status' => 'open',
1231 'ping_status_xpath' => '',
1232 'create_draft' => 'no',
1233 'author' => '',
1234 'post_excerpt' => '',
1235 'post_slug' => '',
1236 'attachments' => '',
1237 'is_import_specified' => 0,
1238 'import_specified' => '',
1239 'is_delete_source' => 0,
1240 'is_cloak' => 0,
1241 'unique_key' => '',
1242 'tmp_unique_key' => '',
1243 'feed_type' => 'auto',
1244 'search_existing_images' => 1,
1245
1246 'create_new_records' => 1,
1247 'is_selective_hashing' => 0,
1248 'is_delete_missing' => 0,
1249 'delete_missing_logic' => 'import',
1250 'delete_missing_action' => 'keep',
1251 'is_send_removed_to_trash' => 0,
1252 'is_change_post_status_of_removed' => 1,
1253 'status_of_removed' => 'draft',
1254 'status_of_removed_products' => 'outofstock',
1255 'set_missing_to_draft' => 0,
1256 'is_update_missing_cf' => 0,
1257 'update_missing_cf_name' => [],
1258 'update_missing_cf_value' => [],
1259
1260 'is_keep_former_posts' => 'no',
1261 'is_update_status' => 1,
1262 'is_update_content' => 1,
1263 'is_update_title' => 1,
1264 'is_update_slug' => 1,
1265 'is_update_excerpt' => 1,
1266 'is_update_categories' => 1,
1267 'is_update_author' => 1,
1268 'is_update_comment_status' => 1,
1269 'is_update_ping_status' => 1,
1270 'is_update_post_type' => 1,
1271 'is_update_post_format' => 1,
1272 'update_categories_logic' => 'full_update',
1273 'taxonomies_list' => array(),
1274 'taxonomies_only_list' => array(),
1275 'taxonomies_except_list' => array(),
1276 'do_not_create_terms' => 0,
1277 'is_update_attachments' => 1,
1278 'is_update_images' => 1,
1279 'update_images_logic' => 'full_update',
1280 'is_update_dates' => 1,
1281 'is_update_menu_order' => 1,
1282 'is_update_parent' => 1,
1283 'is_keep_attachments' => 0,
1284 'is_delete_attachments' => 0,
1285 'is_keep_imgs' => 0,
1286 'is_delete_imgs' => 0,
1287 'do_not_remove_images' => 1,
1288
1289 'is_update_custom_fields' => 1,
1290 'update_custom_fields_logic' => 'full_update',
1291 'custom_fields_list' => array(),
1292 'custom_fields_only_list' => array(),
1293 'custom_fields_except_list' => array(),
1294
1295 'duplicate_matching' => 'auto',
1296 'duplicate_indicator' => 'title',
1297 'custom_duplicate_name' => '',
1298 'custom_duplicate_value' => '',
1299 'is_update_previous' => 0,
1300 'is_scheduled' => '',
1301 'scheduled_period' => '',
1302 'friendly_name' => '',
1303 'records_per_request' => 20,
1304 'auto_rename_images' => 0,
1305 'auto_rename_images_suffix' => '',
1306 'images_name' => 'filename',
1307 'post_format' => 'standard',
1308 'post_format_xpath' => '',
1309 'encoding' => 'UTF-8',
1310 'delimiter' => '',
1311 'image_meta_title' => '',
1312 'image_meta_title_delim' => ',',
1313 'image_meta_caption' => '',
1314 'image_meta_caption_delim' => ',',
1315 'image_meta_alt' => '',
1316 'image_meta_alt_delim' => ',',
1317 'image_meta_description' => '',
1318 'image_meta_description_delim' => ',',
1319 'image_meta_description_delim_logic' => 'separate',
1320 'status_xpath' => '',
1321 'download_images' => 'yes',
1322 'converted_options' => 0,
1323 'update_all_data' => 'yes',
1324 'is_fast_mode' => 0,
1325 'chuncking' => 1,
1326 'import_processing' => 'ajax',
1327 'processing_iteration_logic' => 'auto',
1328 'save_template_as' => 0,
1329
1330 'title' => '',
1331 'content' => '',
1332 'name' => '',
1333 'is_keep_linebreaks' => 1,
1334 'is_leave_html' => 0,
1335 'fix_characters' => 0,
1336 'pid_xpath' => '',
1337 'slug_xpath' => '',
1338 'title_xpath' => '',
1339
1340 'featured_image' => '',
1341 'download_featured_image' => '',
1342 'download_featured_delim' => ',',
1343 'gallery_featured_image' => '',
1344 'gallery_featured_delim' => ',',
1345 'is_featured' => 1,
1346 'is_featured_xpath' => '',
1347 'set_image_meta_title' => 0,
1348 'set_image_meta_caption' => 0,
1349 'set_image_meta_alt' => 0,
1350 'set_image_meta_description' => 0,
1351 'auto_set_extension' => 0,
1352 'new_extension' => '',
1353 'tax_logic' => array(),
1354 'tax_assing' => array(),
1355 'term_assing' => array(),
1356 'multiple_term_assing' => array(),
1357 'tax_hierarchical_assing' => array(),
1358 'tax_hierarchical_last_level_assign' => array(),
1359 'tax_single_xpath' => array(),
1360 'tax_multiple_xpath' => array(),
1361 'tax_hierarchical_xpath' => array(),
1362 'tax_multiple_delim' => array(),
1363 'tax_hierarchical_delim' => array(),
1364 'tax_manualhierarchy_delim' => array(),
1365 'tax_hierarchical_logic_entire' => array(),
1366 'tax_hierarchical_logic_manual' => array(),
1367 'tax_enable_mapping' => array(),
1368 'tax_is_full_search_single' => array(),
1369 'tax_is_full_search_multiple' => array(),
1370 'tax_assign_to_one_term_single' => array(),
1371 'tax_assign_to_one_term_multiple' => array(),
1372 'tax_mapping' => array(),
1373 'tax_logic_mapping' => array(),
1374 'is_tax_hierarchical_group_delim' => array(),
1375 'tax_hierarchical_group_delim' => array(),
1376 'nested_files' => array(),
1377 'xml_reader_engine' => 0,
1378 'taxonomy_type' => '',
1379 'taxonomy_parent' => '',
1380 'taxonomy_slug' => 'auto',
1381 'taxonomy_slug_xpath' => '',
1382 'taxonomy_display_type' => '',
1383 'taxonomy_display_type_xpath' => '',
1384 'import_img_tags' => 0,
1385 'search_existing_images_logic' => 'by_url',
1386 'enable_import_scheduling' => 'false',
1387 'scheduling_enable' => false,
1388 'scheduling_weekly_days' => '',
1389 'scheduling_run_on' => 'weekly',
1390 'scheduling_monthly_day' => '',
1391 'scheduling_times' => array(),
1392 'scheduling_timezone' => 'UTC',
1393 'is_update_comment_post_id' => 1,
1394 'is_update_comment_author' => 1,
1395 'is_update_comment_author_email' => 1,
1396 'is_update_comment_author_url' => 1,
1397 'is_update_comment_author_IP' => 1,
1398 'is_update_comment_karma' => 1,
1399 'is_update_comment_approved' => 1,
1400 'is_update_comment_verified' => 1,
1401 'is_update_comment_rating' => 1,
1402 'is_update_comment_agent' => 1,
1403 'is_update_comment_user_id' => 1,
1404 'is_update_comment_type' => 1,
1405 'is_update_comments' => 1,
1406 'update_comments_logic' => 'full_update',
1407 'comment_author' => '',
1408 'comment_author_email' => '',
1409 'comment_author_url' => '',
1410 'comment_author_IP' => '',
1411 'comment_karma' => '',
1412 'comment_parent' => '',
1413 'comment_approved' => '1',
1414 'comment_approved_xpath' => '',
1415 'comment_verified' => '1',
1416 'comment_verified_xpath' => '',
1417 'comment_agent' => '',
1418 'comment_type' => '',
1419 'comment_type_xpath' => '',
1420 'comment_user_id' => 'email',
1421 'comment_user_id_xpath' => '',
1422 'comment_post' => '',
1423 'comment_rating' => '',
1424 'comments_repeater_mode' => 'csv',
1425 'comments_repeater_mode_separator' => '|',
1426 'comments_repeater_mode_foreach' => '',
1427 'comments' => array(
1428 'content' => '',
1429 'author' => '',
1430 'author_email' => '',
1431 'author_url' => '',
1432 'author_ip' => '',
1433 'karma' => '',
1434 'approved' => '',
1435 'type' => '',
1436 'date' => 'now'
1437 ),
1438
1439 // Excel Alternative Processing
1440 'use_alternative_excel_processing' => 0,
1441
1442 );
1443 }
1444
1445 /*
1446 * Convert csv to xml
1447 */
1448 public static function csv_to_xml($csv_url){
1449
1450 include_once(self::ROOT_DIR.'/libraries/XmlImportCsvParse.php');
1451
1452 $csv = new PMXI_CsvParser($csv_url);
1453
1454 $wp_uploads = wp_upload_dir();
1455 $tmpname = wp_unique_filename($wp_uploads['path'], str_replace("csv", "xml", basename($csv_url)));
1456 $xml_file = $wp_uploads['path'] .'/'. $tmpname;
1457 file_put_contents($xml_file, $csv->toXML());
1458 return $xml_file;
1459
1460 }
1461
1462 /**
1463 * @return bool
1464 */
1465 public static function is_ajax(){
1466 return (isset($_SERVER["HTTP_ACCEPT"]) && strpos($_SERVER["HTTP_ACCEPT"], 'json')) !== false;
1467 }
1468
1469 /**
1470 * Returns ID of current import.
1471 *
1472 * @return int|bool
1473 */
1474 public static function getCurrentImportId() {
1475 $input = new PMXI_Input();
1476 $import_id = $input->get('id');
1477 if (empty($import_id)) {
1478 $import_id = $input->get('import_id');
1479 }
1480 return $import_id;
1481 }
1482
1483 /**
1484 * @param $message
1485 */
1486 public function showNoticeAndDisablePlugin($message){
1487 $this->showNotice($message);
1488 deactivate_plugins( str_replace('\\', '/', dirname(__FILE__)) . '/wp-all-import-pro.php');
1489 }
1490
1491 /**
1492 * @param $message
1493 */
1494 public function showNotice($message) {
1495 $notice = new \Wpai\WordPress\AdminErrorNotice($message);
1496 $notice->render();
1497 }
1498
1499 /**
1500 * @param $message
1501 * @param $noticeId
1502 */
1503 public function showDismissibleNotice($message, $noticeId) {
1504 $notice = new \Wpai\WordPress\AdminDismissibleNotice($message, $noticeId);
1505 if(!$notice->isDismissed()) {
1506 $notice->render();
1507 }
1508 }
1509
1510
1511 }
1512
1513 PMXI_Plugin::getInstance();
1514