Import Products from any XML or CSV to WooCommerce - Version 1.0

Version Description

Download this release

Release Info

Developer soflyy
Plugin Icon 128x128 Import Products from any XML or CSV to WooCommerce
Version 1.0
Comparing to
See all releases

Version 1.0

actions/admin_notices.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ function pmwi_admin_notices() {
4
+ // notify user if history folder is not writable
5
+
6
+ if ( ! class_exists( 'Woocommerce' )) {
7
+ ?>
8
+ <div class="error"><p>
9
+ <?php printf(
10
+ __('<b>%s Plugin</b>: WooCommerce must be installed.', 'pmwi_plugin'),
11
+ PMWI_Plugin::getInstance()->getName()
12
+ ) ?>
13
+ </p></div>
14
+ <?php
15
+
16
+ deactivate_plugins( PMWI_FREE_ROOT_DIR . '/plugin.php');
17
+
18
+ }
19
+
20
+ if ( ! class_exists( 'PMXI_Plugin' ) ) {
21
+ ?>
22
+ <div class="error"><p>
23
+ <?php printf(
24
+ __('<b>%s Plugin</b>: WP All Import must be installed. Free edition of WP All Import at <a href="http://wordpress.org/plugins/wp-all-import/" target="_blank">http://wordpress.org/plugins/wp-all-import/</a> and the paid edition at <a href="http://www.wpallimport.com/">http://www.wpallimport.com/</a>', 'pmwi_plugin'),
25
+ PMWI_Plugin::getInstance()->getName()
26
+ ) ?>
27
+ </p></div>
28
+ <?php
29
+
30
+ deactivate_plugins( PMWI_FREE_ROOT_DIR . '/plugin.php');
31
+
32
+ }
33
+
34
+ $input = new PMWI_Input();
35
+ $messages = $input->get('PMWI_nt', array());
36
+ if ($messages) {
37
+ is_array($messages) or $messages = array($messages);
38
+ foreach ($messages as $type => $m) {
39
+ in_array((string)$type, array('updated', 'error')) or $type = 'updated';
40
+ ?>
41
+ <div class="<?php echo $type ?>"><p><?php echo $m ?></p></div>
42
+ <?php
43
+ }
44
+ }
45
+ }
actions/wp_loaded.php ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <?php
2
+
3
+ function pmwi_wp_loaded() {
4
+
5
+
6
+ }
classes/config.php ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Class to load config files
4
+ *
5
+ * @author Pavel Kulbakin <p.kulbakin@gmail.com>
6
+ */
7
+ class PMWI_Config implements IteratorAggregate {
8
+ /**
9
+ * Config variables stored
10
+ * @var array
11
+ */
12
+ protected $config = array();
13
+ /**
14
+ * List of loaded files in order to avoid loading same file several times
15
+ * @var array
16
+ */
17
+ protected $loaded = array();
18
+
19
+ /**
20
+ * Static method to create config instance from file on disc
21
+ * @param string $filePath
22
+ * @param string[optional] $section
23
+ * @return PMWI_Config
24
+ */
25
+ public static function createFromFile($filePath, $section = NULL) {
26
+ $config = new self();
27
+ return $config->loadFromFile($filePath, $section);
28
+ }
29
+
30
+ /**
31
+ * Load config file
32
+ * @param string $filePath
33
+ * @param string[optional] $section
34
+ * @return PMWI_Config
35
+ */
36
+ public function loadFromFile($filePath, $section = NULL) {
37
+ if ( ! is_null($section)) {
38
+ $this->config[$section] = self::createFromFile($filePath);
39
+ } else {
40
+ $filePath = realpath($filePath);
41
+ if ($filePath and ! in_array($filePath, $this->loaded)) {
42
+ require $filePath;
43
+
44
+ $sandbox = create_function('', "require '$filePath'; if(array_keys(get_defined_vars()) != array('config')) return array(); return \$config;");
45
+ $config = $sandbox();
46
+ $this->loaded[] = $filePath;
47
+ $this->config = array_merge($this->config, $config);
48
+ }
49
+ }
50
+ return $this;
51
+ }
52
+ /**
53
+ * Return value of setting with specified name
54
+ * @param string $field Setting name
55
+ * @param string[optional] $section Section name to look setting in
56
+ * @return mixed
57
+ */
58
+ public function get($field, $section = NULL) {
59
+ return ! is_null($section) ? $this->config[$section]->get($field) : $this->config[$field];
60
+ }
61
+
62
+ /**
63
+ * Magic method for checking whether some config option are set
64
+ * @param string $field
65
+ * @return bool
66
+ */
67
+ public function __isset($field) {
68
+ return isset($this->config[$field]);
69
+ }
70
+ /**
71
+ * Magic method to implement object-like access to config parameters
72
+ * @param string $field
73
+ * @return mixed
74
+ */
75
+ public function __get($field) {
76
+ return $this->config[$field];
77
+ }
78
+
79
+ /**
80
+ * Return all config options as array
81
+ * @return array
82
+ */
83
+ public function toArray($section = NULL) {
84
+ return ! is_null($section) ? $this->config[$section]->toArray() : $this->config;
85
+ }
86
+
87
+ public function getIterator() {
88
+ return new ArrayIterator($this->config);
89
+ }
90
+
91
+ }
classes/helper.php ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Helper class which defnes a namespace for some commonly used functions
4
+ *
5
+ * @author Pavel Kulbakin <p.kulbakin@gmail.com>
6
+ */
7
+ class PMWI_Helper {
8
+ const GLOB_MARK = 1;
9
+ const GLOB_NOSORT = 2;
10
+ const GLOB_ONLYDIR = 4;
11
+
12
+ const GLOB_NODIR = 256;
13
+ const GLOB_PATH = 512;
14
+ const GLOB_NODOTS = 1024;
15
+ const GLOB_RECURSE = 2048;
16
+
17
+ /**
18
+ * A safe empowered glob().
19
+ *
20
+ * Function glob() is prohibited on some server (probably in safe mode)
21
+ * (Message "Warning: glob() has been disabled for security reasons in
22
+ * (script) on line (line)") for security reasons as stated on:
23
+ * http://seclists.org/fulldisclosure/2005/Sep/0001.html
24
+ *
25
+ * safe_glob() intends to replace glob() using readdir() & fnmatch() instead.
26
+ * Supported flags: self::GLOB_MARK, self::GLOB_NOSORT, self::GLOB_ONLYDIR
27
+ * Additional flags: self::GLOB_NODIR, self::GLOB_PATH, self::GLOB_NODOTS, self::GLOB_RECURSE
28
+ * (not original glob() flags)
29
+ * @author BigueNique AT yahoo DOT ca
30
+ * @updates
31
+ * - 080324 Added support for additional flags: self::GLOB_NODIR, self::GLOB_PATH,
32
+ * self::GLOB_NODOTS, self::GLOB_RECURSE
33
+ * - 100607 Recurse is_dir check fixed by Pavel Kulbakin <p.kulbakin@gmail.com>
34
+ */
35
+ public static function safe_glob($pattern, $flags=0) {
36
+ $split = explode('/', str_replace('\\', '/', $pattern));
37
+ $mask = array_pop($split);
38
+ $path = implode('/', $split);
39
+
40
+ if (($dir = @opendir($path)) !== false or ($dir = @opendir($path . '/')) !== false) {
41
+ $glob = array();
42
+ while(($file = readdir($dir)) !== false) {
43
+ // Recurse subdirectories (self::GLOB_RECURSE)
44
+ if (($flags & self::GLOB_RECURSE) && is_dir($path . '/' . $file) && ( ! in_array($file, array('.', '..')))) {
45
+ $glob = array_merge($glob, self::array_prepend(self::safe_glob($path . '/' . $file . '/' . $mask, $flags), ($flags & self::GLOB_PATH ? '' : $file . '/')));
46
+ }
47
+ // Match file mask
48
+ if (self::fnmatch($mask, $file)) {
49
+ if ((( ! ($flags & self::GLOB_ONLYDIR)) || is_dir("$path/$file"))
50
+ && (( ! ($flags & self::GLOB_NODIR)) || ( ! is_dir($path . '/' . $file)))
51
+ && (( ! ($flags & self::GLOB_NODOTS)) || ( ! in_array($file, array('.', '..'))))
52
+ ) {
53
+ $glob[] = ($flags & self::GLOB_PATH ? $path . '/' : '') . $file . ($flags & self::GLOB_MARK ? '/' : '');
54
+ }
55
+ }
56
+ }
57
+ closedir($dir);
58
+ if ( ! ($flags & self::GLOB_NOSORT)) sort($glob);
59
+ return $glob;
60
+ } else {
61
+ return false;
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Prepends $string to each element of $array
67
+ * If $deep is true, will indeed also apply to sub-arrays
68
+ * @author BigueNique AT yahoo DOT ca
69
+ * @since 080324
70
+ */
71
+ public static function array_prepend($array, $string, $deep=false) {
72
+ if(empty($array)||empty($string)) {
73
+ return $array;
74
+ }
75
+ foreach ($array as $key => $element) {
76
+ if (is_array($element)) {
77
+ if ($deep) {
78
+ $array[$key] = self::array_prepend($element,$string,$deep);
79
+ } else {
80
+ trigger_error(__METHOD__ . ': array element', E_USER_WARNING);
81
+ }
82
+ } else {
83
+ $array[$key] = $string.$element;
84
+ }
85
+ }
86
+ return $array;
87
+
88
+ }
89
+
90
+ const FNM_PATHNAME = 1;
91
+ const FNM_NOESCAPE = 2;
92
+ const FNM_PERIOD = 4;
93
+ const FNM_CASEFOLD = 16;
94
+
95
+ /**
96
+ * non-POSIX complient remplacement for the fnmatch
97
+ */
98
+ public static function fnmatch($pattern, $string, $flags = 0) {
99
+
100
+ $modifiers = null;
101
+ $transforms = array(
102
+ '\*' => '.*',
103
+ '\?' => '.',
104
+ '\[\!' => '[^',
105
+ '\[' => '[',
106
+ '\]' => ']',
107
+ '\.' => '\.',
108
+ '\\' => '\\\\',
109
+ '\-' => '-',
110
+ );
111
+
112
+ // Forward slash in string must be in pattern:
113
+ if ($flags & FNM_PATHNAME) {
114
+ $transforms['\*'] = '[^/]*';
115
+ }
116
+
117
+ // Back slash should not be escaped:
118
+ if ($flags & FNM_NOESCAPE) {
119
+ unset($transforms['\\']);
120
+ }
121
+
122
+ // Perform case insensitive match:
123
+ if ($flags & FNM_CASEFOLD) {
124
+ $modifiers .= 'i';
125
+ }
126
+
127
+ // Period at start must be the same as pattern:
128
+ if ($flags & FNM_PERIOD) {
129
+ if (strpos($string, '.') === 0 && strpos($pattern, '.') !== 0) return false;
130
+ }
131
+
132
+ $pattern = '#^'
133
+ .strtr(preg_quote($pattern, '#'), $transforms)
134
+ .'$#'
135
+ .$modifiers;
136
+
137
+ return (boolean)preg_match($pattern, $string);
138
+ }
139
+ }
classes/input.php ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class PMWI_Input {
3
+ protected $filters = array('stripslashes');
4
+
5
+ public function read($inputArray, $paramName, $default = NULL) {
6
+ if (is_array($paramName) and ! is_null($default)) {
7
+ throw new Exception('Either array of parameter names with default values as the only argument or param name and default value as seperate arguments are expected.');
8
+ }
9
+ if (is_array($paramName)) {
10
+ foreach ($paramName as $param => $def) {
11
+ if (isset($inputArray[$param])) {
12
+ $paramName[$param] = $this->applyFilters($inputArray[$param]);
13
+ }
14
+ }
15
+ return $paramName;
16
+ } else {
17
+ return isset($inputArray[$paramName]) ? $this->applyFilters($inputArray[$paramName]) : $default;
18
+ }
19
+ }
20
+
21
+ public function get($paramName, $default = NULL) {
22
+ return $this->read($_GET, $paramName, $default);
23
+ }
24
+
25
+ public function post($paramName, $default = NULL) {
26
+ return $this->read($_POST, $paramName, $default);
27
+ }
28
+
29
+ public function cookie($paramName, $default = NULL) {
30
+ return $this->read($_COOKIE, $paramName, $default);
31
+ }
32
+
33
+ public function request($paramName, $default = NULL) {
34
+ return $this->read($_GET + $_POST + $_COOKIE, $paramName, $default);
35
+ }
36
+
37
+ public function getpost($paramName, $default = NULL) {
38
+ return $this->read($_GET + $_POST, $paramName, $default);
39
+ }
40
+
41
+ public function server($paramName, $default = NULL) {
42
+ return $this->read($_SERVER, $paramName, $default);
43
+ }
44
+
45
+ public function addFilter($callback) {
46
+ if ( ! is_callable($callback)) {
47
+ throw new Exception(get_class($this) . '::' . __METHOD__ . ' parameter must be a proper callback function reference.');
48
+ }
49
+ if ( ! in_array($callback, $this->filters)) {
50
+ $this->filters[] = $callback;
51
+ }
52
+ return $this;
53
+ }
54
+
55
+ public function removeFilter($callback) {
56
+ $this->filters = array_diff($this->filters, array($callback));
57
+ return $this;
58
+ }
59
+
60
+ protected function applyFilters($val) {
61
+ if (is_array($val)) {
62
+ foreach ($val as $k => $v) {
63
+ $val[$k] = $this->applyFilters($v);
64
+ }
65
+ } else {
66
+ foreach ($this->filters as $filter) {
67
+ $val = call_user_func($filter, $val);
68
+ }
69
+ }
70
+ return $val;
71
+ }
72
+ }
config/options.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * List of plugin optins, contains only default values, actual values are stored in database
4
+ * and can be changed by corresponding wordpress function calls
5
+ */
6
+ $config = array(
7
+ "info_api_url" => "",
8
+ );
controllers/admin/import.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Import configuration wizard
4
+ *
5
+ * @author Pavel Kulbakin <p.kulbakin@gmail.com>
6
+ */
7
+
8
+ class PMWI_Admin_Import extends PMWI_Controller_Admin {
9
+
10
+ /**
11
+ * Step #1: Choose File
12
+ */
13
+ public function index() {
14
+
15
+ $default = PMWI_Plugin::get_default_import_options();
16
+
17
+ $id = $this->input->get('id');
18
+
19
+ $this->data['import'] = $import = new PMXI_Import_Record();
20
+ if ( ! $id or $import->getById($id)->isEmpty()) { // specified import is not found
21
+ $post = $this->input->post(
22
+ $default
23
+ );
24
+ }
25
+ else
26
+ $post = $this->input->post(
27
+ $this->data['import']->options
28
+ + $default
29
+ );
30
+
31
+ $this->data['is_loaded_template'] = PMXI_Plugin::$session->data['pmxi_import']['is_loaded_template'];
32
+
33
+ $load_options = $this->input->post('load_template');
34
+
35
+ if ($load_options) { // init form with template selected
36
+
37
+ $template = new PMXI_Template_Record();
38
+ if ( ! $template->getById($this->data['is_loaded_template'])->isEmpty()) {
39
+ $post = (!empty($template->options) ? $template->options : array()) + $default;
40
+ }
41
+
42
+ } elseif ($load_options == -1){
43
+
44
+ $post = $default;
45
+
46
+ }
47
+
48
+ $this->data['woo_commerce_attributes'] = $woo_commerce_attributes = new PMXI_Model_List();
49
+ $woo_commerce_attributes->setTable(PMXI_Plugin::getInstance()->getWPPrefix() . 'woocommerce_attribute_taxonomies');
50
+ $woo_commerce_attributes->setColumns('attribute_name', 'attribute_id', 'attribute_label')->getBy(NULL, "attribute_id", NULL, NULL, "attribute_name");
51
+
52
+ $this->data['post'] =& $post;
53
+
54
+ $this->render();
55
+
56
+ }
57
+
58
+ }
controllers/controller.php ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Common logic for all shortcodes plugin implements
4
+ *
5
+ * @author Pavel Kulbakin <p.kulbakin@gmail.com>
6
+ */
7
+ abstract class PMWI_Controller {
8
+ /**
9
+ * Input class instance to retrieve parameters submitted during page request
10
+ * @var PMWI_Input
11
+ */
12
+ protected $input;
13
+ /**
14
+ * Error messages
15
+ * @var WP_Error
16
+ */
17
+ protected $errors;
18
+ /**
19
+ * Associative array of data which will be automatically available as variables when template is rendered
20
+ * @var array
21
+ */
22
+ public $data = array();
23
+ /**
24
+ * Constructor
25
+ */
26
+ public function __construct() {
27
+ $this->input = new PMWI_Input();
28
+ $this->input->addFilter('trim');
29
+
30
+ $this->errors = new WP_Error();
31
+
32
+ $this->init();
33
+ }
34
+
35
+ /**
36
+ * Method to put controller initialization logic to
37
+ */
38
+ protected function init() {}
39
+
40
+ /**
41
+ * Checks wether protocol is HTTPS and redirects user to secure connection if not
42
+ */
43
+ protected function force_ssl() {
44
+ if (force_ssl_admin() && ! is_ssl()) {
45
+ if ( 0 === strpos($_SERVER['REQUEST_URI'], 'http') ) {
46
+ wp_redirect(preg_replace('|^http://|', 'https://', $_SERVER['REQUEST_URI'])); die();
47
+ } else {
48
+ wp_redirect('https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']); die();
49
+ }
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Method returning resolved template content
55
+ *
56
+ * @param string[optional] $viewPath Template path to render
57
+ */
58
+ protected function render($viewPath = null) {
59
+ // assume template file name depending on calling function
60
+ if (is_null($viewPath)) {
61
+ $trace = debug_backtrace();
62
+ $viewPath = str_replace('_', '/', preg_replace('%^' . preg_quote(PMWI_Plugin::PREFIX, '%') . '%', '', strtolower($trace[1]['class']))) . '/' . $trace[1]['function'];
63
+ }
64
+ // append file extension if not specified
65
+ if ( ! preg_match('%\.php$%', $viewPath)) {
66
+ $viewPath .= '.php';
67
+ }
68
+ $filePath = PMWI_Plugin::ROOT_DIR . '/views/' . $viewPath;
69
+ if (is_file($filePath)) {
70
+ extract($this->data);
71
+ include $filePath;
72
+ } else {
73
+ throw new Exception("Requested template file $filePath is not found.");
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Display list of errors
79
+ *
80
+ * @param string|array|WP_Error[optional] $msgs
81
+ */
82
+ protected function error($msgs = NULL) {
83
+ if (is_null($msgs)) {
84
+ $msgs = $this->errors;
85
+ }
86
+ if (is_wp_error($msgs)) {
87
+ $msgs = $msgs->get_error_messages();
88
+ }
89
+ if ( ! is_array($msgs)) {
90
+ $msgs = array($msgs);
91
+ }
92
+ $this->data['errors'] = $msgs;
93
+
94
+ $viewPathRel = str_replace('_', '/', preg_replace('%^' . preg_quote(PMWI_Plugin::PREFIX, '%') . '%', '', strtolower(get_class($this)))) . '/error.php';
95
+ if (is_file(PMWI_Plugin::ROOT_DIR . '/views/' . $viewPathRel)) { // if calling controller class has specific error view
96
+ $this->render($viewPathRel);
97
+ } else { // render default error view
98
+ $this->render('controller/error.php');
99
+ }
100
+ }
101
+
102
+ }
controllers/controller/admin.php ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Introduce special type for controllers which render pages inside admin area
4
+ *
5
+ * @author Pavel Kulbakin <p.kulbakin@gmail.com>
6
+ */
7
+ abstract class PMWI_Controller_Admin extends PMWI_Controller {
8
+ /**
9
+ * Admin page base url (request url without all get parameters but `page`)
10
+ * @var string
11
+ */
12
+ public $baseUrl;
13
+ /**
14
+ * Parameters which is left when baseUrl is detected
15
+ * @var array
16
+ */
17
+ public $baseUrlParamNames = array('page', 'pagenum', 'order', 'order_by', 'type', 's', 'f');
18
+ /**
19
+ * Whether controller is rendered inside wordpress page
20
+ * @var bool
21
+ */
22
+ public $isInline = false;
23
+ /**
24
+ * Constructor
25
+ */
26
+ public function __construct() {
27
+ $remove = array_diff(array_keys($_GET), $this->baseUrlParamNames);
28
+ if ($remove) {
29
+ $this->baseUrl = remove_query_arg($remove);
30
+ } else {
31
+ $this->baseUrl = $_SERVER['REQUEST_URI'];
32
+ }
33
+ parent::__construct();
34
+
35
+ // add special filter for url fields
36
+ $this->input->addFilter(create_function('$str', 'return "http://" == $str || "ftp://" == $str ? "" : $str;'));
37
+
38
+ // enqueue required sripts and styles
39
+ global $wp_styles;
40
+ if ( ! is_a($wp_styles, 'WP_Styles'))
41
+ $wp_styles = new WP_Styles();
42
+
43
+ wp_enqueue_style('pmwi-admin-style', PMWI_FREE_ROOT_URL . '/static/css/admin.css');
44
+
45
+
46
+ wp_enqueue_script('pmwi-script', PMWI_FREE_ROOT_URL . '/static/js/pmwi.js', array('jquery'));
47
+ wp_enqueue_script('pmwi-admin-script', PMWI_FREE_ROOT_URL . '/static/js/admin.js', array('jquery', 'jquery-ui-dialog', 'jquery-ui-datepicker', 'jquery-ui-draggable', 'jquery-ui-droppable'));
48
+
49
+ global $woocommerce;
50
+
51
+ /*wp_enqueue_script('woocommerce_writepanel', $woocommerce->plugin_url() . '/assets/js/admin/write-panels.min.js', array('jquery', 'jquery-ui-datepicker'), $woocommerce->version);
52
+ wp_enqueue_script('jquery-ui-datepicker', $woocommerce->plugin_url() . '/assets/js/admin/ui-datepicker.js', array('jquery','jquery-ui-core'), $woocommerce->version );
53
+ wp_enqueue_script('woocommerce_admin', $woocommerce->plugin_url() . '/assets/js/admin/woocommerce_admin.min.js', array('jquery', 'jquery-ui-widget', 'jquery-ui-core'), $woocommerce->version);
54
+ wp_enqueue_script('ajax-chosen', $woocommerce->plugin_url() . '/assets/js/chosen/ajax-chosen.jquery.min.js', array('jquery', 'chosen'), $woocommerce->version );
55
+ wp_enqueue_script('chosen', $woocommerce->plugin_url() . '/assets/js/chosen/chosen.jquery.min.js', array('jquery'), $woocommerce->version );
56
+ wp_enqueue_script('jquery-blockui', $woocommerce->plugin_url() . '/assets/js/jquery-blockui/jquery.blockUI.min.js', array( 'jquery' ), $woocommerce->version, true );
57
+ wp_enqueue_script('jquery-placeholder', $woocommerce->plugin_url() . '/assets/js/jquery-placeholder/jquery.placeholder.min.js', array( 'jquery' ), $woocommerce->version, true );*/
58
+
59
+ $woocommerce_witepanel_params = array(
60
+ 'remove_item_notice' => __("Remove this item? If you have previously reduced this item's stock, or this order was submitted by a customer, will need to manually restore the item's stock.", 'woocommerce'),
61
+ 'remove_attribute' => __('Remove this attribute?', 'woocommerce'),
62
+ 'name_label' => __('Name', 'woocommerce'),
63
+ 'remove_label' => __('Remove', 'woocommerce'),
64
+ 'click_to_toggle' => __('Click to toggle', 'woocommerce'),
65
+ 'values_label' => __('Value(s)', 'woocommerce'),
66
+ 'text_attribute_tip' => __('Enter some text, or some attributes by pipe (|) separating values.', 'woocommerce'),
67
+ 'visible_label' => __('Visible on the product page', 'woocommerce'),
68
+ 'used_for_variations_label' => __('Used for variations', 'woocommerce'),
69
+ 'new_attribute_prompt' => __('Enter a name for the new attribute term:', 'woocommerce'),
70
+ 'calc_totals' => __("Calculate totals based on order items, discount amount, and shipping? Note, you will need to (optionally) calculate tax rows and cart discounts manually.", 'woocommerce'),
71
+ 'calc_line_taxes' => __("Calculate line taxes? This will calculate taxes based on the customers country. If no billing/shipping is set it will use the store base country.", 'woocommerce'),
72
+ 'copy_billing' => __("Copy billing information to shipping information? This will remove any currently entered shipping information.", 'woocommerce'),
73
+ 'load_billing' => __("Load the customer's billing information? This will remove any currently entered billing information.", 'woocommerce'),
74
+ 'load_shipping' => __("Load the customer's shipping information? This will remove any currently entered shipping information.", 'woocommerce'),
75
+ 'featured_label' => __('Featured', 'woocommerce'),
76
+ 'tax_or_vat' => $woocommerce->countries->tax_or_vat(),
77
+ 'prices_include_tax' => get_option('woocommerce_prices_include_tax'),
78
+ 'round_at_subtotal' => get_option( 'woocommerce_tax_round_at_subtotal' ),
79
+ 'meta_name' => __('Meta Name', 'woocommerce'),
80
+ 'meta_value' => __('Meta Value', 'woocommerce'),
81
+ 'no_customer_selected' => __('No customer selected', 'woocommerce'),
82
+ 'tax_label' => __('Tax Label:', 'woocommerce'),
83
+ 'compound_label' => __('Compound:', 'woocommerce'),
84
+ 'cart_tax_label' => __('Cart Tax:', 'woocommerce'),
85
+ 'shipping_tax_label' => __('Shipping Tax:', 'woocommerce'),
86
+ 'plugin_url' => $woocommerce->plugin_url(),
87
+ 'ajax_url' => admin_url('admin-ajax.php'),
88
+ 'add_order_item_nonce' => wp_create_nonce("add-order-item"),
89
+ 'add_attribute_nonce' => wp_create_nonce("add-attribute"),
90
+ 'calc_totals_nonce' => wp_create_nonce("calc-totals"),
91
+ 'get_customer_details_nonce' => wp_create_nonce("get-customer-details"),
92
+ 'search_products_nonce' => wp_create_nonce("search-products"),
93
+ 'calendar_image' => $woocommerce->plugin_url().'/assets/images/calendar.png',
94
+ 'post_id' => null
95
+ );
96
+
97
+ wp_localize_script( 'woocommerce_writepanel', 'woocommerce_writepanel_params', $woocommerce_witepanel_params );
98
+
99
+ wp_enqueue_style('pmwi-woo-style', $woocommerce->plugin_url() . '/assets/css/admin.css');
100
+ }
101
+
102
+ /**
103
+ * @see Controller::render()
104
+ */
105
+ protected function render($viewPath = NULL)
106
+ {
107
+ // assume template file name depending on calling function
108
+ if (is_null($viewPath)) {
109
+ $trace = debug_backtrace();
110
+ $viewPath = str_replace('_', '/', preg_replace('%^' . preg_quote(PMWI_Plugin::PREFIX, '%') . '%', '', strtolower($trace[1]['class']))) . '/' . $trace[1]['function'];
111
+ }
112
+
113
+ // render contextual help automatically
114
+ $viewHelpPath = $viewPath;
115
+ // append file extension if not specified
116
+ if ( ! preg_match('%\.php$%', $viewHelpPath)) {
117
+ $viewHelpPath .= '.php';
118
+ }
119
+ $viewHelpPath = preg_replace('%\.php$%', '-help.php', $viewHelpPath);
120
+ $fileHelpPath = PMWI_Plugin::ROOT_DIR . '/views/' . $viewHelpPath;
121
+
122
+ if (is_file($fileHelpPath)) { // there is help file defined
123
+ ob_start();
124
+ include $fileHelpPath;
125
+ add_contextual_help(PMWI_Plugin::getInstance()->getAdminCurrentScreen()->id, ob_get_clean());
126
+ }
127
+
128
+ parent::render($viewPath);
129
+ }
130
+
131
+ }
models/import/list.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class PMWI_Import_List extends PMWI_Model_List {
4
+ public function __construct() {
5
+ parent::__construct();
6
+ $this->setTable(PMWI_Plugin::getInstance()->getTablePrefix() . 'imports');
7
+ }
8
+ }
models/import/record.php ADDED
@@ -0,0 +1,843 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class PMWI_Import_Record extends PMWI_Model_Record {
4
+
5
+ /**
6
+ * Associative array of data which will be automatically available as variables when template is rendered
7
+ * @var array
8
+ */
9
+ public $data = array();
10
+
11
+ /**
12
+ * Initialize model instance
13
+ * @param array[optional] $data Array of record data to initialize object with
14
+ */
15
+ public function __construct($data = array()) {
16
+ parent::__construct($data);
17
+ $this->setTable(PMXI_Plugin::getInstance()->getTablePrefix() . 'imports');
18
+ }
19
+
20
+ /**
21
+ * Perform import operation
22
+ * @param string $xml XML string to import
23
+ * @param callback[optional] $logger Method where progress messages are submmitted
24
+ * @return PMWI_Import_Record
25
+ * @chainable
26
+ */
27
+ public function process($import, $count, $xml, $logger = NULL, $chunk = false) {
28
+ add_filter('user_has_cap', array($this, '_filter_has_cap_unfiltered_html')); kses_init(); // do not perform special filtering for imported content
29
+
30
+ $this->data = array();
31
+
32
+ $records = array();
33
+
34
+ ($chunk == 1 or (empty($import->large_import) or $import->large_import == 'No')) and $logger and call_user_func($logger, __('Composing product data...', 'pmxi_plugin'));
35
+
36
+ // Composing product types
37
+ if ($import->options['is_multiple_product_type'] != 'yes' and "" != $import->options['single_product_type']){
38
+ $this->data['product_types'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_type'], $file)->parse($records); $tmp_files[] = $file;
39
+ }
40
+ else{
41
+ $count and $this->data['product_types'] = array_fill(0, $count, $import->options['multiple_product_type']);
42
+ }
43
+
44
+ // Composing product is Virtual
45
+ if ($import->options['is_product_virtual'] == 'xpath' and "" != $import->options['single_product_virtual']){
46
+ $this->data['product_virtual'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_virtual'], $file)->parse($records); $tmp_files[] = $file;
47
+ }
48
+ else{
49
+ $count and $this->data['product_virtual'] = array_fill(0, $count, $import->options['is_product_virtual']);
50
+ }
51
+
52
+ // Composing product is Downloadable
53
+ if ($import->options['is_product_downloadable'] == 'xpath' and "" != $import->options['single_product_downloadable']){
54
+ $this->data['product_downloadable'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_downloadable'], $file)->parse($records); $tmp_files[] = $file;
55
+ }
56
+ else{
57
+ $count and $this->data['product_downloadable'] = array_fill(0, $count, $import->options['is_product_downloadable']);
58
+ }
59
+
60
+ // Composing product is Variable Enabled
61
+ if ($import->options['is_product_enabled'] == 'xpath' and "" != $import->options['single_product_enabled']){
62
+ $this->data['product_enabled'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_enabled'], $file)->parse($records); $tmp_files[] = $file;
63
+ }
64
+ else{
65
+ $count and $this->data['product_enabled'] = array_fill(0, $count, $import->options['is_product_enabled']);
66
+ }
67
+
68
+ // Composing product is Featured
69
+ if ($import->options['is_product_featured'] == 'xpath' and "" != $import->options['single_product_featured']){
70
+ $this->data['product_featured'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_featured'], $file)->parse($records); $tmp_files[] = $file;
71
+ }
72
+ else{
73
+ $count and $this->data['product_featured'] = array_fill(0, $count, $import->options['is_product_featured']);
74
+ }
75
+
76
+ // Composing product is Visibility
77
+ if ($import->options['is_product_visibility'] == 'xpath' and "" != $import->options['single_product_visibility']){
78
+ $this->data['product_visibility'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_visibility'], $file)->parse($records); $tmp_files[] = $file;
79
+ }
80
+ else{
81
+ $count and $this->data['product_visibility'] = array_fill(0, $count, $import->options['is_product_visibility']);
82
+ }
83
+
84
+ if ("" != $import->options['single_product_sku']){
85
+ $this->data['product_sku'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_sku'], $file)->parse($records); $tmp_files[] = $file;
86
+ }
87
+ else{
88
+ $count and $this->data['product_sku'] = array_fill(0, $count, "");
89
+ }
90
+
91
+ if ("" != $import->options['single_product_url']){
92
+ $this->data['product_url'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_url'], $file)->parse($records); $tmp_files[] = $file;
93
+ }
94
+ else{
95
+ $count and $this->data['product_url'] = array_fill(0, $count, "");
96
+ }
97
+
98
+ if ("" != $import->options['single_product_button_text']){
99
+ $this->data['product_button_text'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_button_text'], $file)->parse($records); $tmp_files[] = $file;
100
+ }
101
+ else{
102
+ $count and $this->data['product_button_text'] = array_fill(0, $count, "");
103
+ }
104
+
105
+ if ("" != $import->options['single_product_regular_price']){
106
+ $this->data['product_regular_price'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_regular_price'], $file)->parse($records); $tmp_files[] = $file;
107
+ }
108
+ else{
109
+ $count and $this->data['product_regular_price'] = array_fill(0, $count, "");
110
+ }
111
+
112
+ if ($import->options['is_regular_price_shedule'] and "" != $import->options['single_sale_price_dates_from']){
113
+ $this->data['product_sale_price_dates_from'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_sale_price_dates_from'], $file)->parse($records); $tmp_files[] = $file;
114
+ }
115
+ else{
116
+ $count and $this->data['product_sale_price_dates_from'] = array_fill(0, $count, "");
117
+ }
118
+
119
+ if ($import->options['is_regular_price_shedule'] and "" != $import->options['single_sale_price_dates_to']){
120
+ $this->data['product_sale_price_dates_to'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_sale_price_dates_to'], $file)->parse($records); $tmp_files[] = $file;
121
+ }
122
+ else{
123
+ $count and $this->data['product_sale_price_dates_to'] = array_fill(0, $count, "");
124
+ }
125
+
126
+ if ("" != $import->options['single_product_sale_price']){
127
+ $this->data['product_sale_price'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_sale_price'], $file)->parse($records); $tmp_files[] = $file;
128
+ }
129
+ else{
130
+ $count and $this->data['product_sale_price'] = array_fill(0, $count, "");
131
+ }
132
+
133
+ if ("" != $import->options['single_product_files']){
134
+ $this->data['product_files'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_files'], $file)->parse($records); $tmp_files[] = $file;
135
+ }
136
+ else{
137
+ $count and $this->data['product_files'] = array_fill(0, $count, "");
138
+ }
139
+
140
+ if ("" != $import->options['single_product_download_limit']){
141
+ $this->data['product_download_limit'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_download_limit'], $file)->parse($records); $tmp_files[] = $file;
142
+ }
143
+ else{
144
+ $count and $this->data['product_download_limit'] = array_fill(0, $count, "");
145
+ }
146
+
147
+ if ("" != $import->options['single_product_download_expiry']){
148
+ $this->data['product_download_expiry'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_download_expiry'], $file)->parse($records); $tmp_files[] = $file;
149
+ }
150
+ else{
151
+ $count and $this->data['product_download_expiry'] = array_fill(0, $count, "");
152
+ }
153
+
154
+ // Composing product Tax Status
155
+ if ($import->options['is_multiple_product_tax_status'] != 'yes' and "" != $import->options['single_product_tax_status']){
156
+ $this->data['product_tax_status'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_tax_status'], $file)->parse($records); $tmp_files[] = $file;
157
+ }
158
+ else{
159
+ $count and $this->data['product_tax_status'] = array_fill(0, $count, $import->options['multiple_product_tax_status']);
160
+ }
161
+
162
+ // Composing product Tax Class
163
+ if ($import->options['is_multiple_product_tax_class'] != 'yes' and "" != $import->options['single_product_tax_class']){
164
+ $this->data['product_tax_class'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_tax_class'], $file)->parse($records); $tmp_files[] = $file;
165
+ }
166
+ else{
167
+ $count and $this->data['product_tax_class'] = array_fill(0, $count, $import->options['multiple_product_tax_class']);
168
+ }
169
+
170
+ // Composing product Manage stock?
171
+ if ($import->options['is_product_manage_stock'] == 'xpath' and "" != $import->options['single_product_manage_stock']){
172
+ $this->data['product_manage_stock'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_manage_stock'], $file)->parse($records); $tmp_files[] = $file;
173
+ }
174
+ else{
175
+ $count and $this->data['product_manage_stock'] = array_fill(0, $count, $import->options['is_product_manage_stock']);
176
+ }
177
+
178
+ if ("" != $import->options['single_product_stock_qty']){
179
+ $this->data['product_stock_qty'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_stock_qty'], $file)->parse($records); $tmp_files[] = $file;
180
+ }
181
+ else{
182
+ $count and $this->data['product_stock_qty'] = array_fill(0, $count, "");
183
+ }
184
+
185
+ // Composing product Stock status
186
+ if ($import->options['product_stock_status'] == 'xpath' and "" != $import->options['single_product_stock_status']){
187
+ $this->data['product_stock_status'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_stock_status'], $file)->parse($records); $tmp_files[] = $file;
188
+ }
189
+ else{
190
+ $count and $this->data['product_stock_status'] = array_fill(0, $count, $import->options['product_stock_status']);
191
+ }
192
+
193
+ // Composing product Allow Backorders?
194
+ if ($import->options['product_allow_backorders'] == 'xpath' and "" != $import->options['single_product_allow_backorders']){
195
+ $this->data['product_allow_backorders'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_allow_backorders'], $file)->parse($records); $tmp_files[] = $file;
196
+ }
197
+ else{
198
+ $count and $this->data['product_allow_backorders'] = array_fill(0, $count, $import->options['product_allow_backorders']);
199
+ }
200
+
201
+ // Composing product Sold Individually?
202
+ if ($import->options['product_sold_individually'] == 'xpath' and "" != $import->options['single_product_sold_individually']){
203
+ $this->data['product_sold_individually'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_sold_individually'], $file)->parse($records); $tmp_files[] = $file;
204
+ }
205
+ else{
206
+ $count and $this->data['product_sold_individually'] = array_fill(0, $count, $import->options['product_sold_individually']);
207
+ }
208
+
209
+ if ("" != $import->options['single_product_weight']){
210
+ $this->data['product_weight'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_weight'], $file)->parse($records); $tmp_files[] = $file;
211
+ }
212
+ else{
213
+ $count and $this->data['product_weight'] = array_fill(0, $count, "");
214
+ }
215
+ if ("" != $import->options['single_product_length']){
216
+ $this->data['product_length'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_length'], $file)->parse($records); $tmp_files[] = $file;
217
+ }
218
+ else{
219
+ $count and $this->data['product_length'] = array_fill(0, $count, "");
220
+ }
221
+ if ("" != $import->options['single_product_width']){
222
+ $this->data['product_width'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_width'], $file)->parse($records); $tmp_files[] = $file;
223
+ }
224
+ else{
225
+ $count and $this->data['product_width'] = array_fill(0, $count, "");
226
+ }
227
+ if ("" != $import->options['single_product_height']){
228
+ $this->data['product_height'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_height'], $file)->parse($records); $tmp_files[] = $file;
229
+ }
230
+ else{
231
+ $count and $this->data['product_height'] = array_fill(0, $count, "");
232
+ }
233
+
234
+ // Composing product Shipping Class
235
+ if ($import->options['is_multiple_product_shipping_class'] != 'yes' and "" != $import->options['single_product_shipping_class']){
236
+ $this->data['product_shipping_class'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_shipping_class'], $file)->parse($records); $tmp_files[] = $file;
237
+ }
238
+ else{
239
+ $count and $this->data['product_shipping_class'] = array_fill(0, $count, $import->options['multiple_product_shipping_class']);
240
+ }
241
+
242
+ if ("" != $import->options['single_product_up_sells']){
243
+ $this->data['product_up_sells'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_up_sells'], $file)->parse($records); $tmp_files[] = $file;
244
+ }
245
+ else{
246
+ $count and $this->data['product_up_sells'] = array_fill(0, $count, "");
247
+ }
248
+ if ("" != $import->options['single_product_cross_sells']){
249
+ $this->data['product_cross_sells'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_cross_sells'], $file)->parse($records); $tmp_files[] = $file;
250
+ }
251
+ else{
252
+ $count and $this->data['product_cross_sells'] = array_fill(0, $count, "");
253
+ }
254
+
255
+ if ("" != $import->options['grouping_product']){
256
+ $this->data['product_grouping_parent'] = XmlImportParser::factory($xml, $import->xpath, $import->options['grouping_product'], $file)->parse($records); $tmp_files[] = $file;
257
+ }
258
+ else{
259
+ $count and $this->data['product_grouping_parent'] = array_fill(0, $count, "");
260
+ }
261
+
262
+ if ("" != $import->options['single_product_purchase_note']){
263
+ $this->data['product_purchase_note'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_purchase_note'], $file)->parse($records); $tmp_files[] = $file;
264
+ }
265
+ else{
266
+ $count and $this->data['product_purchase_note'] = array_fill(0, $count, "");
267
+ }
268
+ if ("" != $import->options['single_product_menu_order']){
269
+ $this->data['product_menu_order'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_menu_order'], $file)->parse($records); $tmp_files[] = $file;
270
+ }
271
+ else{
272
+ $count and $this->data['product_menu_order'] = array_fill(0, $count, "");
273
+ }
274
+
275
+ // Composing product Enable reviews
276
+ if ($import->options['is_product_enable_reviews'] == 'xpath' and "" != $import->options['single_product_enable_reviews']){
277
+ $this->data['product_enable_reviews'] = XmlImportParser::factory($xml, $import->xpath, $import->options['single_product_enable_reviews'], $file)->parse($records); $tmp_files[] = $file;
278
+ }
279
+ else{
280
+ $count and $this->data['product_enable_reviews'] = array_fill(0, $count, $import->options['is_product_enable_reviews']);
281
+ }
282
+
283
+ // Composing variations attributes
284
+ ($chunk == 1 or (empty($import->large_import) or $import->large_import == 'No')) and $logger and call_user_func($logger, __('Composing variations attributes...', 'pmxi_plugin'));
285
+ $attribute_keys = array();
286
+ $attribute_values = array();
287
+ $attribute_in_variation = array();
288
+ $attribute_is_visible = array();
289
+ $attribute_is_taxonomy = array();
290
+ $attribute_create_taxonomy_terms = array();
291
+
292
+ if (!empty($import->options['attribute_name'][0])){
293
+ foreach ($import->options['attribute_name'] as $j => $attribute_name) { if ($attribute_name == "") continue;
294
+ $attribute_keys[$j] = XmlImportParser::factory($xml, $import->xpath, $attribute_name, $file)->parse($records); $tmp_files[] = $file;
295
+ $attribute_values[$j] = XmlImportParser::factory($xml, $import->xpath, $import->options['attribute_value'][$j], $file)->parse($records); $tmp_files[] = $file;
296
+ $attribute_in_variation[$j] = XmlImportParser::factory($xml, $import->xpath, $import->options['in_variations'][$j], $file)->parse($records); $tmp_files[] = $file;
297
+ $attribute_is_visible[$j] = XmlImportParser::factory($xml, $import->xpath, $import->options['is_visible'][$j], $file)->parse($records); $tmp_files[] = $file;
298
+ $attribute_is_taxonomy[$j] = XmlImportParser::factory($xml, $import->xpath, $import->options['is_taxonomy'][$j], $file)->parse($records); $tmp_files[] = $file;
299
+ $attribute_create_taxonomy_terms[$j] = XmlImportParser::factory($xml, $import->xpath, $import->options['create_taxonomy_in_not_exists'][$j], $file)->parse($records); $tmp_files[] = $file;
300
+ }
301
+ }
302
+
303
+ // serialized attributes for product variations
304
+ $this->data['serialized_attributes'] = array();
305
+ if (!empty($attribute_keys)){
306
+ foreach ($attribute_keys as $j => $attribute_name) {
307
+ if (!in_array($attribute_name[0], array_keys($this->data['serialized_attributes']))){
308
+ $this->data['serialized_attributes'][$attribute_name[0]] = array(
309
+ 'value' => $attribute_values[$j],
310
+ 'is_visible' => $attribute_is_visible[$j],
311
+ 'in_variation' => $attribute_in_variation[$j],
312
+ 'in_taxonomy' => $attribute_is_taxonomy[$j],
313
+ 'is_create_taxonomy_terms' => $attribute_create_taxonomy_terms[$j]
314
+ );
315
+ }
316
+ }
317
+ }
318
+
319
+ remove_filter('user_has_cap', array($this, '_filter_has_cap_unfiltered_html')); kses_init(); // return any filtering rules back if they has been disabled for import procedure
320
+
321
+ foreach ($tmp_files as $file) { // remove all temporary files created
322
+ unlink($file);
323
+ }
324
+
325
+ return $this->data;
326
+ }
327
+
328
+ public function import($pid, $i, $import, $articleData, $xml, $is_cron = false){
329
+
330
+ $logger = create_function('$m', 'echo "<div class=\\"progress-msg\\">$m</div>\\n"; if ( "" != strip_tags(pmxi_strip_tags_content($m))) { PMXI_Plugin::$session[\'pmxi_import\'][\'log\'] .= "<p>".strip_tags(pmxi_strip_tags_content($m))."</p>"; flush(); }');
331
+
332
+ global $woocommerce;
333
+
334
+ extract($this->data);
335
+
336
+ // Add any default post meta
337
+ add_post_meta( $pid, 'total_sales', '0', true );
338
+
339
+ // Get types
340
+ $product_type = 'simple';
341
+ $is_downloadable = $product_downloadable[$i];
342
+ $is_virtual = $product_virtual[$i];
343
+ $is_featured = $product_featured[$i];
344
+
345
+ $existing_meta_keys = array();
346
+ foreach (get_post_meta($pid, '') as $cur_meta_key => $cur_meta_val) $existing_meta_keys[] = $cur_meta_key;
347
+
348
+ // Product type + Downloadable/Virtual
349
+ wp_set_object_terms( $pid, $product_type, 'product_type' );
350
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_downloadable')) update_post_meta( $pid, '_downloadable', ($is_downloadable == "yes") ? 'yes' : 'no' );
351
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_virtual')) update_post_meta( $pid, '_virtual', ($is_virtual == "yes") ? 'yes' : 'no' );
352
+
353
+ // Update post meta
354
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_regular_price')) update_post_meta( $pid, '_regular_price', stripslashes( $product_regular_price[$i] ) );
355
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_sale_price')) update_post_meta( $pid, '_sale_price', stripslashes( $product_sale_price[$i] ) );
356
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_tax_status')) update_post_meta( $pid, '_tax_status', stripslashes( $product_tax_status[$i] ) );
357
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_tax_class')) update_post_meta( $pid, '_tax_class', stripslashes( $product_tax_class[$i] ) );
358
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_visibility')) update_post_meta( $pid, '_visibility', stripslashes( $product_visibility[$i] ) );
359
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_purchase_note')) update_post_meta( $pid, '_purchase_note', stripslashes( $product_purchase_note[$i] ) );
360
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_featured')) update_post_meta( $pid, '_featured', ($is_featured == "yes") ? 'yes' : 'no' );
361
+
362
+ // Dimensions
363
+ if ( $is_virtual == 'no' ) {
364
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_weight')) update_post_meta( $pid, '_weight', stripslashes( $product_weight[$i] ) );
365
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_length')) update_post_meta( $pid, '_length', stripslashes( $product_length[$i] ) );
366
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_width')) update_post_meta( $pid, '_width', stripslashes( $product_width[$i] ) );
367
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_height')) update_post_meta( $pid, '_height', stripslashes( $product_height[$i] ) );
368
+ } else {
369
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_weight')) update_post_meta( $pid, '_weight', '' );
370
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_length')) update_post_meta( $pid, '_length', '' );
371
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_width')) update_post_meta( $pid, '_width', '' );
372
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_height')) update_post_meta( $pid, '_height', '' );
373
+ }
374
+
375
+ // Save shipping class
376
+ $product_shipping_class = $product_shipping_class[$i] > 0 && $product_type != 'external' ? absint( $product_shipping_class[$i] ) : '';
377
+ wp_set_object_terms( $pid, $product_shipping_class, 'product_shipping_class');
378
+
379
+ // Unique SKU
380
+ $sku = get_post_meta($pid, '_sku', true);
381
+ $new_sku = esc_html( trim( stripslashes( $product_sku[$i] ) ) );
382
+
383
+ if ( $new_sku == '' ) {
384
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_sku')) update_post_meta( $pid, '_sku', '' );
385
+ } elseif ( $new_sku !== $sku ) {
386
+ if ( ! empty( $new_sku ) ) {
387
+ if (
388
+ $this->wpdb->get_var( $this->wpdb->prepare("
389
+ SELECT ".$this->wpdb->posts.".ID
390
+ FROM ".$this->wpdb->posts."
391
+ LEFT JOIN ".$this->wpdb->postmeta." ON (".$this->wpdb->posts.".ID = ".$this->wpdb->postmeta.".post_id)
392
+ WHERE ".$this->wpdb->posts.".post_type = 'product'
393
+ AND ".$this->wpdb->posts.".post_status = 'publish'
394
+ AND ".$this->wpdb->postmeta.".meta_key = '_sku' AND ".$this->wpdb->postmeta.".meta_value = '%s'
395
+ ", $new_sku ) )
396
+ ) {
397
+ $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Product SKU must be unique.', 'pmxi_plugin')));
398
+
399
+ } else {
400
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_sku')) update_post_meta( $pid, '_sku', $new_sku );
401
+ }
402
+ } else {
403
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_sku')) update_post_meta( $pid, '_sku', '' );
404
+ }
405
+ }
406
+
407
+ // Save Attributes
408
+ $attributes = array();
409
+
410
+ if ( !empty($serialized_attributes) ) {
411
+
412
+ $attribute_position = 0;
413
+
414
+ foreach ($serialized_attributes as $attr_name => $attr_data) {
415
+
416
+ $is_visible = intval( $attr_data['is_visible'][$i] );
417
+ $is_variation = intval( $attr_data['in_variation'][$i] );
418
+ $is_taxonomy = intval( $attr_data['in_taxonomy'][$i] );
419
+
420
+
421
+ if ( $is_taxonomy ) {
422
+
423
+ if ( isset( $attr_data['value'][$i] ) ) {
424
+
425
+ $values = array_map( 'stripslashes', array_map( 'strip_tags', explode( '|', $attr_data['value'][$i] ) ) );
426
+
427
+ // Remove empty items in the array
428
+ $values = array_filter( $values );
429
+
430
+ if ( ! taxonomy_exists( $woocommerce->attribute_taxonomy_name( $attr_name ) ) and intval($attr_data['is_create_taxonomy_terms'][$i])) {
431
+
432
+ // Grab the submitted data
433
+ $attribute_name = ( isset( $attr_name ) ) ? woocommerce_sanitize_taxonomy_name( stripslashes( (string) $attr_name ) ) : '';
434
+ $attribute_label = ucwords($attribute_name);
435
+ $attribute_type = 'select';
436
+ $attribute_orderby = 'menu_order';
437
+
438
+ $reserved_terms = array(
439
+ 'attachment', 'attachment_id', 'author', 'author_name', 'calendar', 'cat', 'category', 'category__and',
440
+ 'category__in', 'category__not_in', 'category_name', 'comments_per_page', 'comments_popup', 'cpage', 'day',
441
+ 'debug', 'error', 'exact', 'feed', 'hour', 'link_category', 'm', 'minute', 'monthnum', 'more', 'name',
442
+ 'nav_menu', 'nopaging', 'offset', 'order', 'orderby', 'p', 'page', 'page_id', 'paged', 'pagename', 'pb', 'perm',
443
+ 'post', 'post__in', 'post__not_in', 'post_format', 'post_mime_type', 'post_status', 'post_tag', 'post_type',
444
+ 'posts', 'posts_per_archive_page', 'posts_per_page', 'preview', 'robots', 's', 'search', 'second', 'sentence',
445
+ 'showposts', 'static', 'subpost', 'subpost_id', 'tag', 'tag__and', 'tag__in', 'tag__not_in', 'tag_id',
446
+ 'tag_slug__and', 'tag_slug__in', 'taxonomy', 'tb', 'term', 'type', 'w', 'withcomments', 'withoutcomments', 'year',
447
+ );
448
+
449
+ if ( in_array( $attribute_name, $reserved_terms ) ) {
450
+ $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Slug “%s” is not allowed because it is a reserved term. Change it, please.', 'pmxi_plugin'), sanitize_title( $attribute_name )));
451
+ }
452
+ else{
453
+ $this->wpdb->insert(
454
+ $this->wpdb->prefix . 'woocommerce_attribute_taxonomies',
455
+ array(
456
+ 'attribute_label' => $attribute_label,
457
+ 'attribute_name' => $attribute_name,
458
+ 'attribute_type' => $attribute_type,
459
+ 'attribute_orderby' => $attribute_orderby,
460
+ )
461
+ );
462
+
463
+ $logger and call_user_func($logger, sprintf(__('<b>CREATED</b>: Taxonomy attribute “%s” have been successfully created.', 'pmxi_plugin'), sanitize_title( $attribute_name )));
464
+
465
+ // Register the taxonomy now so that the import works!
466
+ $domain = $woocommerce->attribute_taxonomy_name( $attr_name );
467
+ register_taxonomy( $domain,
468
+ apply_filters( 'woocommerce_taxonomy_objects_' . $domain, array('product') ),
469
+ apply_filters( 'woocommerce_taxonomy_args_' . $domain, array(
470
+ 'hierarchical' => true,
471
+ 'show_ui' => false,
472
+ 'query_var' => true,
473
+ 'rewrite' => false,
474
+ ) )
475
+ );
476
+
477
+ delete_transient( 'wc_attribute_taxonomies' );
478
+
479
+ $attribute_taxonomies = $this->wpdb->get_results( "SELECT * FROM " . $this->wpdb->prefix . "woocommerce_attribute_taxonomies" );
480
+
481
+ set_transient( 'wc_attribute_taxonomies', $attribute_taxonomies );
482
+
483
+ apply_filters( 'woocommerce_attribute_taxonomies', $attribute_taxonomies );
484
+ }
485
+
486
+ }
487
+
488
+ if ( ! empty($values) and taxonomy_exists( $woocommerce->attribute_taxonomy_name( $attr_name ) )){
489
+
490
+ $attr_values = array();
491
+
492
+ $terms = get_terms( $woocommerce->attribute_taxonomy_name( $attr_name ), array('hide_empty' => false));
493
+
494
+ if ( ! is_wp_error($terms) ){
495
+
496
+ foreach ($values as $key => $value) {
497
+ $term_founded = false;
498
+ if ( count($terms) > 0 ){
499
+ foreach ( $terms as $term ) {
500
+
501
+ if ( strtolower($term->name) == trim(strtolower($value)) ) {
502
+ $attr_values[] = $term->slug;
503
+ $term_founded = true;
504
+ }
505
+ }
506
+ }
507
+ if ( ! $term_founded and intval($attr_data['is_create_taxonomy_terms'][$i]) ){
508
+ $term = wp_insert_term(
509
+ $value, // the term
510
+ $woocommerce->attribute_taxonomy_name( $attr_name ) // the taxonomy
511
+ );
512
+ if ( ! is_wp_error($term) ){
513
+ $term = get_term_by( 'id', $term['term_id'], $woocommerce->attribute_taxonomy_name( $attr_name ));
514
+ $attr_values[] = $term->slug;
515
+ }
516
+
517
+ }
518
+ }
519
+ }
520
+ else {
521
+ $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: %s.', 'pmxi_plugin'), $terms->get_error_message()));
522
+ }
523
+
524
+ $values = $attr_values;
525
+
526
+ }
527
+ else {
528
+ $values = array();
529
+ }
530
+
531
+ }
532
+
533
+ // Update post terms
534
+ if ( taxonomy_exists( $woocommerce->attribute_taxonomy_name( $attr_name ) ))
535
+ wp_set_object_terms( $pid, $values, $woocommerce->attribute_taxonomy_name( $attr_name ) );
536
+
537
+ if ( $values ) {
538
+
539
+ // Add attribute to array, but don't set values
540
+ $attributes[ $woocommerce->attribute_taxonomy_name( $attr_name ) ] = array(
541
+ 'name' => $woocommerce->attribute_taxonomy_name( $attr_name ),
542
+ 'value' => '',
543
+ 'position' => $attribute_position,
544
+ 'is_visible' => $is_visible,
545
+ 'is_variation' => $is_variation,
546
+ 'is_taxonomy' => 1,
547
+ 'is_create_taxonomy_terms' => (!empty($attr_data['is_create_taxonomy_terms'][$i])) ? 1 : 0
548
+ );
549
+
550
+ }
551
+
552
+ } else {
553
+
554
+ if ( taxonomy_exists( $woocommerce->attribute_taxonomy_name( $attr_name ) ))
555
+ wp_set_object_terms( $pid, NULL, $woocommerce->attribute_taxonomy_name( $attr_name ) );
556
+
557
+ // Text based, separate by pipe
558
+ $values = implode( ' | ', array_map( 'sanitize_text_field', explode( '|', $attr_data['value'][$i] ) ) );
559
+
560
+ // Custom attribute - Add attribute to array and set the values
561
+ $attributes[ sanitize_title( $attr_name ) ] = array(
562
+ 'name' => sanitize_text_field( $attr_name ),
563
+ 'value' => $values,
564
+ 'position' => $attribute_position,
565
+ 'is_visible' => $is_visible,
566
+ 'is_variation' => $is_variation,
567
+ 'is_taxonomy' => 0
568
+ );
569
+
570
+ }
571
+
572
+ $attribute_position++;
573
+ }
574
+ }
575
+
576
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_product_attributes')) update_post_meta( $pid, '_product_attributes', $attributes );
577
+
578
+ // Sales and prices
579
+ if ( ! in_array( $product_type, array( 'grouped' ) ) ) {
580
+
581
+ $date_from = isset( $product_sale_price_dates_from[$i] ) ? $product_sale_price_dates_from[$i] : '';
582
+ $date_to = isset( $product_sale_price_dates_to[$i] ) ? $product_sale_price_dates_to[$i] : '';
583
+
584
+ // Dates
585
+ if ( $date_from ){
586
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_sale_price_dates_from')) update_post_meta( $pid, '_sale_price_dates_from', strtotime( $date_from ) );
587
+ }
588
+ else{
589
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_sale_price_dates_from')) update_post_meta( $pid, '_sale_price_dates_from', '' );
590
+ }
591
+
592
+ if ( $date_to ){
593
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_sale_price_dates_to')) update_post_meta( $pid, '_sale_price_dates_to', strtotime( $date_to ) );
594
+ }
595
+ else{
596
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_sale_price_dates_to')) update_post_meta( $pid, '_sale_price_dates_to', '' );
597
+ }
598
+
599
+ if ( $date_to && ! $date_from ){
600
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_sale_price_dates_from')) update_post_meta( $pid, '_sale_price_dates_from', strtotime( 'NOW', current_time( 'timestamp' ) ) );
601
+ }
602
+
603
+ // Update price if on sale
604
+ if ( $product_sale_price[$i] != '' && $date_to == '' && $date_from == '' ){
605
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_price')) update_post_meta( $pid, '_price', stripslashes( $product_sale_price[$i] ) );
606
+ }
607
+ else{
608
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_price')) update_post_meta( $pid, '_price', stripslashes( $product_regular_price[$i] ) );
609
+ }
610
+
611
+ if ( $product_sale_price[$i] != '' && $date_from && strtotime( $date_from ) < strtotime( 'NOW', current_time( 'timestamp' ) ) ){
612
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_price')) update_post_meta( $pid, '_price', stripslashes($product_sale_price[$i]) );
613
+ }
614
+
615
+ if ( $date_to && strtotime( $date_to ) < strtotime( 'NOW', current_time( 'timestamp' ) ) ) {
616
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_price')) update_post_meta( $pid, '_price', stripslashes($product_regular_price[$i]) );
617
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_sale_price_dates_from')) update_post_meta( $pid, '_sale_price_dates_from', '');
618
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_sale_price_dates_to')) update_post_meta( $pid, '_sale_price_dates_to', '');
619
+ }
620
+ }
621
+
622
+ // Update parent if grouped so price sorting works and stays in sync with the cheapest child
623
+ if ( $product_type == 'grouped' || ( "" != $product_grouping_parent[$i] and absint($product_grouping_parent[$i]) > 0)) {
624
+
625
+ $clear_parent_ids = array();
626
+
627
+ if ( $product_type == 'grouped' )
628
+ $clear_parent_ids[] = $pid;
629
+
630
+ if ( "" != $product_grouping_parent[$i] and absint($product_grouping_parent[$i]) > 0 )
631
+ $clear_parent_ids[] = absint( $product_grouping_parent[$i] );
632
+
633
+ if ( $clear_parent_ids ) {
634
+ foreach( $clear_parent_ids as $clear_id ) {
635
+
636
+ $children_by_price = get_posts( array(
637
+ 'post_parent' => $clear_id,
638
+ 'orderby' => 'meta_value_num',
639
+ 'order' => 'asc',
640
+ 'meta_key' => '_price',
641
+ 'posts_per_page'=> 1,
642
+ 'post_type' => 'product',
643
+ 'fields' => 'ids'
644
+ ) );
645
+ if ( $children_by_price ) {
646
+ foreach ( $children_by_price as $child ) {
647
+ $child_price = get_post_meta( $child, '_price', true );
648
+ update_post_meta( $clear_id, '_price', $child_price );
649
+ }
650
+ }
651
+
652
+ // Clear cache/transients
653
+ $woocommerce->clear_product_transients( $clear_id );
654
+ }
655
+ }
656
+ }
657
+
658
+ // Sold Individuall
659
+ if ( "yes" == $product_sold_individually[$i] ) {
660
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_sold_individually')) update_post_meta( $pid, '_sold_individually', 'yes' );
661
+ } else {
662
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_sold_individually')) update_post_meta( $pid, '_sold_individually', '' );
663
+ }
664
+
665
+ // Stock Data
666
+ if ( $product_manage_stock[$i] == 'yes' ) {
667
+
668
+ if ( ! empty( $product_manage_stock[$i] ) ) {
669
+
670
+ // Manage stock
671
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_stock')) update_post_meta( $pid, '_stock', (int) $product_stock_qty[$i] );
672
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_stock_status')) update_post_meta( $pid, '_stock_status', stripslashes( $product_stock_status[$i] ) );
673
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_backorders')) update_post_meta( $pid, '_backorders', stripslashes( $product_allow_backorders[$i] ) );
674
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_manage_stock')) update_post_meta( $pid, '_manage_stock', 'yes' );
675
+
676
+ // Check stock level
677
+ if ( $product_type !== 'variable' && $product_allow_backorders[$i] == 'no' && (int) $product_stock_qty[$i] < 1 ){
678
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_stock_status')) update_post_meta( $pid, '_stock_status', 'outofstock' );
679
+ }
680
+
681
+ } else {
682
+
683
+ // Don't manage stock
684
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_stock')) update_post_meta( $pid, '_stock', '' );
685
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_stock_status')) update_post_meta( $pid, '_stock_status', stripslashes( $product_stock_status[$i] ) );
686
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_backorders')) update_post_meta( $pid, '_backorders', stripslashes( $product_allow_backorders[$i] ) );
687
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_manage_stock')) update_post_meta( $pid, '_manage_stock', 'no' );
688
+
689
+ }
690
+
691
+ } else {
692
+
693
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_stock_status')) update_post_meta( $pid, '_stock_status', stripslashes( $product_stock_status[$i] ) );
694
+
695
+ }
696
+
697
+ // Upsells
698
+ if ( !empty( $product_up_sells[$i] ) ) {
699
+ $upsells = array();
700
+ $ids = explode(',', $product_up_sells[$i]);
701
+ foreach ( $ids as $id ){
702
+ $args = array(
703
+ 'post_type' => 'product',
704
+ 'meta_query' => array(
705
+ array(
706
+ 'key' => '_sku',
707
+ 'value' => $id,
708
+ )
709
+ )
710
+ );
711
+ $query = new WP_Query( $args );
712
+
713
+ if ( $query->have_posts() ) $upsells[] = $query->post->ID;
714
+
715
+ wp_reset_postdata();
716
+ }
717
+
718
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_upsell_ids')) update_post_meta( $pid, '_upsell_ids', $upsells );
719
+ } else {
720
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_upsell_ids')) delete_post_meta( $pid, '_upsell_ids' );
721
+ }
722
+
723
+ // Cross sells
724
+ if ( !empty( $product_cross_sells[$i] ) ) {
725
+ $crosssells = array();
726
+ $ids = explode(',', $product_cross_sells[$i]);
727
+ foreach ( $ids as $id ){
728
+ $args = array(
729
+ 'post_type' => 'product',
730
+ 'meta_query' => array(
731
+ array(
732
+ 'key' => '_sku',
733
+ 'value' => $id,
734
+ )
735
+ )
736
+ );
737
+ $query = new WP_Query( $args );
738
+
739
+ if ( $query->have_posts() ) $crosssells[] = $query->post->ID;
740
+
741
+ wp_reset_postdata();
742
+ }
743
+
744
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_crosssell_ids')) update_post_meta( $pid, '_crosssell_ids', $crosssells );
745
+ } else {
746
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_crosssell_ids')) delete_post_meta( $pid, '_crosssell_ids' );
747
+ }
748
+
749
+ // Downloadable options
750
+ if ( $is_downloadable == 'yes' ) {
751
+
752
+ $_download_limit = absint( $product_download_limit[$i] );
753
+ if ( ! $_download_limit )
754
+ $_download_limit = ''; // 0 or blank = unlimited
755
+
756
+ $_download_expiry = absint( $product_download_expiry[$i] );
757
+ if ( ! $_download_expiry )
758
+ $_download_expiry = ''; // 0 or blank = unlimited
759
+
760
+ // file paths will be stored in an array keyed off md5(file path)
761
+ if ( !empty( $product_file_paths[$i] ) ) {
762
+ $_file_paths = array();
763
+
764
+ $file_paths = explode( $import->options['product_files_delim'] , $product_file_paths[$i] );
765
+
766
+ foreach ( $file_paths as $file_path ) {
767
+ $file_path = trim( $file_path );
768
+ $_file_paths[ md5( $file_path ) ] = $file_path;
769
+ }
770
+
771
+ // grant permission to any newly added files on any existing orders for this product
772
+ do_action( 'woocommerce_process_product_file_download_paths', $pid, 0, $_file_paths );
773
+
774
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_file_paths')) update_post_meta( $pid, '_file_paths', $_file_paths );
775
+ }
776
+ if ( isset( $product_download_limit[$i] ) )
777
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_download_limit')) update_post_meta( $pid, '_download_limit', esc_attr( $_download_limit ) );
778
+ if ( isset( $product_download_expiry[$i] ) )
779
+ if ($this->keep_custom_fields($existing_meta_keys, $import->options, '_download_expiry')) update_post_meta( $pid, '_download_expiry', esc_attr( $_download_expiry ) );
780
+ }
781
+
782
+ // Do action for product type
783
+ do_action( 'woocommerce_process_product_meta_' . $product_type, $pid );
784
+
785
+ // Clear cache/transients
786
+ $woocommerce->clear_product_transients( $pid );
787
+
788
+ }
789
+
790
+ public function _filter_has_cap_unfiltered_html($caps)
791
+ {
792
+ $caps['unfiltered_html'] = true;
793
+ return $caps;
794
+ }
795
+
796
+ /**
797
+ * Find duplicates according to settings
798
+ */
799
+ public function findDuplicates($articleData, $custom_duplicate_name = '', $custom_duplicate_value = '', $duplicate_indicator = 'title')
800
+ {
801
+ if ('custom field' == $duplicate_indicator){
802
+ $duplicate_ids = array();
803
+ $args = array(
804
+ 'post_type' => $articleData['post_type'],
805
+ 'meta_query' => array(
806
+ array(
807
+ 'key' => $custom_duplicate_name,
808
+ 'value' => $custom_duplicate_value,
809
+ )
810
+ )
811
+ );
812
+ $query = new WP_Query( $args );
813
+
814
+ if ( $query->have_posts() ) $duplicate_ids[] = $query->post->ID;
815
+
816
+ wp_reset_postdata();
817
+
818
+ return $duplicate_ids;
819
+ }
820
+ else{
821
+ $field = 'post_' . $duplicate_indicator; // post_title or post_content
822
+ return $this->wpdb->get_col($this->wpdb->prepare("
823
+ SELECT ID FROM " . $this->wpdb->posts . "
824
+ WHERE
825
+ post_type = %s
826
+ AND ID != %s
827
+ AND REPLACE(REPLACE(REPLACE($field, ' ', ''), '\\t', ''), '\\n', '') = %s
828
+ ",
829
+ $articleData['post_type'],
830
+ isset($articleData['ID']) ? $articleData['ID'] : 0,
831
+ preg_replace('%[ \\t\\n]%', '', $articleData[$field])
832
+ ));
833
+ }
834
+ }
835
+
836
+ function keep_custom_fields($existing_meta_keys, $options, $meta_key){
837
+
838
+ $keep_custom_fields_specific = ( ! $options['keep_custom_fields'] and ! empty($options['keep_custom_fields_specific'])) ? array_map('trim', explode(',', $options['keep_custom_fields_specific'])) : array();
839
+
840
+ return (($options['keep_custom_fields'] and in_array($meta_key, $existing_meta_keys)) or (in_array($meta_key, $existing_meta_keys) and ! $options['keep_custom_fields'] and in_array($meta_key, $keep_custom_fields_specific))) ? false : true;
841
+
842
+ }
843
+ }
models/model.php ADDED
@@ -0,0 +1,198 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Base class for models
4
+ *
5
+ * @author Pavel Kulbakin <p.kulbakin@gmail.com>
6
+ */
7
+ abstract class PMWI_Model extends ArrayObject {
8
+ /**
9
+ * WPDB instance
10
+ * @var wpdb
11
+ */
12
+ protected $wpdb;
13
+ /**
14
+ * Table name the model is linked to
15
+ * @var string
16
+ */
17
+ protected $table;
18
+ /**
19
+ * Array of columns representing primary key
20
+ * @var array
21
+ */
22
+ protected $primary = array('id');
23
+ /**
24
+ * Wether key field is auto_increment (sure make scence only if key s
25
+ * @var bool
26
+ */
27
+ protected $auto_increment = FALSE;
28
+
29
+ /**
30
+ * Cached data retrieved from database
31
+ * @var array
32
+ */
33
+ private static $meta_cache = array();
34
+
35
+ /**
36
+ * Initialize model
37
+ * @param array[optional] $data Array of record data to initialize object with
38
+ */
39
+ public function __construct() {
40
+ $this->wpdb = $GLOBALS['wpdb'];
41
+ }
42
+
43
+ /**
44
+ * Read records from database by specified fields and values
45
+ * When 1st parameter is an array, it expected to be an associative array of field => value pairs to read data by
46
+ * If 2 parameters are set, first one is expected to be a field name and second - it's value
47
+ *
48
+ * @param string|array $field
49
+ * @param mixed[optional] $value
50
+ * @return PMWI_Model
51
+ */
52
+ abstract public function getBy($field = NULL, $value = NULL);
53
+
54
+ /**
55
+ * Magic function to automatically resolve calls like $obj->getBy%FIELD_NAME%
56
+ * @param string $method
57
+ * @param array $args
58
+ * @return PMWI_Model
59
+ */
60
+ public function __call($method, $args) {
61
+ if (preg_match('%^get_?by_?(.+)%i', $method, $mtch)) {
62
+ array_unshift($args, $mtch[1]);
63
+ return call_user_func_array(array($this, 'getBy'), $args);
64
+ } else {
65
+ throw new Exception("Requested method " . get_class($this) . "::$method doesn't exist.");
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Bind model to database table
71
+ * @param string $tableName
72
+ * @return PMWI_Model
73
+ */
74
+ public function setTable($tableName) {
75
+ if ( ! is_null($this->table)) {
76
+ throw new Exception('Table name cannot be changed once being set.');
77
+ }
78
+ $this->table = $tableName;
79
+ if ( ! isset(self::$meta_cache[$this->table])) {
80
+ $tableMeta = $this->wpdb->get_results("SHOW COLUMNS FROM $this->table", ARRAY_A);
81
+ $primary = array();
82
+ $auto_increment = false;
83
+ foreach ($tableMeta as $colMeta) {
84
+ if ('PRI' == $colMeta['Key']) {
85
+ $primary[] = $colMeta['Field'];
86
+ }
87
+ if ('auto_increment' == $colMeta['Extra']) {
88
+ $auto_increment = true;
89
+ break; // no point to iterate futher since auto_increment means corresponding primary key is simple
90
+ }
91
+ }
92
+ self::$meta_cache[$this->table] = array('primary' => $primary, 'auto_increment' => $auto_increment);
93
+ }
94
+ $this->primary = self::$meta_cache[$this->table]['primary'];
95
+ $this->auto_increment = self::$meta_cache[$this->table]['auto_increment'];
96
+
97
+ return $this;
98
+ }
99
+
100
+ /**
101
+ * Return database table name this object is bound to
102
+ * @return string
103
+ */
104
+ public function getTable() {
105
+ return $this->table;
106
+ }
107
+ /**
108
+ * Return column name with table name
109
+ * @param string $col
110
+ * @return string
111
+ */
112
+ public function getFieldName($col) {
113
+ return $this->table . '.' . $col;
114
+ }
115
+
116
+ /**
117
+ * Compose WHERE clause based on parameters provided
118
+ * @param string|array $field
119
+ * @param mixed[optional] $value
120
+ * @param string[optional] $operator AND or OR string, 'AND' by default
121
+ * @return string
122
+ */
123
+ protected function buildWhere($field, $value = NULL, $operator = NULL) {
124
+ if ( ! is_array($field)) {
125
+ $field = array($field => $value);
126
+ } else { // shift arguments
127
+ $operator = $value;
128
+ }
129
+ ! is_null($operator) or $operator = 'AND'; // apply default operator value
130
+
131
+ $where = array();
132
+ foreach ($field as $key => $val) {
133
+ if (is_int($key)) {
134
+ $where[] = '(' . call_user_func_array(array($this, 'buildWhere'), $val) . ')';
135
+ } else {
136
+ if ( ! preg_match('%^(.+?) *(=|<>|!=|<|>|<=|>=| (NOT +)?(IN|(LIKE|REGEXP|RLIKE)( BINARY)?))?$%i', trim($key), $mtch)) {
137
+ throw new Exception('Wrong field name format.');
138
+ }
139
+ $key = $mtch[1];
140
+ if (is_array($val) and (empty($mtch[2]) or 'IN' == strtoupper($mtch[4]))) {
141
+ $op = empty($mtch[2]) ? 'IN' : strtoupper(trim($mtch[2]));
142
+ $where[] = $this->wpdb->prepare("$key $op (" . implode(', ', array_fill(0, count($val), "%s")) . ")", $val);
143
+ } else {
144
+ $op = empty($mtch[2]) ? '=' : strtoupper(trim($mtch[2]));
145
+ $where[] = $this->wpdb->prepare("$key $op %s", $val);
146
+ }
147
+ }
148
+ }
149
+ return implode(" $operator ", $where);
150
+ }
151
+
152
+
153
+ /**
154
+ * Return associative array with record data
155
+ * @param bool[optional] $serialize Whether returned fields should be serialized
156
+ * @return array
157
+ */
158
+ public function toArray($serialize = FALSE) {
159
+ $result = (array)$this;
160
+ if ($serialize) {
161
+ foreach ($result as $k => $v) {
162
+ if ( ! is_scalar($v)) {
163
+ $result[$k] = serialize($v);
164
+ }
165
+ }
166
+ }
167
+ return $result;
168
+ }
169
+
170
+ /**
171
+ * Check whether object data is empty
172
+ * @return bool
173
+ */
174
+ public function isEmpty() {
175
+ return $this->count() == 0;
176
+ }
177
+
178
+ /**
179
+ * Empty object data
180
+ * @return PMWI_Model
181
+ */
182
+ public function clear() {
183
+ $this->exchangeArray(array());
184
+ return $this;
185
+ }
186
+
187
+ /**
188
+ * Delete all content from model's table
189
+ * @return PMWI_Model
190
+ */
191
+ public function truncateTable() {
192
+ if (FALSE !== $this->wpdb->query("TRUNCATE $this->table")) {
193
+ return $this;
194
+ } else {
195
+ throw new Exception($this->wpdb->last_error);
196
+ }
197
+ }
198
+ }
models/model/list.php ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Incapsulates behavior for list of database records
4
+ *
5
+ * @author Pavel Kulbakin <p.kulbakin@gmail.com>
6
+ */
7
+ class PMWI_Model_List extends PMWI_Model {
8
+
9
+ /**
10
+ * Total number of records in database which correspond last getBy rule without paging
11
+ * @var int
12
+ */
13
+ protected $total = 0;
14
+
15
+ /**
16
+ * Joined tables
17
+ * @var array
18
+ */
19
+ protected $joined = array();
20
+ /**
21
+ * Columns to select from database
22
+ * @var string
23
+ */
24
+ protected $what = '*';
25
+ /**
26
+ * Sets table to use in conjuction with primary list table
27
+ * @param string $table Table to join
28
+ * @param string $on Condition to join
29
+ * @param string $type Join type (INNER, OUTER, etc)
30
+ * @return PMWI_Model_List
31
+ */
32
+ public function join($table, $on, $type = 'INNER') {
33
+ $this->joined[] = ( ! is_null($type) ? $type . ' ' : '') . 'JOIN ' . $table . ' ON ' . $on;
34
+ return $this;
35
+ }
36
+
37
+ /**
38
+ * Set columns to be selected from database
39
+ * @param array $columns
40
+ * @return PMWI_Model_List
41
+ */
42
+ public function setColumns($columns) {
43
+ is_array($columns) or $columns = func_get_args();
44
+ $this->what = implode(', ', $columns);
45
+ return $this;
46
+ }
47
+
48
+ /**
49
+ * Read records from database by specified fields and values
50
+ * When 1st parameter is an array, it's expected to be an associative array of field => value pairs to read data by
51
+ * When 2nd parameter is a scalar, it's expected to be a field name and second parameter - it's value
52
+ *
53
+ * @param string|array[optional] $field
54
+ * @param mixed[optional] $value
55
+ * @param string[optional] $orderBy Ordering rule
56
+ * @param int[optional] $page Paging paramter used to limit number of records returned
57
+ * @param int[optional] $perPage Page size when paging parameter is used (20 by default)
58
+ * @return PMWI_Model_List
59
+ */
60
+ public function getBy($field = NULL, $value = NULL, $orderBy = NULL, $page = NULL, $perPage = NULL, $groupBy = NULL) {
61
+ if (is_array($field) or is_null($field)) { // when associative array is submitted, do not expect second paramter to be $value, but act as if there is no $value parameter at all
62
+ $groupBy = $perPage; $perPage = $page; $page = $orderBy; $orderBy = $value; $value = NULL;
63
+ }
64
+ ! is_null($perPage) or $perPage = 20; // set default value for page length
65
+ $page = intval($page);
66
+
67
+ $sql = "FROM $this->table ";
68
+ $sql .= implode(' ', $this->joined);
69
+ if ( ! is_null($field)) {
70
+ $sql .= " WHERE " . $this->buildWhere($field, $value);
71
+ }
72
+ if ( ! is_null($groupBy)) {
73
+ $sql .= " GROUP BY $groupBy";
74
+ }
75
+ is_null($orderBy) and $orderBy = implode(', ', $this->primary); // default sort order is by primary key
76
+ $sql .= " ORDER BY $orderBy";
77
+ if ($page > 0) {
78
+ $sql = "SELECT SQL_CALC_FOUND_ROWS $this->what $sql LIMIT " . intval(($page - 1) * $perPage) . ", " . intval($perPage);
79
+ } else {
80
+ $sql = "SELECT $this->what $sql";
81
+ }
82
+ $result = $this->wpdb->get_results($sql, ARRAY_A);
83
+ if (is_array($result)) {
84
+ foreach ($result as $i => $row) {
85
+ foreach ($row as $k => $v) {
86
+ if (is_serialized($v)) {
87
+ $result[$i][$k] = unserialize($v);
88
+ }
89
+ }
90
+ }
91
+ if ($page > 0) {
92
+ $this->total = intval($this->wpdb->get_var('SELECT FOUND_ROWS()'));
93
+ } else {
94
+ $this->total = count($result);
95
+ }
96
+ $this->exchangeArray($result);
97
+ } else {
98
+ $this->total = 0;
99
+ $this->clear();
100
+ }
101
+ return $this;
102
+ }
103
+
104
+ /**
105
+ * Count records in table
106
+ * @param string|array $field
107
+ * @param mixed[optional] $value
108
+ * @return int
109
+ */
110
+ public function countBy($field = NULL, $value = NULL) {
111
+ $sql = "SELECT COUNT(*) FROM $this->table ";
112
+ $sql .= implode(' ', $this->joined);
113
+ if ( ! is_null($field)) {
114
+ $sql .= " WHERE " . $this->buildWhere($field, $value);
115
+ }
116
+ return intval($this->wpdb->get_var($sql));
117
+ }
118
+
119
+ /**
120
+ * Method returns number of rows in database which correspond last getBy query
121
+ * @return int
122
+ */
123
+ public function total() {
124
+ return $this->total;
125
+ }
126
+
127
+ /**
128
+ * Converts elements to instances of specifield class. If includeFields are provided only fields listed are included
129
+ * @param string[optoinal] $elementClass
130
+ * @param array[optional] $includeFields
131
+ * @return PMWI_Model_List
132
+ */
133
+ public function convertRecords($elementClass = NULL, $includeFields = NULL) {
134
+ ! is_null($elementClass) or $elementClass = preg_replace('%List$%', 'Record', get_class($this));
135
+ if ( ! is_subclass_of($elementClass, PMWI_Plugin::PREFIX . 'Model_Record')) {
136
+ throw new Exception("Provideded class name $elementClass must be a subclass of " . PMWI_Plugin::PREFIX . 'Model_Record');
137
+ }
138
+ $records = $this->exchangeArray(array());
139
+ foreach ($records as $r) {
140
+ $data = (array)$r;
141
+ if ( ! is_null($includeFields)) {
142
+ $data = array_intersect_key($data, array_flip($includeFields));
143
+ }
144
+ $this[] = new $elementClass($data);
145
+ }
146
+ return $this;
147
+ }
148
+
149
+ }
models/model/record.php ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Base class for models
4
+ *
5
+ * @author Pavel Kulbakin <p.kulbakin@gmail.com>
6
+ */
7
+ class PMWI_Model_Record extends PMWI_Model {
8
+ /**
9
+ * Initialize model
10
+ * @param array[optional] $data Array of record data to initialize object with
11
+ */
12
+ public function __construct($data = array()) {
13
+ parent::__construct();
14
+ if (! is_array($data)) {
15
+ throw new Exception("Array expected as paramenter for " . get_class($this) . "::" . __METHOD__);
16
+ }
17
+ $data and $this->set($data);
18
+ }
19
+
20
+ /**
21
+ * @see PMWI_Model::getBy()
22
+ * @return PMWI_Model_Record
23
+ */
24
+ public function getBy($field = NULL, $value = NULL) {
25
+ if (is_null($field)) {
26
+ throw new Exception("Field parameter is expected at " . get_class($this) . "::" . __METHOD__);
27
+ }
28
+ $sql = "SELECT * FROM $this->table WHERE " . $this->buildWhere($field, $value);
29
+ $result = $this->wpdb->get_row($sql, ARRAY_A);
30
+ if (is_array($result)) {
31
+ foreach ($result as $k => $v) {
32
+ if (is_serialized($v)) {
33
+ $result[$k] = unserialize($v);
34
+ }
35
+ }
36
+ $this->exchangeArray($result);
37
+ } else {
38
+ $this->clear();
39
+ }
40
+ return $this;
41
+ }
42
+
43
+ /**
44
+ * Ger records related to current one
45
+ * @param string $model Class name of model of related records
46
+ * @param array[optoinal] $keyAssoc
47
+ * @return PMWI_Model_List
48
+ */
49
+ public function getRelated($model, $keyAssoc = NULL) {
50
+ $related = new $model();
51
+ if ( ! empty($this->id)) {
52
+ if (is_null($keyAssoc)) {
53
+ $defaultPrefix = strtolower(preg_replace('%^' . strtoupper(PMWI_Plugin::PREFIX) . '|_Record$%', '', get_class($this)));
54
+ $keyAssoc = array();
55
+ foreach ($this->primary as $key) {
56
+ $keyAssoc = array($defaultPrefix . '_' . $key => $key);
57
+ }
58
+ }
59
+ foreach ($keyAssoc as $foreign => $local) {
60
+ $keyAssoc[$foreign] = $this->$local;
61
+ }
62
+ $related->getBy($keyAssoc);
63
+ }
64
+ return $related instanceof PMWI_Model_List ? $related->convertRecords() : $related;
65
+ }
66
+
67
+ /**
68
+ * Saves currently set object data as database record
69
+ * @return PMWI_Model_Record
70
+ */
71
+ public function insert() {
72
+ if ($this->wpdb->insert($this->table, $this->toArray(TRUE))) {
73
+ if (isset($this->auto_increment)) {
74
+ $this[$this->primary[0]] = $this->wpdb->insert_id;
75
+ }
76
+ return $this;
77
+ } else {
78
+ throw new Exception($this->wpdb->last_error);
79
+ }
80
+ }
81
+ /**
82
+ * Update record in database
83
+ * @return PMWI_Model_Record
84
+ */
85
+ public function update() {
86
+ $record = $this->toArray(TRUE);
87
+ $this->wpdb->update($this->table, $record, array_intersect_key($record, array_flip($this->primary)));
88
+ if ($this->wpdb->last_error) {
89
+ throw new Exception($this->wpdb->last_error);
90
+ }
91
+ return $this;
92
+ }
93
+
94
+ /**
95
+ * Delete record form database
96
+ * @return PMWI_Model_Record
97
+ */
98
+ public function delete() {
99
+ if ($this->wpdb->query("DELETE FROM $this->table WHERE " . $this->buildWhere(array_intersect_key($this->toArray(TRUE), array_flip($this->primary))))) {
100
+ return $this;
101
+ } else {
102
+ throw new Exception($this->wpdb->last_error);
103
+ }
104
+ }
105
+ /**
106
+ * Insert or Update the record
107
+ * WARNING: function doesn't check actual record presents in database, it simply tries to insert if no primary key specified and update otherwise
108
+ * @return PMWI_Model_Record
109
+ */
110
+ public function save() {
111
+ if (array_intersect_key($this->toArray(TRUE), array_flip($this->primary))) {
112
+ $this->update();
113
+ } else {
114
+ $this->insert();
115
+ }
116
+ return $this;
117
+ }
118
+
119
+ /**
120
+ * Set record data
121
+ * When 1st parameter is an array, it expected to be an associative array of field => value pairs
122
+ * If 2 parameters are set, first one is expected to be a field name and second - it's value
123
+ *
124
+ * @param string|array $field
125
+ * @param mixed[optional] $value
126
+ * @return PMWI_Model_Record
127
+ */
128
+ public function set($field, $value = NULL) {
129
+ if (is_array($field) and ( ! is_null($value) or 0 == count($field))) {
130
+ throw new Exception(__CLASS__ . "::set method expects either not empty associative array as the only paramter or field name and it's value as two seperate parameters.");
131
+ }
132
+ if (is_array($field)) {
133
+ $this->exchangeArray(array_merge($this->toArray(), $field));
134
+ } else {
135
+ $this[$field] = $value;
136
+ }
137
+
138
+ return $this;
139
+ }
140
+
141
+ /**
142
+ * Magic method to resolved object-like request to record values in format $obj->%FIELD_NAME%
143
+ * @param string $field
144
+ * @return mixed
145
+ */
146
+ public function __get($field) {
147
+ if ( ! $this->offsetExists($field)) {
148
+ throw new Exception("Undefined field $field.");
149
+ }
150
+ return $this[$field];
151
+ }
152
+ /**
153
+ * Magic method to assign values to record fields in format $obj->%FIELD_NAME = value
154
+ * @param string $field
155
+ * @param mixed $value
156
+ */
157
+ public function __set($field, $value) {
158
+ $this[$field] = $value;
159
+ }
160
+ /**
161
+ * Magic method to check wether some record fields are set
162
+ * @param string $field
163
+ * @return bool
164
+ */
165
+ public function __isset($field) {
166
+ return $this->offsetExists($field);
167
+ }
168
+ /**
169
+ * Magic method to unset record fields
170
+ * @param string $field
171
+ */
172
+ public function __unset($field) {
173
+ $this->offsetUnset($field);
174
+ }
175
+
176
+ }
plugin.php ADDED
@@ -0,0 +1,517 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Plugin Name: WP All Import - WooCommerce Add-On
4
+ Plugin URI: http://www.wpallimport.com/
5
+ Description: Free edition. An extremely easy, drag & drop importer to import WooCommerce simple products. Works with WP All Import free or paid editions.
6
+ Version: 0.9
7
+ Author: Soflyy
8
+ */
9
+ /**
10
+ * Plugin root dir with forward slashes as directory separator regardless of actuall DIRECTORY_SEPARATOR value
11
+ * @var string
12
+ */
13
+ define('PMWI_FREE_ROOT_DIR', str_replace('\\', '/', dirname(__FILE__)));
14
+ /**
15
+ * Plugin root url for referencing static content
16
+ * @var string
17
+ */
18
+ define('PMWI_FREE_ROOT_URL', rtrim(plugin_dir_url(__FILE__), '/'));
19
+ /**
20
+ * Plugin prefix for making names unique (be aware that this variable is used in conjuction with naming convention,
21
+ * i.e. in order to change it one must not only modify this constant but also rename all constants, classes and functions which
22
+ * names composed using this prefix)
23
+ * @var string
24
+ */
25
+ define('PMWI_PREFIX', 'pmwi_');
26
+
27
+ define('PMWI_FREE_VERSION', '1.0');
28
+
29
+ define('PMWI_EDITION', 'free');
30
+
31
+ /**
32
+ * Main plugin file, Introduces MVC pattern
33
+ *
34
+ * @singletone
35
+ * @author Pavel Kulbakin <p.kulbakin@gmail.com>
36
+ */
37
+ final class PMWI_Plugin {
38
+ /**
39
+ * Singletone instance
40
+ * @var PMWI_Plugin
41
+ */
42
+ protected static $instance;
43
+
44
+ /**
45
+ * Plugin options
46
+ * @var array
47
+ */
48
+ protected $options = array();
49
+
50
+ /**
51
+ * Plugin root dir
52
+ * @var string
53
+ */
54
+ const ROOT_DIR = PMWI_FREE_ROOT_DIR;
55
+ /**
56
+ * Plugin root URL
57
+ * @var string
58
+ */
59
+ const ROOT_URL = PMWI_FREE_ROOT_URL;
60
+ /**
61
+ * Prefix used for names of shortcodes, action handlers, filter functions etc.
62
+ * @var string
63
+ */
64
+ const PREFIX = PMWI_PREFIX;
65
+ /**
66
+ * Plugin file path
67
+ * @var string
68
+ */
69
+ const FILE = __FILE__;
70
+
71
+ /**
72
+ * Return singletone instance
73
+ * @return PMWI_Plugin
74
+ */
75
+ static public function getInstance() {
76
+ if (self::$instance == NULL) {
77
+ self::$instance = new self();
78
+ }
79
+ return self::$instance;
80
+ }
81
+
82
+ /**
83
+ * Common logic for requestin plugin info fields
84
+ */
85
+ public function __call($method, $args) {
86
+ if (preg_match('%^get(.+)%i', $method, $mtch)) {
87
+ $info = get_plugin_data(self::FILE);
88
+ if (isset($info[$mtch[1]])) {
89
+ return $info[$mtch[1]];
90
+ }
91
+ }
92
+ throw new Exception("Requested method " . get_class($this) . "::$method doesn't exist.");
93
+ }
94
+
95
+ /**
96
+ * Get path to plagin dir relative to wordpress root
97
+ * @param bool[optional] $noForwardSlash Whether path should be returned withot forwarding slash
98
+ * @return string
99
+ */
100
+ public function getRelativePath($noForwardSlash = false) {
101
+ $wp_root = str_replace('\\', '/', ABSPATH);
102
+ return ($noForwardSlash ? '' : '/') . str_replace($wp_root, '', self::ROOT_DIR);
103
+ }
104
+
105
+ /**
106
+ * Check whether plugin is activated as network one
107
+ * @return bool
108
+ */
109
+ public function isNetwork() {
110
+ if ( !is_multisite() )
111
+ return false;
112
+
113
+ $plugins = get_site_option('active_sitewide_plugins');
114
+ if (isset($plugins[plugin_basename(self::FILE)]))
115
+ return true;
116
+
117
+ return false;
118
+ }
119
+
120
+ /**
121
+ * Check whether permalinks is enabled
122
+ * @return bool
123
+ */
124
+ public function isPermalinks() {
125
+ global $wp_rewrite;
126
+
127
+ return $wp_rewrite->using_permalinks();
128
+ }
129
+
130
+ /**
131
+ * Return prefix for plugin database tables
132
+ * @return string
133
+ */
134
+ public function getTablePrefix() {
135
+ global $wpdb;
136
+ return ($this->isNetwork() ? $wpdb->base_prefix : $wpdb->prefix) . self::PREFIX;
137
+ }
138
+
139
+ /**
140
+ * Return prefix for wordpress database tables
141
+ * @return string
142
+ */
143
+ public function getWPPrefix() {
144
+ global $wpdb;
145
+ return ($this->isNetwork() ? $wpdb->base_prefix : $wpdb->prefix);
146
+ }
147
+
148
+ /**
149
+ * Class constructor containing dispatching logic
150
+ * @param string $rootDir Plugin root dir
151
+ * @param string $pluginFilePath Plugin main file
152
+ */
153
+ protected function __construct() {
154
+
155
+ // create/update required database tables
156
+
157
+ // regirster autoloading method
158
+ if (function_exists('__autoload') and ! in_array('__autoload', spl_autoload_functions())) { // make sure old way of autoloading classes is not broken
159
+ spl_autoload_register('__autoload');
160
+ }
161
+ spl_autoload_register(array($this, '__autoload'));
162
+
163
+ // init plugin options
164
+ $option_name = get_class($this) . '_Options';
165
+ $options_default = PMWI_Config::createFromFile(self::ROOT_DIR . '/config/options.php')->toArray();
166
+ $this->options = array_intersect_key(get_option($option_name, array()), $options_default) + $options_default;
167
+ $this->options = array_intersect_key($options_default, array_flip(array('info_api_url'))) + $this->options; // make sure hidden options apply upon plugin reactivation
168
+
169
+ update_option($option_name, $this->options);
170
+ $this->options = get_option(get_class($this) . '_Options');
171
+
172
+ register_activation_hook(self::FILE, array($this, '__activation'));
173
+
174
+ // register action handlers
175
+ if (is_dir(self::ROOT_DIR . '/actions')) if (is_dir(self::ROOT_DIR . '/actions')) foreach (PMWI_Helper::safe_glob(self::ROOT_DIR . '/actions/*.php', PMWI_Helper::GLOB_RECURSE | PMWI_Helper::GLOB_PATH) as $filePath) {
176
+ require_once $filePath;
177
+ $function = $actionName = basename($filePath, '.php');
178
+ if (preg_match('%^(.+?)[_-](\d+)$%', $actionName, $m)) {
179
+ $actionName = $m[1];
180
+ $priority = intval($m[2]);
181
+ } else {
182
+ $priority = 10;
183
+ }
184
+ 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)
185
+ }
186
+
187
+ // register filter handlers
188
+ if (is_dir(self::ROOT_DIR . '/filters')) foreach (PMWI_Helper::safe_glob(self::ROOT_DIR . '/filters/*.php', PMWI_Helper::GLOB_RECURSE | PMWI_Helper::GLOB_PATH) as $filePath) {
189
+ require_once $filePath;
190
+ $function = $actionName = basename($filePath, '.php');
191
+ if (preg_match('%^(.+?)[_-](\d+)$%', $actionName, $m)) {
192
+ $actionName = $m[1];
193
+ $priority = intval($m[2]);
194
+ } else {
195
+ $priority = 10;
196
+ }
197
+ 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)
198
+ }
199
+
200
+ // register shortcodes handlers
201
+ if (is_dir(self::ROOT_DIR . '/shortcodes')) foreach (PMWI_Helper::safe_glob(self::ROOT_DIR . '/shortcodes/*.php', PMWI_Helper::GLOB_RECURSE | PMWI_Helper::GLOB_PATH) as $filePath) {
202
+ $tag = strtolower(str_replace('/', '_', preg_replace('%^' . preg_quote(self::ROOT_DIR . '/shortcodes/', '%') . '|\.php$%', '', $filePath)));
203
+ add_shortcode($tag, array($this, 'shortcodeDispatcher'));
204
+ }
205
+
206
+ // register admin page pre-dispatcher
207
+ add_action('admin_init', array($this, '__adminInit'));
208
+
209
+ }
210
+
211
+ /**
212
+ * pre-dispatching logic for admin page controllers
213
+ */
214
+ public function __adminInit() {
215
+ $input = new PMWI_Input();
216
+ $page = strtolower($input->getpost('page', ''));
217
+ if (preg_match('%^' . preg_quote(str_replace('_', '-', self::PREFIX), '%') . '([\w-]+)$%', $page)) {
218
+ $this->adminDispatcher($page, strtolower($input->getpost('action', 'index')));
219
+ }
220
+ }
221
+
222
+ /**
223
+ * Dispatch shorttag: create corresponding controller instance and call its index method
224
+ * @param array $args Shortcode tag attributes
225
+ * @param string $content Shortcode tag content
226
+ * @param string $tag Shortcode tag name which is being dispatched
227
+ * @return string
228
+ */
229
+ public function shortcodeDispatcher($args, $content, $tag) {
230
+
231
+ $controllerName = self::PREFIX . preg_replace('%(^|_).%e', 'strtoupper("$0")', $tag); // capitalize first letters of class name parts and add prefix
232
+ $controller = new $controllerName();
233
+ if ( ! $controller instanceof PMWI_Controller) {
234
+ throw new Exception("Shortcode `$tag` matches to a wrong controller type.");
235
+ }
236
+ ob_start();
237
+ $controller->index($args, $content);
238
+ return ob_get_clean();
239
+ }
240
+
241
+ /**
242
+ * Dispatch admin page: call corresponding controller based on get parameter `page`
243
+ * The method is called twice: 1st time as handler `parse_header` action and then as admin menu item handler
244
+ * @param string[optional] $page When $page set to empty string ealier buffered content is outputted, otherwise controller is called based on $page value
245
+ */
246
+ public function adminDispatcher($page = '', $action = 'index') {
247
+ static $buffer = NULL;
248
+ static $buffer_callback = NULL;
249
+ if ('' === $page) {
250
+ if ( ! is_null($buffer)) {
251
+ echo '<div class="wrap">';
252
+ echo $buffer;
253
+ do_action('PMWI_action_after');
254
+ echo '</div>';
255
+ } elseif ( ! is_null($buffer_callback)) {
256
+ echo '<div class="wrap">';
257
+ call_user_func($buffer_callback);
258
+ do_action('PMWI_action_after');
259
+ echo '</div>';
260
+ } else {
261
+ throw new Exception('There is no previousely buffered content to display.');
262
+ }
263
+ } else {
264
+ $controllerName = preg_replace('%(^' . preg_quote(self::PREFIX, '%') . '|_).%e', 'strtoupper("$0")', str_replace('-', '_', $page)); // capitalize prefix and first letters of class name parts
265
+ $actionName = str_replace('-', '_', $action);
266
+ if (method_exists($controllerName, $actionName)) {
267
+ $this->_admin_current_screen = (object)array(
268
+ 'id' => $controllerName,
269
+ 'base' => $controllerName,
270
+ 'action' => $actionName,
271
+ 'is_ajax' => isset($_SERVER['HTTP_X_REQUESTED_WITH']) and strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest',
272
+ 'is_network' => is_network_admin(),
273
+ 'is_user' => is_user_admin(),
274
+ );
275
+ add_filter('current_screen', array($this, 'getAdminCurrentScreen'));
276
+ add_filter('admin_body_class', create_function('', 'return "' . PMWI_Plugin::PREFIX . 'plugin";'));
277
+
278
+ $controller = new $controllerName();
279
+ if ( ! $controller instanceof PMWI_Controller_Admin) {
280
+ throw new Exception("Administration page `$page` matches to a wrong controller type.");
281
+ }
282
+
283
+ if ($this->_admin_current_screen->is_ajax) { // ajax request
284
+ $controller->$action();
285
+ do_action('PMWI_action_after');
286
+ die(); // stop processing since we want to output only what controller is randered, nothing in addition
287
+ } elseif ( ! $controller->isInline) {
288
+ ob_start();
289
+ $controller->$action();
290
+ $buffer = ob_get_clean();
291
+ } else {
292
+ $buffer_callback = array($controller, $action);
293
+ }
294
+ } else { // redirect to dashboard if requested page and/or action don't exist
295
+ wp_redirect(admin_url()); die();
296
+ }
297
+ }
298
+ }
299
+
300
+ protected $_admin_current_screen = NULL;
301
+ public function getAdminCurrentScreen()
302
+ {
303
+ return $this->_admin_current_screen;
304
+ }
305
+
306
+ /**
307
+ * Autoloader
308
+ * It's assumed class name consists of prefix folloed by its name which in turn corresponds to location of source file
309
+ * if `_` symbols replaced by directory path separator. File name consists of prefix folloed by last part in class name (i.e.
310
+ * symbols after last `_` in class name)
311
+ * When class has prefix it's source is looked in `models`, `controllers`, `shortcodes` folders, otherwise it looked in `core` or `library` folder
312
+ *
313
+ * @param string $className
314
+ * @return bool
315
+ */
316
+ public function __autoload($className) {
317
+ $is_prefix = false;
318
+ $filePath = str_replace('_', '/', preg_replace('%^' . preg_quote(self::PREFIX, '%') . '%', '', strtolower($className), 1, $is_prefix)) . '.php';
319
+ if ( ! $is_prefix) { // also check file with original letter case
320
+ $filePathAlt = $className . '.php';
321
+ }
322
+ foreach ($is_prefix ? array('models', 'controllers', 'shortcodes', 'classes') : array() as $subdir) {
323
+ $path = self::ROOT_DIR . '/' . $subdir . '/' . $filePath;
324
+ if (is_file($path)) {
325
+ require $path;
326
+ return TRUE;
327
+ }
328
+ if ( ! $is_prefix) {
329
+ $pathAlt = self::ROOT_DIR . '/' . $subdir . '/' . $filePathAlt;
330
+ if (is_file($pathAlt)) {
331
+ require $pathAlt;
332
+ return TRUE;
333
+ }
334
+ }
335
+ }
336
+
337
+ return FALSE;
338
+ }
339
+
340
+ /**
341
+ * Get plugin option
342
+ * @param string[optional] $option Parameter to return, all array of options is returned if not set
343
+ * @return mixed
344
+ */
345
+ public function getOption($option = NULL) {
346
+ if (is_null($option)) {
347
+ return $this->options;
348
+ } else if (isset($this->options[$option])) {
349
+ return $this->options[$option];
350
+ } else {
351
+ throw new Exception("Specified option is not defined for the plugin");
352
+ }
353
+ }
354
+ /**
355
+ * Update plugin option value
356
+ * @param string $option Parameter name or array of name => value pairs
357
+ * @param mixed[optional] $value New value for the option, if not set than 1st parameter is supposed to be array of name => value pairs
358
+ * @return array
359
+ */
360
+ public function updateOption($option, $value = NULL) {
361
+ is_null($value) or $option = array($option => $value);
362
+ if (array_diff_key($option, $this->options)) {
363
+ throw new Exception("Specified option is not defined for the plugin");
364
+ }
365
+ $this->options = $option + $this->options;
366
+ update_option(get_class($this) . '_Options', $this->options);
367
+
368
+ return $this->options;
369
+ }
370
+
371
+ /**
372
+ * Plugin activation logic
373
+ */
374
+ public function __activation() {
375
+
376
+ // uncaught exception doesn't prevent plugin from being activated, therefore replace it with fatal error so it does
377
+ set_exception_handler(create_function('$e', 'trigger_error($e->getMessage(), E_USER_ERROR);'));
378
+
379
+ // create plugin options
380
+ $option_name = get_class($this) . '_Options';
381
+ $options_default = PMWI_Config::createFromFile(self::ROOT_DIR . '/config/options.php')->toArray();
382
+ update_option($option_name, $options_default);
383
+
384
+ }
385
+
386
+ /**
387
+ * Method returns default import options, main utility of the method is to avoid warnings when new
388
+ * option is introduced but already registered imports don't have it
389
+ */
390
+ public static function get_default_import_options() {
391
+ return array(
392
+ 'is_multiple_product_type' => 'yes',
393
+ 'multiple_product_type' => 'simple',
394
+ 'single_product_type' => '',
395
+ 'is_product_virtual' => 'no',
396
+ 'single_product_virtual' => '',
397
+ 'is_product_downloadable' => 'no',
398
+ 'single_product_downloadable' => '',
399
+ 'is_product_enabled' => 'yes',
400
+ 'single_product_enabled' => '',
401
+ 'is_product_featured' => 'no',
402
+ 'single_product_featured' => '',
403
+ 'is_product_visibility' => 'visible',
404
+ 'single_product_visibility' => '',
405
+ 'single_product_sku' => '',
406
+ 'single_product_url' => '',
407
+ 'single_product_button_text' => '',
408
+ 'single_product_regular_price' => '',
409
+ 'single_product_sale_price' => '',
410
+ 'single_product_files' => '',
411
+ 'single_product_download_limit' => '',
412
+ 'single_product_download_expiry' => '',
413
+ 'is_multiple_product_tax_status' => 'yes',
414
+ 'multiple_product_tax_status' => 'none',
415
+ 'single_product_tax_status' => '',
416
+ 'is_multiple_product_tax_class' => 'yes',
417
+ 'multiple_product_tax_class' => '',
418
+ 'single_product_tax_class' => '',
419
+ 'is_product_manage_stock' => 'no',
420
+ 'single_product_manage_stock' => '',
421
+ 'single_product_stock_qty' => '',
422
+ 'product_stock_status' => 'instock',
423
+ 'single_product_stock_status' => '',
424
+ 'product_allow_backorders' => 'no',
425
+ 'single_product_allow_backorders' => '',
426
+ 'product_sold_individually' => 'no',
427
+ 'single_product_sold_individually' => '',
428
+ 'single_product_weight' => '',
429
+ 'single_product_length' => '',
430
+ 'single_product_width' => '',
431
+ 'single_product_height' => '',
432
+ 'is_multiple_product_shipping_class' => 'yes',
433
+ 'multiple_product_shipping_class' => '',
434
+ 'single_product_shipping_class' => '',
435
+ 'single_product_up_sells' => '',
436
+ 'single_product_cross_sells' => '',
437
+ 'attribute_name' => array(),
438
+ 'attribute_value' => array(),
439
+ 'in_variations' => array(),
440
+ 'is_visible' => array(),
441
+ 'is_taxonomy' => array(),
442
+ 'create_taxonomy_in_not_exists' => array(),
443
+ 'single_product_purchase_note' => '',
444
+ 'single_product_menu_order' => 0,
445
+ 'is_product_enable_reviews' => 'no',
446
+ 'single_product_enable_reviews' => '',
447
+ 'single_product_id' => '',
448
+ 'single_product_parent_id' => '',
449
+ '_virtual' => 0,
450
+ '_downloadable' => 0,
451
+ 'is_regular_price_shedule' => 0,
452
+ 'single_sale_price_dates_from' => 'now',
453
+ 'single_sale_price_dates_to' => 'now',
454
+ 'product_files_delim' => ',',
455
+ 'grouping_product' => '',
456
+ 'matching_parent' => 'auto',
457
+ 'parent_indicator' => 'custom field',
458
+ 'custom_parent_indicator_name' => '',
459
+ 'custom_parent_indicator_value' => '',
460
+ 'missing_records_stock_status' => 0,
461
+ 'variations_xpath' => '',
462
+ '_variable_virtual' => '',
463
+ '_variable_downloadable' => '',
464
+ 'variable_stock' => '',
465
+ 'variable_regular_price' => '',
466
+ 'variable_sale_price' => '',
467
+ 'is_variable_sale_price_shedule' => 0,
468
+ 'variable_sale_price_dates_from' => '',
469
+ 'variable_sale_price_dates_to' => '',
470
+ 'variable_weight' => '',
471
+ 'variable_length' => '',
472
+ 'variable_width' => '',
473
+ 'variable_height' => '',
474
+ 'variable_shipping_class' => '',
475
+ 'variable_tax_class' => '',
476
+ 'variable_file_paths' => '',
477
+ 'variable_download_limit' => '',
478
+ 'variable_download_expiry' => '',
479
+ 'is_variable_product_virtual' => 'no',
480
+ 'is_multiple_variable_product_shipping_class' => 'yes',
481
+ 'multiple_variable_product_shipping_class' => '',
482
+ 'single_variable_product_shipping_class' => '',
483
+ 'is_multiple_variable_product_tax_class' => 'yes',
484
+ 'multiple_variable_product_tax_class' => 'parent',
485
+ 'single_variable_product_tax_class' => '',
486
+ 'is_variable_product_downloadable' => 'no',
487
+ 'single_variable_product_downloadable' => '',
488
+ 'variable_attribute_name' => array(),
489
+ 'variable_attribute_value' => array(),
490
+ 'variable_in_variations' => array(),
491
+ 'variable_is_visible' => array(),
492
+ 'variable_is_taxonomy' => array(),
493
+ 'variable_create_taxonomy_in_not_exists' => array(),
494
+ 'variable_product_files_delim' => ',',
495
+ 'variable_image' => '',
496
+ 'variable_sku' => '',
497
+ 'is_variable_product_enabled' => 'yes',
498
+ 'single_variable_product_enabled' => '',
499
+ 'link_all_variations' => 0,
500
+ 'variable_stock_use_parent' => 0,
501
+ 'variable_regular_price_use_parent' => 0,
502
+ 'variable_sale_price_use_parent' => 0,
503
+ 'variable_sale_dates_use_parent' => 0,
504
+ 'variable_weight_use_parent' => 0,
505
+ 'single_variable_product_virtual_use_parent' => 0,
506
+ 'variable_dimensions_use_parent' => 0,
507
+ 'variable_image_use_parent' => 0,
508
+ 'single_variable_product_shipping_class_use_parent' => 0,
509
+ 'single_variable_product_tax_class_use_parent' => 0,
510
+ 'single_variable_product_downloadable_use_parent' => 0,
511
+ 'variable_download_limit_use_parent' => 0,
512
+ 'variable_download_expiry_use_parent' => 0
513
+ );
514
+ }
515
+ }
516
+
517
+ PMWI_Plugin::getInstance();
readme.txt ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === Import Products from any XML or CSV to WooCommerce ===
2
+ Contributors: soflyy
3
+ Requires at least: 3.5
4
+ Tested up to: 3.5.2
5
+ Stable tag: 0.9
6
+ License: GPLv2 or later
7
+ License URI: http://www.gnu.org/licenses/gpl-2.0.html
8
+ Tags: woocommerce xml import, woocommerce csv import, woocommerce, import, xml, csv, wp all import
9
+
10
+ Easily import products from any XML or CSV file to WooCommerce with the WooCommerce add-on for WP All Import.
11
+
12
+ == Description ==
13
+
14
+ **Bulk import your products to WooCommerce in less than 10 minutes with the WooCommerce add-on.**
15
+
16
+ The left side of the plugin looks just like WooCommerce, and the right side displays a product from your XML/CSV file.
17
+
18
+ **Drag & drop the data from your XML or CSV into the WooCommerce fields to import it.**
19
+
20
+ It is so intuitive it is almost like manually adding a product in WooCommerce.
21
+
22
+ Why use the WooCommerce add-on for WP All Import?
23
+
24
+ - Supports files in any format and structure. There are no requirements that the data in your file be organized in a certain way.
25
+ - Supports files of practically unlimited size by automatically splitting them into chunks. Import 100Mb+ product catalogs with ease, even on shared hosting.
26
+
27
+ [youtube http://www.youtube.com/watch?v=7xL4RGT-JRc]
28
+ *demo video shows some pro version only features*
29
+
30
+ Upgrade to the professional edition of **WP All Import + the WooCommerce add-on** to:
31
+
32
+ * Import External/Affiliate products, Grouped products, and Variable products.
33
+
34
+ * Import files from a URL or FTP server - Download and import files from external websites or FTP servers, even if they are password protected. FTP imports support wildcard patterns, i.e. *.xml, so for example you could download and import all XML files in a certain folder.
35
+
36
+ * Cron Job/Recurring Imports - WP All Import pro can check periodically check a file for updates, and add, edit, delete, and update the stock status of the imported products accordingly.
37
+
38
+ * Execution of Custom PHP Functions on data, i.e. use something like [my_function({xpath/to/a/field[1]})] in your template, to pass the value of {xpath/to/a/field[1]} to my_function and use whatever it returns.
39
+
40
+ * Get access to our customer portal with documentation and tutorials, and e-mail technical support.
41
+
42
+ [Upgrade to the professional edition of WP All Import + the WooCommerce add-on now.](http://www.wpallimport.com/woocommerce-product-import "WooCommerce XML & CSV Import")
43
+
44
+ You need the WooCommerce add-on if you need to:
45
+
46
+ * Import XML to WooCommerce
47
+ * Import CSV to WooCommerce
48
+ * Are frustrated with the limitations of the official WooThemes Product CSV Import Suite
49
+
50
+ == Installation ==
51
+
52
+ First, install [WP All Import](http://wordpress.org/plugins/wp-all-import "WordPress XML & CSV Import").
53
+
54
+ Then install the WooCommerce add-on.
55
+
56
+ To install the WooCommerce add-on, either: -
57
+
58
+ - Upload the plugin from the Plugins page in WordPress
59
+ - Unzip woocommere-product-import-add-on-for-wp-all-import.zip and upload the contents to /wp-content/plugins/, and then activate the plugin from the Plugins page in WordPress
60
+
61
+ The WooCommerce add-on will appear in the Step 4 of WP All Import.
62
+
63
+ == Screenshots ==
64
+
65
+ 1. The WooCommerce add-on.
66
+
67
+ == Changelog ==
68
+
69
+ = 0.9 =
70
+ * Initial release.
71
+
72
+ == Support ==
73
+
74
+ We do not handle support in the WordPress.org community forums.
75
+
76
+ We do try to handle support for our free version users at the following e-mail address:
77
+
78
+ E-mail: support@soflyy.com
79
+
80
+ Support for free version customers is not guaranteed and based on ability. For premium support, [purchase WP All Import and the WooCommerce add-on.](http://www.wpallimport.com/upgrade-to-pro)
81
+
schema.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Plugin database schema
4
+ * WARNING:
5
+ * dbDelta() doesn't like empty lines in schema string, so don't put them there;
6
+ * WPDB doesn't like NULL values so better not to have them in the tables;
7
+ */
screenshot-1.png ADDED
Binary file
static/css/admin-ie.css ADDED
File without changes
static/css/admin.css ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .pmxi_plugin #existing_meta_keys, .pmxi_plugin #existing_attributes{
2
+ margin-bottom: 10px;
3
+ padding: 2px;
4
+ width: 580px;
5
+ height:200px;
6
+ }
7
+ .pmxi_checkbox{
8
+ position: relative;
9
+ top: -2px;
10
+ width: 50px !important;
11
+ }
12
+ .pmxi_plugin .options_group{
13
+ padding-bottom: 10px;
14
+ overflow: hidden;
15
+ }
16
+ .pmxi_plugin .options_group .input{
17
+ padding-left: 8px;
18
+ margin-top: 10px;
19
+ }
20
+ .pmxi_plugin .options_group .input input{
21
+ width:auto !important;
22
+ }
23
+ .pmxi_plugin .options_group .input label{
24
+ padding-left: 7px;
25
+ position: relative;
26
+ top: -2px;
27
+ width: auto;
28
+ }
29
+ .pmxi_plugin #woocommerce-product-data{
30
+ overflow: hidden;
31
+ }
32
+ .pmxi_plugin #woocommerce-product-data .hndle{
33
+ margin-bottom: 0px;
34
+ cursor: default;
35
+ padding: 10px;
36
+ overflow: hidden;
37
+ }
38
+ .pmxi_plugin .main_choise{
39
+ float: left;
40
+ margin-right: 5px;
41
+ padding: 5px 0;
42
+ }
43
+ .pmxi_plugin .set_with_xpath{
44
+ padding-left:20px;
45
+ position:absolute;
46
+ left:0px;
47
+ top:-15px;
48
+ }
49
+ .pmxi_plugin .in_variations select, .pmxi_plugin .is_visible select, .pmxi_plugin .is_taxonomy select{
50
+ float:none !important;
51
+ }
52
+ .pmxi_plugin .in_variations, .pmxi_plugin .is_visible, .pmxi_plugin .is_taxonomy, .pmxi_plugin .is_create_taxonomy{
53
+ display: block;
54
+ float: left;
55
+ margin-top: 10px;
56
+ margin-left: 5px;
57
+ }
58
+ .pmxi_plugin .in_variations label, .pmxi_plugin .is_visible label, .pmxi_plugin .is_taxonomy label{
59
+ width: 80px;
60
+ }
61
+ .pmxi_plugin .is_create_taxonomy label{
62
+ width: 115px;
63
+ }
64
+ .pmxi_plugin .panel{
65
+ background: #fff;
66
+ padding-bottom: 20px;
67
+ min-height: 200px;
68
+ }
69
+ .pmxi_plugin .wc-tabs{
70
+ width:152px !important;
71
+ }
72
+ .pmxi_plugin ul.wc-tabs li.active a{
73
+ width:120px !important;
74
+ background-color: #fff !important;
75
+ }
76
+ .pmxi_plugin .fleft{
77
+ float: left;
78
+ }
79
+ .pmxi_plugin #woocommerce_attributes{
80
+ padding-left: 2%;
81
+ padding-top: 10px;
82
+ width:98% !important;
83
+ }
84
+ .pmxi_plugin .variations_tree{
85
+ font-family: sans-serif;
86
+ /*position: absolute;
87
+ width:100%;
88
+ top:-155px;*/
89
+ }
90
+
91
+ .pmxi_plugin .variations_tag {
92
+ background-color: #fff;
93
+ /*position: fixed; */
94
+ margin-top: 45px;
95
+ border-top: 1px solid #DFDFDF;
96
+ -moz-border-radius-topleft: 4px;
97
+ -webkit-border-top-left-radius: 4px;
98
+ border-top-left-radius: 4px;
99
+ -moz-border-radius-topright: 4px;
100
+ -webkit-border-top-right-radius: 4px;
101
+ border-top-right-radius: 4px;
102
+ }
103
+ .pmxi_plugin .options .variations_tag{
104
+ margin-top: 0px;
105
+ }
106
+ .pmxi_plugin .variations_tag .title {
107
+ font-weight: bold;
108
+ padding: 6px 8px;
109
+ color: #464646;
110
+ background: #DFDFDF;
111
+ font-size: 12px;
112
+ }
113
+ .pmxi_plugin .variations_tag .xml {
114
+ max-height: 525px;
115
+ overflow: auto;
116
+ border: 1px solid #DFDFDF;
117
+ border-top:none;
118
+ -moz-border-radius-bottomright: 4px;
119
+ -webkit-border-bottom-right-radius: 4px;
120
+ border-bottom-right-radius: 4px;
121
+ -moz-border-radius-bottomleft: 4px;
122
+ -webkit-border-bottom-left-radius: 4px;
123
+ border-bottom-left-radius: 4px;
124
+ }
125
+ .pmxi_plugin .variations_tag .navigation {
126
+ float: right;
127
+ margin: -2px -12px 0 0;
128
+ }
129
+ .pmxi_plugin .variations_tag .navigation a,
130
+ .pmxi_plugin .variations_tag .navigation span {
131
+ font-weight: bold;
132
+ padding: 0 12px;
133
+ text-decoration: none;
134
+ }
135
+
136
+ @media screen and (max-height: 700px) {
137
+ .pmxi_plugin .variations_tag {
138
+ height:300px;
139
+ }
140
+ .pmxi_plugin .variations_tag .xml {
141
+ max-height: 265px;
142
+ }
143
+ }
144
+ .use_parent{
145
+ display: inline-block;
146
+ position: relative;
147
+ }
148
+
149
+ #woocommerce_attributes label{
150
+ font-size: 12px;
151
+ position: relative;
152
+ top:-2px;
153
+ left: 3px;
154
+ }
155
+
156
+ #variations_tag{
157
+ clear: both;
158
+ }
static/js/admin.js ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * plugin admin area javascript
3
+ */
4
+ (function($){$(function () {
5
+ if ( ! $('body.pmxi_plugin').length) return; // do not execute any code if we are not on plugin page
6
+
7
+ $('.product_data_tabs').find('a').click(function(){
8
+ $('.product_data_tabs').find('li').removeClass('active');
9
+ $(this).parent('li').addClass('active');
10
+ $('.panel').hide();
11
+ $('#' + $(this).attr('rel')).show();
12
+ });
13
+
14
+ var change_depencies = function (){
15
+
16
+ var is_variable = ($('#product-type').val() == 'variable');
17
+ var is_grouped = ($('#product-type').val() == 'grouped');
18
+ var is_simple = ($('#product-type').val() == 'simple');
19
+ var is_external = ($('#product-type').val() == 'external');
20
+ var is_downloadable = ($('#_downloadable').is(':checked'));
21
+ var is_virtual = ($('#_virtual').is(':checked'));
22
+ var is_multiple_product_type = ($('input[name=is_multiple_product_type]:checked').val() == 'yes');
23
+
24
+ if (!is_multiple_product_type) $('.product_data_tabs li, .options_group').show();
25
+
26
+ $('.product_data_tabs li, .options_group').each(function(){
27
+
28
+ if (($(this).hasClass('hide_if_grouped') ||
29
+ $(this).hasClass('hide_if_external')) && is_multiple_product_type)
30
+ {
31
+ if ($(this).hasClass('hide_if_grouped') && is_grouped) { $(this).hide(); return true; } else if ( $(this).hasClass('hide_if_grouped') && !is_grouped ) $(this).show();
32
+ if ($(this).hasClass('hide_if_external') && is_external) { $(this).hide(); return true; } else if ( $(this).hasClass('hide_if_external') && !is_external ) $(this).show();
33
+ }
34
+
35
+ if (($(this).hasClass('show_if_simple') || $(this).hasClass('show_if_variable') || $(this).hasClass('show_if_grouped') || $(this).hasClass('show_if_external')) && is_multiple_product_type){
36
+ if ($(this).hasClass('show_if_simple') && is_simple) $(this).show(); else if ( ! is_simple ){
37
+ $(this).hide();
38
+ if ($(this).hasClass('show_if_variable') && is_variable) $(this).show(); else if ( ! is_variable ){
39
+ $(this).hide();
40
+ if ($(this).hasClass('show_if_grouped') && is_grouped) $(this).show(); else if ( ! is_grouped ) {
41
+ $(this).hide();
42
+ if ($(this).hasClass('show_if_external') && is_external) $(this).show(); else if ( ! is_external ) $(this).hide();
43
+ }
44
+ }
45
+ }
46
+ else if( !$(this).hasClass('show_if_simple') ){
47
+ if ($(this).hasClass('show_if_variable') && is_variable) $(this).show(); else if ( ! is_variable ){
48
+ $(this).hide();
49
+ if ($(this).hasClass('show_if_grouped') && is_grouped) $(this).show(); else if ( ! is_grouped ) {
50
+ $(this).hide();
51
+ if ($(this).hasClass('show_if_external') && is_external) $(this).show(); else if ( ! is_external ) $(this).hide();
52
+ }
53
+ }
54
+ else if ( !$(this).hasClass('show_if_variable') ){
55
+ if ($(this).hasClass('show_if_grouped') && is_grouped) $(this).show(); else if ( ! is_grouped ) {
56
+ $(this).hide();
57
+ if ($(this).hasClass('show_if_external') && is_external) $(this).show(); else if ( ! is_external ) $(this).hide();
58
+ }
59
+ else if ( !$(this).hasClass('show_if_grouped') ){
60
+ if ($(this).hasClass('show_if_external') && is_external) $(this).show(); else if ( ! is_external ) $(this).hide();
61
+ }
62
+ }
63
+ }
64
+ }
65
+
66
+ if ($(this).hasClass('hide_if_virtual') ||
67
+ $(this).hasClass('show_if_virtual') ||
68
+ $(this).hasClass('show_if_downloadable'))
69
+ {
70
+ if ($(this).hasClass('hide_if_virtual') && is_virtual) $(this).hide(); else if ( $(this).hasClass('hide_if_virtual') && !is_virtual ) $(this).show();
71
+ if ($(this).hasClass('show_if_virtual') && is_virtual) $(this).show(); else if ( $(this).hasClass('show_if_virtual') && !is_virtual ) $(this).hide();
72
+ if ($(this).hasClass('show_if_downloadable') && is_downloadable) $(this).show(); else if ( $(this).hasClass('show_if_downloadable') && !is_downloadable ) $(this).hide();
73
+ }
74
+ });
75
+
76
+ if ($('input[name=is_product_manage_stock]:checked').val() == 'no') $('.stock_fields').hide(); else $('.stock_fields').show();
77
+
78
+ if ($('#link_all_variations').is(':checked')) $('.variations_tab').hide(); else if (is_variable) $('.variations_tab').show();
79
+
80
+ if ( ! is_simple ) {
81
+ $('.woocommerce_options_panel').find('input, select').attr('disabled','disabled');
82
+ $('.upgrade_template').show();
83
+ }
84
+ else {
85
+ $('.woocommerce_options_panel').find('input, select').removeAttr('disabled');
86
+ $('.upgrade_template').hide();
87
+ }
88
+
89
+ if ($('#xml_matching_parent').is(':checked')) $('#variations_tag').show(); else $('#variations_tag').hide();
90
+ }
91
+
92
+ $('input[name=matching_parent]').click(function(){
93
+
94
+ if ($(this).val() == "xml") $('#variations_tag').show(); else $('#variations_tag').hide();
95
+
96
+ });
97
+
98
+ change_depencies();
99
+
100
+ $('#product-type').change(function(){
101
+ change_depencies();
102
+ $('.wc-tabs').find('li:visible:first').find('a').click();
103
+ });
104
+ $('#_virtual, #_downloadable, input[name=is_product_manage_stock]').click(change_depencies);
105
+ $('input[name=is_multiple_product_type]').click(function(){
106
+ change_depencies();
107
+ $('.wc-tabs').find('li:visible:first').find('a').click();
108
+ });
109
+ $('#link_all_variations').change(function(){
110
+ if ($(this).is(':checked'))
111
+ $('.variations_tab').hide();
112
+ else
113
+ $('.variations_tab').show();
114
+ });
115
+ $('#regular_price_shedule').click(function(){
116
+ $('#sale_price_range').show();
117
+ $('input[name=is_regular_price_shedule]').val('1');
118
+ $(this).hide();
119
+ });
120
+
121
+ $('#cancel_regular_price_shedule').click(function(){
122
+ $('#sale_price_range').hide();
123
+ $('input[name=is_regular_price_shedule]').val('0');
124
+ $('#regular_price_shedule').show();
125
+ });
126
+
127
+ $('#variable_sale_price_shedule').click(function(){
128
+ $('#variable_sale_price_range').show();
129
+ $('input[name=is_variable_sale_price_shedule]').val('1');
130
+ $(this).hide();
131
+ });
132
+
133
+ $('#cancel_variable_regular_price_shedule').click(function(){
134
+ $('#variable_sale_price_range').hide();
135
+ $('input[name=is_variable_sale_price_shedule]').val('0');
136
+ $('#variable_sale_price_shedule').show();
137
+ });
138
+
139
+ $('#_variable_virtual').click(function(){
140
+ if ($(this).is(':checked')){
141
+ $('#variable_virtual').show();
142
+ $('#variable_dimensions').hide();
143
+ }
144
+ else{
145
+ $('#variable_virtual').hide();
146
+ $('#variable_dimensions').show();
147
+ }
148
+ });
149
+
150
+ $('#_variable_downloadable').click(function(){
151
+ if ($(this).is(':checked')) $('#variable_downloadable').show(); else $('#variable_downloadable').hide();
152
+ });
153
+
154
+ $('.variation_attributes, #woocommerce_attributes').find('label').live({
155
+ mouseenter:
156
+ function()
157
+ {
158
+ if ( "" == $(this).attr('for')){
159
+ var counter = $('.variation_attributes').find('.form-field').length;
160
+ $(this).parents('span:first').find('input').attr('id', $(this).parents('span:first').find('input').attr('name') + '_' + counter);
161
+ $(this).attr('for', $(this).parents('span:first').find('input').attr('id'));
162
+ }
163
+ },
164
+ mouseleave:
165
+ function()
166
+ {
167
+
168
+ }
169
+ });
170
+
171
+ $('#variations_tag').insertAfter('.xpath_help');
172
+
173
+ });})(jQuery);
static/js/pmwi.js ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ /**
2
+ * plugin javascript
3
+ */
4
+ (function($){$(function () {
5
+
6
+
7
+ });})(jQuery);
views/admin/import/index.php ADDED
@@ -0,0 +1,1163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <tr>
2
+ <td colspan="3">
3
+ <div class="postbox " id="woocommerce-product-data">
4
+ <h3 class="hndle">
5
+ <span>
6
+ <div class="main_choise" style="padding:0px; margin-right:0px;">
7
+ <input type="radio" id="multiple_product_type_yes" class="switcher" name="is_multiple_product_type" value="yes" <?php echo 'no' != $post['is_multiple_product_type'] ? 'checked="checked"': '' ?>/>
8
+ <label for="multiple_product_type_yes"><?php _e('Product Type', 'pmxi_plugin' )?></label>
9
+ </div>
10
+ <div class="switcher-target-multiple_product_type_yes" style="float:left;">
11
+ <div class="input">
12
+ <select name="multiple_product_type" id="product-type" style="vertical-align:middle; height:23px; width:220px;">
13
+ <optgroup label="Product Type">
14
+ <option value="simple" <?php echo 'simple' == $post['multiple_product_type'] ? 'selected="selected"': '' ?>><?php _e('Simple product', 'woocommerce');?></option>
15
+ <option value="grouped" <?php echo 'grouped' == $post['multiple_product_type'] ? 'selected="selected"': '' ?>><?php _e('Grouped product','woocommerce');?></option>
16
+ <option value="external" <?php echo 'external' == $post['multiple_product_type'] ? 'selected="selected"': '' ?>><?php _e('External/Affiliate product','woocommerce');?></option>
17
+ <option value="variable" <?php echo 'variable' == $post['multiple_product_type'] ? 'selected="selected"': '' ?>><?php _e('Variable product','woocommerce');?></option>
18
+ </optgroup>
19
+ </select>
20
+ </div>
21
+ </div>
22
+ <div class="main_choise" style="padding:0px; margin-left:40px;">
23
+ <input type="radio" id="multiple_product_type_no" class="switcher" name="is_multiple_product_type" value="no" <?php echo 'no' == $post['is_multiple_product_type'] ? 'checked="checked"': '' ?> disabled="disabled"/>
24
+ <label for="multiple_product_type_no"><?php _e('Set Product Type With XPath', 'pmxi_plugin' )?></label>
25
+ </div>
26
+ <div class="switcher-target-multiple_product_type_no" style="float:left;">
27
+ <div class="input">
28
+ <input type="text" class="smaller-text" name="single_product_type" style="width:300px;" value="<?php echo esc_attr($post['single_product_type']) ?>"/>
29
+ <a href="#help" class="help" title="<?php _e('The value of presented XPath should be one of the following: (\'simple\', \'grouped\', \'external\', \'variable\').', 'pmxi_plugin') ?>">?</a>
30
+ </div>
31
+ </div>
32
+ <div style="float:right;">
33
+ <label class="show_if_simple" for="_virtual" style="border-right:none;"><?php _e('Virtual','woocommerce');?>: <input type="checkbox" id="_virtual" name="_virtual" <?php echo ($post['_virtual']) ? 'checked="checked"' : ''; ?>></label>
34
+ <label class="show_if_simple" for="_downloadable"><?php _e('Downloadable','woocommerce');?>: <input type="checkbox" id="_downloadable" name="_downloadable" <?php echo ($post['_downloadable']) ? 'checked="checked"' : ''; ?>></label>
35
+ </div>
36
+ </span>
37
+ </h3>
38
+ <div class="clear"></div>
39
+ <div class="inside">
40
+ <div class="panel-wrap product_data">
41
+
42
+ <div class="wc-tabs-back"></div>
43
+
44
+ <ul style="" class="product_data_tabs wc-tabs">
45
+
46
+ <li class="general_options hide_if_grouped active"><a href="javascript:void(0);" rel="general_product_data"><?php _e('General','woocommerce');?></a></li>
47
+
48
+ <li class="inventory_tab show_if_simple show_if_variable show_if_grouped inventory_options" style="display: block;"><a href="javascript:void(0);" rel="inventory_product_data"><?php _e('Inventory', 'woocommerce');?></a></li>
49
+
50
+ <li class="shipping_tab hide_if_virtual shipping_options hide_if_grouped hide_if_external"><a href="javascript:void(0);" rel="shipping_product_data"><?php _e('Shipping', 'woocommerce');?></a></li>
51
+
52
+ <li class="linked_product_tab linked_product_options"><a href="javascript:void(0);" rel="linked_product_data"><?php _e('Linked Products', 'woocommerce');?></a></li>
53
+
54
+ <li class="attributes_tab attribute_options"><a href="javascript:void(0);" rel="woocommerce_attributes"><?php _e('Attributes','woocommerce');?></a></li>
55
+
56
+ <li class="advanced_tab advanced_options"><a href="javascript:void(0);" rel="advanced_product_data"><?php _e('Advanced','woocommerce');?></a></li>
57
+
58
+ <li class="variations_tab show_if_variable variation_options"><a title="Variations for variable products are defined here." href="javascript:void(0);" rel="variable_product_options"><?php _e('Variations','woocommerce');?></a></li>
59
+
60
+ <li class="options_tab advanced_options"><a title="Variations for variable products are defined here." href="javascript:void(0);" rel="add_on_options"><?php _e('Add-On Options', 'pmxi_plugin');?></a></li>
61
+
62
+ </ul>
63
+
64
+ <div class="panel woocommerce_options_panel" id="general_product_data">
65
+
66
+ <p class="upgrade_template" style='display:none; font-size: 1.3em; font-weight: bold;'>
67
+ <a href="http://www.wpallimport.com/upgrade-to-pro?utm_source=wordpress.org&utm_medium=wooco&utm_campaign=free+plugin+wooco" target="_blank" class="upgrade_link">Upgrade to the pro version of the WooCommerce Add-On to import to grouped, affiliate/external, and variable products.</a>
68
+ </p>
69
+
70
+ <div class="options_group hide_if_grouped">
71
+ <p class="form-field">
72
+ <label><?php _e("SKU"); ?></label>
73
+ <input type="text" class="short" name="single_product_sku" style="" value="<?php echo esc_attr($post['single_product_sku']) ?>"/>
74
+ <a href="#help" class="help" title="<?php _e('SKU refers to a Stock-keeping unit, a unique identifier for each distinct product and service that can be purchased.', 'woocommerce') ?>">?</a>
75
+ </p>
76
+ </div>
77
+ <div class="options_group show_if_external">
78
+ <p class="form-field">
79
+ <label><?php _e("Product URL"); ?></label>
80
+ <input type="text" class="short" name="single_product_url" value="<?php echo esc_attr($post['single_product_url']) ?>"/>
81
+ <a href="#help" class="help" title="<?php _e('The external/affiliate link URL to the product.', 'pmxi_plugin') ?>">?</a>
82
+ </p>
83
+ <p class="form-field">
84
+ <label><?php _e("Button text"); ?></label>
85
+ <input type="text" class="short" name="single_product_button_text" value="<?php echo esc_attr($post['single_product_button_text']) ?>"/>
86
+ <a href="#help" class="help" title="<?php _e('This text will be shown on the button linking to the external product.', 'pmxi_plugin') ?>">?</a>
87
+ </p>
88
+ </div>
89
+ <div class="options_group pricing show_if_simple show_if_external show_if_variable">
90
+ <p class="form-field">
91
+ <label><?php _e("Regular Price (".get_woocommerce_currency_symbol().")"); ?></label>
92
+ <input type="text" class="short" name="single_product_regular_price" value="<?php echo esc_attr($post['single_product_regular_price']) ?>"/>
93
+ </p>
94
+ <p class="form-field">
95
+ <label><?php _e("Sale Price (".get_woocommerce_currency_symbol().")"); ?></label>
96
+ <input type="text" class="short" name="single_product_sale_price" value="<?php echo esc_attr($post['single_product_sale_price']) ?>"/>&nbsp;<a id="regular_price_shedule" href="javascript:void(0);" <?php if ($post['is_regular_price_shedule']):?>style="display:none;"<?php endif; ?>><?php _e('schedule');?></a>
97
+ <input type="hidden" name="is_regular_price_shedule" value="<?php echo esc_attr($post['is_regular_price_shedule']) ?>"/>
98
+ </p>
99
+ <p class="form-field" <?php if ( ! $post['is_regular_price_shedule']):?>style="display:none;"<?php endif; ?> id="sale_price_range">
100
+ <span style="vertical-align:middle">
101
+ <label><?php _e("Sale Price Dates"); ?></label>
102
+ <input type="text" class="datepicker" name="single_sale_price_dates_from" value="<?php echo esc_attr($post['single_sale_price_dates_from']) ?>" style="float:none;"/>
103
+ <?php _e('and', 'pmxi_plugin') ?>
104
+ <input type="text" class="datepicker" name="single_sale_price_dates_to" value="<?php echo esc_attr($post['single_sale_price_dates_to']) ?>" style="float:none;"/>
105
+ &nbsp;<a id="cancel_regular_price_shedule" href="javascript:void(0);"><?php _e('cancel');?></a>
106
+ </span>
107
+ </p>
108
+ </div>
109
+ <div class="options_group show_if_virtual">
110
+ <div class="input" style="padding-left:0px;">
111
+ <div class="input fleft">
112
+ <input type="radio" id="is_product_virtual_yes" class="switcher" name="is_product_virtual" value="yes" <?php echo 'yes' == $post['is_product_virtual'] ? 'checked="checked"': '' ?>/>
113
+ <label for="is_product_virtual_yes"><?php _e("Virtual"); ?></label>
114
+ </div>
115
+ <div class="input fleft">
116
+ <input type="radio" id="is_product_virtual_no" class="switcher" name="is_product_virtual" value="no" <?php echo 'no' == $post['is_product_virtual'] ? 'checked="checked"': '' ?>/>
117
+ <label for="is_product_virtual_no"><?php _e("Not Virtual"); ?></label>
118
+ </div>
119
+ <div class="input fleft" style="position:relative;width:220px;">
120
+ <input type="radio" id="is_product_virtual_xpath" class="switcher" name="is_product_virtual" value="xpath" <?php echo 'xpath' == $post['is_product_virtual'] ? 'checked="checked"': '' ?>/>
121
+ <label for="is_product_virtual_xpath"><?php _e('Set with XPath', 'pmxi_plugin' )?></label> <br>
122
+ <div class="switcher-target-is_product_virtual_xpath set_with_xpath">
123
+ <div class="input">
124
+ &nbsp;<input type="text" class="smaller-text" name="single_product_virtual" style="width:300px;" value="<?php echo esc_attr($post['single_product_virtual']) ?>"/>
125
+ <a href="#help" class="help" title="<?php _e('The value of presented XPath should be one of the following: (\'yes\', \'no\').', 'pmxi_plugin') ?>" style="position:relative; top:2px;">?</a>
126
+ </div>
127
+ </div>
128
+ </div>
129
+ </div>
130
+ </div>
131
+ <div class="options_group show_if_downloadable">
132
+ <div class="input" style="padding-left:0px;">
133
+ <div class="input fleft">
134
+ <input type="radio" id="is_product_downloadable_yes" class="switcher" name="is_product_downloadable" value="yes" <?php echo 'yes' == $post['is_product_downloadable'] ? 'checked="checked"': '' ?>/>
135
+ <label for="is_product_downloadable_yes"><?php _e("Downloadable"); ?></label>
136
+ </div>
137
+ <div class="input fleft">
138
+ <input type="radio" id="is_product_downloadable_no" class="switcher" name="is_product_downloadable" value="no" <?php echo 'no' == $post['is_product_downloadable'] ? 'checked="checked"': '' ?>/>
139
+ <label for="is_product_downloadable_no"><?php _e("Not Downloadable"); ?></label>
140
+ </div>
141
+ <div class="input fleft" style="position:relative; width:220px;">
142
+ <input type="radio" id="is_product_downloadable_xpath" class="switcher" name="is_product_downloadable" value="xpath" <?php echo 'xpath' == $post['is_product_downloadable'] ? 'checked="checked"': '' ?>/>
143
+ <label for="is_product_downloadable_xpath"><?php _e('Set with XPath', 'pmxi_plugin' )?></label> <br>
144
+ <div class="switcher-target-is_product_downloadable_xpath set_with_xpath">
145
+ <div class="input">
146
+ <input type="text" class="smaller-text" name="single_product_downloadable" style="width:300px;" value="<?php echo esc_attr($post['single_product_downloadable']) ?>"/>
147
+ <a href="#help" class="help" title="<?php _e('The value of presented XPath should be one of the following: (\'yes\', \'no\').', 'pmxi_plugin') ?>" style="position:relative; top:2px;">?</a>
148
+ </div>
149
+ </div>
150
+ </div>
151
+ </div>
152
+ <br>
153
+ <div class="clear"></div>
154
+ <p class="form-field">
155
+ <label><?php _e("File paths"); ?></label>
156
+ <input type="text" class="short" name="single_product_files" value="<?php echo esc_attr($post['single_product_files']) ?>" style="margin-right:5px;"/>
157
+ <input type="text" class="small" name="product_files_delim" value="<?php echo esc_attr($post['product_files_delim']) ?>" style="width:5%; text-align:center;"/>
158
+ <a href="#help" class="help" title="<?php _e('File paths/URLs, comma separated. The delimiter option uses when xml element contains few paths/URLs (http://files.com/1.doc, http://files.com/2.doc).', 'pmxi_plugin') ?>">?</a>
159
+ </p>
160
+ <p class="form-field">
161
+ <label><?php _e("Download Limit"); ?></label>
162
+ <input type="text" class="short" placeholder="Unimited" name="single_product_download_limit" value="<?php echo esc_attr($post['single_product_download_limit']) ?>"/>&nbsp;
163
+ <?php _e( 'Leave blank for unlimited re-downloads.', 'woocommerce' ) ?>
164
+ </p>
165
+ <p class="form-field">
166
+ <label><?php _e("Download Expiry"); ?></label>
167
+ <input type="text" class="short" placeholder="Never" name="single_product_download_expiry" value="<?php echo esc_attr($post['single_product_download_expiry']) ?>"/>&nbsp;
168
+ <?php _e( 'Enter the number of days before a download link expires, or leave blank.', 'woocommerce' ) ?>
169
+ </p>
170
+ </div>
171
+ <div class="options_group show_if_simple show_if_external show_if_variable">
172
+ <div class="input">
173
+ <div class="main_choise">
174
+ <input type="radio" id="multiple_product_tax_status_yes" class="switcher" name="is_multiple_product_tax_status" value="yes" <?php echo 'no' != $post['is_multiple_product_tax_status'] ? 'checked="checked"': '' ?>/>
175
+ <label for="multiple_product_tax_status_yes"><?php _e("Tax Status"); ?></label>
176
+ </div>
177
+ <div class="switcher-target-multiple_product_tax_status_yes" style="padding-left:17px;">
178
+ <div class="input">
179
+ <select class="select short" name="multiple_product_tax_status">
180
+ <option value="taxable" <?php echo 'taxable' == $post['multiple_product_tax_status'] ? 'selected="selected"': '' ?>><?php _e('Taxable', 'woocommerce');?></option>
181
+ <option value="shipping" <?php echo 'shipping' == $post['multiple_product_tax_status'] ? 'selected="selected"': '' ?>><?php _e('Shipping only', 'woocommerce');?></option>
182
+ <option value="none" <?php echo 'none' == $post['multiple_product_tax_status'] ? 'selected="selected"': '' ?>><?php _e('None', 'woocommerce');?></option>
183
+ </select>
184
+ </div>
185
+ </div>
186
+ </div>
187
+ <div class="input">
188
+ <div class="main_choise">
189
+ <input type="radio" id="multiple_product_tax_status_no" class="switcher" name="is_multiple_product_tax_status" value="no" <?php echo 'no' == $post['is_multiple_product_tax_status'] ? 'checked="checked"': '' ?>/>
190
+ <label for="multiple_product_tax_status_no"><?php _e('Set product tax status with XPath', 'pmxi_plugin' )?></label>
191
+ </div>
192
+ <div class="switcher-target-multiple_product_tax_status_no" style="padding-left:17px;">
193
+ <div class="input">
194
+ <input type="text" class="smaller-text" name="single_product_tax_status" style="width:300px;" value="<?php echo esc_attr($post['single_product_tax_status']) ?>"/>
195
+ <a href="#help" class="help" title="<?php _e('The value of presented XPath should be one of the following: (\'taxable\', \'shipping\', \'none\').', 'pmxi_plugin') ?>">?</a>
196
+ </div>
197
+ </div>
198
+ </div>
199
+ </div>
200
+ <div class="options_group show_if_simple show_if_external show_if_variable">
201
+ <div class="input">
202
+ <div class="main_choise">
203
+ <input type="radio" id="multiple_product_tax_class_yes" class="switcher" name="is_multiple_product_tax_class" value="yes" <?php echo 'no' != $post['is_multiple_product_tax_class'] ? 'checked="checked"': '' ?>/>
204
+ <label for="multiple_product_tax_class_yes"><?php _e("Tax Class"); ?></label>
205
+ </div>
206
+ <div class="switcher-target-multiple_product_tax_class_yes" style="padding-left:17px;">
207
+ <div class="input">
208
+ <select class="select short" name="multiple_product_tax_class">
209
+ <option value="" <?php echo '' == $post['multiple_product_tax_class'] ? 'selected="selected"': '' ?>><?php _e('Standard', 'woocommerce');?></option>
210
+ <option value="reduced-rate" <?php echo 'reduced-rate' == $post['multiple_product_tax_class'] ? 'selected="selected"': '' ?>><?php _e('Reduced Rate', 'woocommerce');?></option>
211
+ <option value="zero-rate" <?php echo 'zero-rate' == $post['multiple_product_tax_class'] ? 'selected="selected"': '' ?>><?php _e('Zero Rate', 'woocommerce');?></option>
212
+ </select>
213
+ </div>
214
+ </div>
215
+ </div>
216
+ <div class="input">
217
+ <div class="main_choise">
218
+ <input type="radio" id="multiple_product_tax_class_no" class="switcher" name="is_multiple_product_tax_class" value="no" <?php echo 'no' == $post['is_multiple_product_tax_class'] ? 'checked="checked"': '' ?>/>
219
+ <label for="multiple_product_tax_class_no"><?php _e('Set product tax class with XPath', 'pmxi_plugin' )?></label>
220
+ </div>
221
+ <div class="switcher-target-multiple_product_tax_class_no" style="padding-left:17px;">
222
+ <div class="input">
223
+ <input type="text" class="smaller-text" name="single_product_tax_class" style="width:300px;" value="<?php echo esc_attr($post['single_product_tax_class']) ?>"/>
224
+ <a href="#help" class="help" title="<?php _e('The value of presented XPath should be one of the following: (\'reduced-rate\', \'zero-rate\').', 'pmxi_plugin') ?>">?</a>
225
+ </div>
226
+ </div>
227
+ </div>
228
+ </div>
229
+ </div>
230
+
231
+ <!-- INVENTORY -->
232
+
233
+ <div class="panel woocommerce_options_panel" id="inventory_product_data" style="display:none;">
234
+ <p class="upgrade_template" style='display:none; font-size: 1.3em; font-weight: bold;'>
235
+ <a href="http://www.wpallimport.com/upgrade-to-pro?utm_source=wordpress.org&utm_medium=wooco&utm_campaign=free+plugin+wooco" target="_blank" class="upgrade_link">Upgrade to the pro version of the WooCommerce Add-On to import to grouped, affiliate/external, and variable products.</a>
236
+ </p>
237
+ <div class="options_group show_if_simple show_if_variable">
238
+ <p class="form-field">Manage stock?</p>
239
+ <div class="input" style="margin-top:-10px;">
240
+ <div class="input fleft">
241
+ <input type="radio" id="is_product_manage_stock_yes" class="switcher" name="is_product_manage_stock" value="yes" <?php echo 'yes' == $post['is_product_manage_stock'] ? 'checked="checked"': '' ?>/>
242
+ <label for="is_product_manage_stock_yes"><?php _e("Yes"); ?></label>
243
+ </div>
244
+ <div class="input fleft">
245
+ <input type="radio" id="is_product_manage_stock_no" class="switcher" name="is_product_manage_stock" value="no" <?php echo 'no' == $post['is_product_manage_stock'] ? 'checked="checked"': '' ?>/>
246
+ <label for="is_product_manage_stock_no"><?php _e("No"); ?></label>
247
+ </div>
248
+ <div class="input fleft" style="position:relative; width:220px;">
249
+ <input type="radio" id="is_product_manage_stock_xpath" class="switcher" name="is_product_manage_stock" value="xpath" <?php echo 'xpath' == $post['is_product_manage_stock'] ? 'checked="checked"': '' ?>/>
250
+ <label for="is_product_manage_stock_xpath"><?php _e('Set with XPath', 'pmxi_plugin' )?></label> <br>
251
+ <div class="switcher-target-is_product_manage_stock_xpath set_with_xpath">
252
+ <div class="input">
253
+ <input type="text" class="smaller-text" name="single_product_manage_stock" style="width:300px;" value="<?php echo esc_attr($post['single_product_manage_stock']) ?>"/>
254
+ <a href="#help" class="help" title="<?php _e('The value of presented XPath should be one of the following: (\'yes\', \'no\').', 'pmxi_plugin') ?>" style="position:relative; top:2px;">?</a>
255
+ </div>
256
+ </div>
257
+ </div>
258
+ </div>
259
+ </div>
260
+ <div class="options_group stock_fields show_if_simple show_if_variable" style="padding-bottom:0px;">
261
+ <p class="form-field">
262
+ <label><?php _e("Stock Qty"); ?></label>
263
+ <input type="text" class="short" name="single_product_stock_qty" value="<?php echo esc_attr($post['single_product_stock_qty']) ?>"/>
264
+ <a href="#help" class="help" title="<?php _e('Stock quantity. If this is a variable product this value will be used to control stock for all variations, unless you define stock at variation level.', 'woocommerce'); ?>">?</a>
265
+ </p>
266
+ </div>
267
+ <div class="options_group">
268
+ <p class="form-field"><?php _e('Stock status','pmxi_plugin');?></p>
269
+ <div class="input" style="margin-top:-10px;">
270
+ <div class="input fleft">
271
+ <input type="radio" id="product_stock_status_in_stock" class="switcher" name="product_stock_status" value="instock" <?php echo 'instock' == $post['product_stock_status'] ? 'checked="checked"': '' ?>/>
272
+ <label for="product_stock_status_in_stock"><?php _e("In stock"); ?></label>
273
+ </div>
274
+ <div class="input fleft">
275
+ <input type="radio" id="product_stock_status_out_of_stock" class="switcher" name="product_stock_status" value="outofstock" <?php echo 'outofstock' == $post['product_stock_status'] ? 'checked="checked"': '' ?>/>
276
+ <label for="product_stock_status_out_of_stock"><?php _e("Out of stock"); ?></label>
277
+ </div>
278
+ <div class="input fleft" style="position:relative; width:220px;">
279
+ <input type="radio" id="product_stock_status_xpath" class="switcher" name="product_stock_status" value="xpath" <?php echo 'xpath' == $post['product_stock_status'] ? 'checked="checked"': '' ?>/>
280
+ <label for="product_stock_status_xpath"><?php _e('Set with XPath', 'pmxi_plugin' )?></label><br>
281
+ <div class="switcher-target-product_stock_status_xpath set_with_xpath">
282
+ <div class="input">
283
+ <input type="text" class="smaller-text" name="single_product_stock_status" style="width:300px;" value="<?php echo esc_attr($post['single_product_stock_status']) ?>"/>
284
+ <a href="#help" class="help" title="<?php _e('The value of presented XPath should be one of the following: (\'instock\', \'outofstock\').', 'pmxi_plugin') ?>" style="position:relative; top:2px;">?</a>
285
+ </div>
286
+ </div>
287
+ </div>
288
+ </div>
289
+ </div>
290
+ <div class="options_group show_if_simple show_if_variable">
291
+ <p class="form-field"><?php _e('Allow Backorders?','pmxi_plugin');?><a href="#help" class="help" title="<?php _e('If managing stock, this controls whether or not backorders are allowed for this product and variations. If enabled, stock quantity can go below 0.', 'woocommerce'); ?>">?</a></p>
292
+ <div class="input" style="margin-top:-10px;">
293
+ <div class="input fleft">
294
+ <input type="radio" id="product_allow_backorders_no" class="switcher" name="product_allow_backorders" value="no" <?php echo 'no' == $post['product_allow_backorders'] ? 'checked="checked"': '' ?>/>
295
+ <label for="product_allow_backorders_no"><?php _e("Do not allow"); ?></label>
296
+ </div>
297
+ <div class="input fleft">
298
+ <input type="radio" id="product_allow_backorders_notify" class="switcher" name="product_allow_backorders" value="notify" <?php echo 'notify' == $post['product_allow_backorders'] ? 'checked="checked"': '' ?>/>
299
+ <label for="product_allow_backorders_notify"><?php _e("Allow, but notify customer"); ?></label>
300
+ </div>
301
+ <div class="input fleft">
302
+ <input type="radio" id="product_allow_backorders_yes" class="switcher" name="product_allow_backorders" value="yes" <?php echo 'yes' == $post['product_allow_backorders'] ? 'checked="checked"': '' ?>/>
303
+ <label for="product_allow_backorders_yes"><?php _e("Allow"); ?></label>
304
+ </div>
305
+ <div class="input fleft" style="position:relative; width:220px;">
306
+ <input type="radio" id="product_allow_backorders_xpath" class="switcher" name="product_allow_backorders" value="xpath" <?php echo 'xpath' == $post['product_allow_backorders'] ? 'checked="checked"': '' ?>/>
307
+ <label for="product_allow_backorders_xpath"><?php _e('Set with XPath', 'pmxi_plugin' )?></label><br>
308
+ <div class="switcher-target-product_allow_backorders_xpath set_with_xpath">
309
+ <div class="input">
310
+ <input type="text" class="smaller-text" name="single_product_allow_backorders" style="width:300px;" value="<?php echo esc_attr($post['single_product_allow_backorders']) ?>"/>
311
+ <a href="#help" class="help" title="<?php _e('The value of presented XPath should be one of the following: (\'no\', \'notify\', \'yes\').', 'pmxi_plugin') ?>" style="position:relative; top:2px;">?</a>
312
+ </div>
313
+ </div>
314
+ </div>
315
+ </div>
316
+ </div>
317
+ <div class="options_group show_if_simple show_if_variable">
318
+ <p class="form-field"><?php _e('Sold Individually?','pmxi_plugin');?></p>
319
+ <div class="input" style="margin-top:-10px;">
320
+ <div class="input fleft">
321
+ <input type="radio" id="product_sold_individually_yes" class="switcher" name="product_sold_individually" value="yes" <?php echo 'yes' == $post['product_sold_individually'] ? 'checked="checked"': '' ?>/>
322
+ <label for="product_sold_individually_yes"><?php _e("Yes"); ?></label>
323
+ </div>
324
+ <div class="input fleft">
325
+ <input type="radio" id="product_sold_individually_no" class="switcher" name="product_sold_individually" value="no" <?php echo 'no' == $post['product_sold_individually'] ? 'checked="checked"': '' ?>/>
326
+ <label for="product_sold_individually_no"><?php _e("No"); ?></label>
327
+ </div>
328
+ <div class="input fleft" style="position:relative; width:220px;">
329
+ <input type="radio" id="product_sold_individually_xpath" class="switcher" name="product_sold_individually" value="xpath" <?php echo 'xpath' == $post['product_sold_individually'] ? 'checked="checked"': '' ?>/>
330
+ <label for="product_sold_individually_xpath"><?php _e('Set with XPath', 'pmxi_plugin' )?></label><br>
331
+ <div class="switcher-target-product_sold_individually_xpath set_with_xpath">
332
+ <div class="input">
333
+ <input type="text" class="smaller-text" name="single_product_sold_individually" style="width:300px;" value="<?php echo esc_attr($post['single_product_sold_individually']) ?>"/>
334
+ <a href="#help" class="help" title="<?php _e('The value of presented XPath should be one of the following: (\'yes\', \'no\').', 'pmxi_plugin') ?>" style="position:relative; top:2px;">?</a>
335
+ </div>
336
+ </div>
337
+ </div>
338
+ </div>
339
+ </div>
340
+ </div>
341
+
342
+ <!-- SHIPPING -->
343
+
344
+ <div class="panel woocommerce_options_panel" id="shipping_product_data" style="display:none;">
345
+ <p class="upgrade_template" style='display:none; font-size: 1.3em; font-weight: bold;'>
346
+ <a href="http://www.wpallimport.com/upgrade-to-pro?utm_source=wordpress.org&utm_medium=wooco&utm_campaign=free+plugin+wooco" target="_blank" class="upgrade_link">Upgrade to the pro version of the WooCommerce Add-On to import to grouped, affiliate/external, and variable products.</a>
347
+ </p>
348
+ <div class="options_group">
349
+ <p class="form-field">
350
+ <label><?php _e("Weight (kg)"); ?></label>
351
+ <input type="text" class="short" placeholder="0.00" name="single_product_weight" style="" value="<?php echo esc_attr($post['single_product_weight']) ?>"/>
352
+ </p>
353
+ <p class="form-field">
354
+ <label><?php _e("Dimensions (cm)"); ?></label>
355
+ <input type="text" class="short" placeholder="Length" name="single_product_length" style="margin-right:5px;" value="<?php echo esc_attr($post['single_product_length']) ?>"/>
356
+ <input type="text" class="short" placeholder="Width" name="single_product_width" style="margin-right:5px;" value="<?php echo esc_attr($post['single_product_width']) ?>"/>
357
+ <input type="text" class="short" placeholder="Height" name="single_product_height" style="" value="<?php echo esc_attr($post['single_product_height']) ?>"/>
358
+ </p>
359
+ </div> <!-- End options group -->
360
+
361
+ <div class="options_group">
362
+ <div class="input">
363
+ <div class="main_choise">
364
+ <input type="radio" id="multiple_product_shipping_class_yes" class="switcher" name="is_multiple_product_shipping_class" value="yes" <?php echo 'no' != $post['is_multiple_product_shipping_class'] ? 'checked="checked"': '' ?>/>
365
+ <label for="multiple_product_shipping_class_yes"><?php _e("Shipping Class"); ?></label>
366
+ </div>
367
+ <div class="switcher-target-multiple_product_shipping_class_yes" style="padding-left:17px;">
368
+ <div class="input">
369
+ <?php
370
+ $classes = get_the_terms( 0, 'product_shipping_class' );
371
+ if ( $classes && ! is_wp_error( $classes ) ) $current_shipping_class = current($classes)->term_id; else $current_shipping_class = '';
372
+
373
+ $args = array(
374
+ 'taxonomy' => 'product_shipping_class',
375
+ 'hide_empty' => 0,
376
+ 'show_option_none' => __( 'No shipping class', 'woocommerce' ),
377
+ 'name' => 'multiple_product_shipping_class',
378
+ 'id' => 'multiple_product_shipping_class',
379
+ 'selected' => $current_shipping_class,
380
+ 'class' => 'select short'
381
+ );
382
+
383
+ wp_dropdown_categories( $args );
384
+ ?>
385
+ </div>
386
+ </div>
387
+ </div>
388
+ <div class="input">
389
+ <div class="main_choise">
390
+ <input type="radio" id="multiple_product_shipping_class_no" class="switcher" name="is_multiple_product_shipping_class" value="no" <?php echo 'no' == $post['is_multiple_product_shipping_class'] ? 'checked="checked"': '' ?>/>
391
+ <label for="multiple_product_shipping_class_no"><?php _e('Set product shipping class with XPath', 'pmxi_plugin' )?></label>
392
+ </div>
393
+ <div class="switcher-target-multiple_product_shipping_class_no" style="padding-left:17px;">
394
+ <div class="input">
395
+ <input type="text" class="smaller-text" name="single_product_shipping_class" style="width:300px;" value="<?php echo esc_attr($post['single_product_shipping_class']) ?>"/>
396
+ <a href="#help" class="help" title="<?php _e('The value of presented XPath should be one of the following: (\'taxable\', \'shipping\', \'none\').', 'pmxi_plugin') ?>">?</a>
397
+ </div>
398
+ </div>
399
+ </div>
400
+ </div> <!-- End options group -->
401
+ </div> <!-- End Product Panel -->
402
+
403
+ <!-- LINKED PRODUCT -->
404
+
405
+ <div class="panel woocommerce_options_panel" id="linked_product_data" style="display:none;">
406
+ <p class="upgrade_template" style='display:none; font-size: 1.3em; font-weight: bold;'>
407
+ <a href="http://www.wpallimport.com/upgrade-to-pro?utm_source=wordpress.org&utm_medium=wooco&utm_campaign=free+plugin+wooco" target="_blank" class="upgrade_link">Upgrade to the pro version of the WooCommerce Add-On to import to grouped, affiliate/external, and variable products.</a>
408
+ </p>
409
+ <div class="options_group">
410
+ <p class="form-field">
411
+ <label><?php _e("Up-Sells"); ?></label>
412
+ <input type="text" class="" placeholder="Products SKU, comma separated" name="single_product_up_sells" style="" value="<?php echo esc_attr($post['single_product_up_sells']) ?>"/>
413
+ <a href="#help" class="help" title="<?php _e('Up-sells are products which you recommend instead of the currently viewed product, for example, products that are more profitable or better quality or more expensive.', 'woocommerce') ?>">?</a>
414
+ </p>
415
+ <p class="form-field">
416
+ <label><?php _e("Cross-Sells"); ?></label>
417
+ <input type="text" class="" placeholder="Products SKU, comma separated" name="single_product_cross_sells" value="<?php echo esc_attr($post['single_product_cross_sells']) ?>"/>
418
+ <a href="#help" class="help" title="<?php _e('Cross-sells are products which you promote in the cart, based on the current product.', 'woocommerce') ?>">?</a>
419
+ </p>
420
+ </div> <!-- End options group -->
421
+ <div class="options_group grouping show_if_simple show_if_external">
422
+ <?php
423
+ $post_parents = array();
424
+ $post_parents[''] = __( 'Choose a grouped product&hellip;', 'woocommerce' );
425
+
426
+ $posts_in = array_unique( (array) get_objects_in_term( get_term_by( 'slug', 'grouped', 'product_type' )->term_id, 'product_type' ) );
427
+ if ( sizeof( $posts_in ) > 0 ) {
428
+ $args = array(
429
+ 'post_type' => 'product',
430
+ 'post_status' => 'any',
431
+ 'numberposts' => -1,
432
+ 'orderby' => 'title',
433
+ 'order' => 'asc',
434
+ 'post_parent' => 0,
435
+ 'include' => $posts_in,
436
+ );
437
+ $grouped_products = get_posts( $args );
438
+
439
+ if ( $grouped_products ) {
440
+ foreach ( $grouped_products as $product ) {
441
+
442
+ if ( $product->ID == $post->ID )
443
+ continue;
444
+
445
+ $post_parents[ $product->ID ] = $product->post_title;
446
+ }
447
+ }
448
+ }
449
+ ?>
450
+ <p class="form-field">
451
+ <label><?php _e("Grouping", "woocommerce"); ?></label>
452
+ <select name="grouping_product">
453
+ <?php
454
+ foreach ($post_parents as $parent_id => $parent_title) {
455
+ ?>
456
+ <option value="<?php echo $parent_id; ?>" <?php if ($parent_id == $post['grouping_product']):?>selected="selected"<?php endif;?>><?php echo $parent_title;?></option>
457
+ <?php
458
+ }
459
+ ?>
460
+ </select>
461
+ <a href="#help" class="help" title="<?php _e('Set this option to make this product part of a grouped product.', 'woocommerce'); ?>">?</a>
462
+ </p>
463
+ </div>
464
+ </div><!-- End Product Panel -->
465
+
466
+ <!-- ATTRIBUTES -->
467
+
468
+ <div class="panel woocommerce_options_panel" id="woocommerce_attributes" style="display:none;">
469
+ <p class="upgrade_template" style='display:none; font-size: 1.3em; font-weight: bold;'>
470
+ <a href="http://www.wpallimport.com/upgrade-to-pro?utm_source=wordpress.org&utm_medium=wooco&utm_campaign=free+plugin+wooco" target="_blank" class="upgrade_link">Upgrade to the pro version of the WooCommerce Add-On to import to grouped, affiliate/external, and variable products.</a>
471
+ </p>
472
+ <div class="input">
473
+ <table class="form-table custom-params" id="attributes_table" style="max-width:95%;">
474
+ <thead>
475
+ <tr>
476
+ <td><?php _e('Name', 'pmxi_plugin') ?></td>
477
+ <td><?php _e('Values', 'pmxi_plugin') ?></td>
478
+ <td></td>
479
+ </tr>
480
+ </thead>
481
+ <tbody>
482
+ <?php if (!empty($post['attribute_name'][0])):?>
483
+ <?php foreach ($post['attribute_name'] as $i => $name): if ("" == $name) continue; ?>
484
+ <tr class="form-field">
485
+ <td><input type="text" name="attribute_name[]" value="<?php echo esc_attr($name) ?>" style="width:100%;"/></td>
486
+ <td>
487
+ <textarea name="attribute_value[]"><?php echo esc_html($post['attribute_value'][$i]) ?></textarea>
488
+ <br>
489
+ <span class='in_variations'>
490
+ <input type="checkbox" name="in_variations[]" id="in_variations_<?php echo $i; ?>" <?php echo ($post['in_variations'][$i]) ? 'checked="checked"' : ''; ?> style="width: auto; position: relative; top: 1px; left: 0px;" value="1"/>
491
+ <label for="in_variations_<?php echo $i; ?>"><?php _e('In Variations','pmxi_plugin');?></label>
492
+ </span>
493
+
494
+ <span class='is_visible'>
495
+ <input type="checkbox" name="is_visible[]" id="is_visible_<?php echo $i; ?>" <?php echo ($post['is_visible'][$i]) ? 'checked="checked"' : ''; ?> style="width: auto; position: relative; top: 1px; left: 0px;" value="1"/>
496
+ <label for="is_visible_<?php echo $i; ?>"><?php _e('Is Visible','pmxi_plugin');?></label>
497
+ </span>
498
+
499
+ <span class='is_taxonomy'>
500
+ <input type="checkbox" name="is_taxonomy[]" id="is_taxonomy_<?php echo $i; ?>" <?php echo ($post['is_taxonomy'][$i]) ? 'checked="checked"' : ''; ?> style="width: auto; position: relative; top: 1px; left: 0px;" value="1"/>
501
+ <label for="is_taxonomy_<?php echo $i; ?>"><?php _e('Taxonomy','pmxi_plugin');?></label>
502
+ </span>
503
+
504
+ <span class='is_create_taxonomy'>
505
+ <input type="checkbox" name="create_taxonomy_in_not_exists[]" id="create_taxonomy_in_not_exists_<?php echo $i; ?>" <?php echo ($post['create_taxonomy_in_not_exists'][$i]) ? 'checked="checked"' : ''; ?> style="width: auto; position: relative; top: 1px; left: 0px;" value="1"/>
506
+ <label for="create_taxonomy_in_not_exists_<?php echo $i; ?>"><?php _e('Auto-Create Terms','pmxi_plugin');?></label>
507
+ </span>
508
+ </td>
509
+ <td class="action remove"><a href="#remove"></a></td>
510
+ </tr>
511
+ <?php endforeach ?>
512
+ <?php else: ?>
513
+ <tr class="form-field">
514
+ <td><input type="text" name="attribute_name[]" value="" style="width:100%;"/></td>
515
+ <td>
516
+ <textarea name="attribute_value[]"></textarea>
517
+ <br>
518
+ <span class='in_variations'>
519
+ <input type="checkbox" name="in_variations[]" id="in_variations_0" checked="checked" style="width: auto; position: relative; top: 1px; left: 0px;" value="1"/>
520
+ <label for="in_variations_0"><?php _e('In Variations','pmxi_plugin');?></label>
521
+ </span>
522
+ <span class='is_visible'>
523
+ <input type="checkbox" name="is_visible[]" id="is_visible_0" checked="checked" style="width: auto; position: relative; top: 1px; left: 0px;" value="1"/>
524
+ <label for="is_visible_0"><?php _e('Is Visible','pmxi_plugin');?></label>
525
+ </span>
526
+ <span class='is_taxonomy'>
527
+ <input type="checkbox" name="is_taxonomy[]" id="is_taxonomy_0" checked="checked" style="width: auto; position: relative; top: 1px; left: 0px;" value="1"/>
528
+ <label for="is_taxonomy_0"><?php _e('Taxonomy','pmxi_plugin');?></label>
529
+ </span>
530
+ <span class='is_create_taxonomy'>
531
+ <input type="checkbox" name="create_taxonomy_in_not_exists[]" id="create_taxonomy_in_not_exists_0" checked="checked" style="width: auto; position: relative; top: 1px; left: 0px;" value="1"/>
532
+ <label for="create_taxonomy_in_not_exists_0"><?php _e('Auto-Create Terms','pmxi_plugin');?></label>
533
+ </span>
534
+ <td class="action remove"><a href="#remove"></a></td>
535
+ </tr>
536
+ <?php endif;?>
537
+ <tr class="form-field template">
538
+ <td><input type="text" name="attribute_name[]" value="" style="width:100%;"/></td>
539
+ <td>
540
+ <textarea name="attribute_value[]"></textarea>
541
+ <br>
542
+ <span class='in_variations'>
543
+ <input type="checkbox" name="in_variations[]" checked="checked" style="width: auto; position: relative; top: 1px; left: 0px;" value="1"/>
544
+ <label for=""><?php _e('In Variations','pmxi_plugin');?></label>
545
+ </span>
546
+ <span class='is_visible'>
547
+ <input type="checkbox" name="is_visible[]" checked="checked" style="width: auto; position: relative; top: 1px; left: 0px;" value="1"/>
548
+ <label for=""><?php _e('Is Visible','pmxi_plugin');?></label>
549
+ </span>
550
+ <span class='is_taxonomy'>
551
+ <input type="checkbox" name="is_taxonomy[]" checked="checked" style="width: auto; position: relative; top: 1px; left: 0px;" value="1"/>
552
+ <label for=""><?php _e('Taxonomy','pmxi_plugin');?></label>
553
+ </span>
554
+ <span class='is_create_taxonomy'>
555
+ <input type="checkbox" name="create_taxonomy_in_not_exists[]" checked="checked" style="width: auto; position: relative; top: 1px; left: 0px;" value="1"/>
556
+ <label for=""><?php _e('Auto-Create Terms','pmxi_plugin');?></label>
557
+ </span>
558
+ <td class="action remove"><a href="#remove"></a></td>
559
+ </tr>
560
+ <tr>
561
+ <td colspan="3"><a href="#add" title="<?php _e('add', 'pmxi_plugin')?>" class="action add-new-custom"><?php _e('Add more', 'pmxi_plugin') ?></a></td>
562
+ </tr>
563
+ </tbody>
564
+ </table>
565
+ </div>
566
+ <div class="options_group show_if_variable">
567
+ <div class="input" style="padding-left:5px; marign-top:10px;">
568
+ <input type="hidden" name="link_all_variations" value="0" />
569
+ <input type="checkbox" id="link_all_variations" name="link_all_variations" value="1" <?php echo $post['link_all_variations'] ? 'checked="checked"' : '' ?> style="width:25px; position:relative; top:-1px;"/>
570
+ <label for="link_all_variations"><?php _e('Link all variations', 'pmxi_plugin') ?></label>
571
+ <a href="#help" class="help" title="<?php _e('This option will create all possibility variations with presented attributes.', 'pmxi_plugin') ?>" style="position:relative; top:-3px;">?</a>
572
+ </div>
573
+ </div>
574
+ </div><!-- End Product Panel -->
575
+
576
+ <!-- ADVANCED -->
577
+
578
+ <div class="panel woocommerce_options_panel" id="advanced_product_data" style="display:none;">
579
+ <p class="upgrade_template" style='display:none; font-size: 1.3em; font-weight: bold;'>
580
+ <a href="http://www.wpallimport.com/upgrade-to-pro?utm_source=wordpress.org&utm_medium=wooco&utm_campaign=free+plugin+wooco" target="_blank" class="upgrade_link">Upgrade to the pro version of the WooCommerce Add-On to import to grouped, affiliate/external, and variable products.</a>
581
+ </p>
582
+ <div class="options_group hide_if_external" style="padding-bottom:0px;">
583
+ <p class="form-field">
584
+ <label><?php _e("Purchase Note"); ?></label>
585
+ <input type="text" class="short" placeholder="" name="single_product_purchase_note" style="" value="<?php echo esc_attr($post['single_product_purchase_note']) ?>"/>
586
+ </p>
587
+ </div>
588
+ <div class="options_group" style="padding-bottom:0px;">
589
+ <p class="form-field">
590
+ <label><?php _e("Menu order"); ?></label>
591
+ <input type="text" class="short" placeholder="" name="single_product_menu_order" value="<?php echo esc_attr($post['single_product_menu_order']) ?>"/>
592
+ </p>
593
+ </div>
594
+ <div class="options_group reviews">
595
+ <p class="form-field"><?php _e('Enable reviews','pmxi_plugin');?></p>
596
+ <div class="input" style="margin-top:-10px;">
597
+ <div class="input fleft">
598
+ <input type="radio" id="product_enable_reviews_yes" class="switcher" name="is_product_enable_reviews" value="yes" <?php echo 'yes' == $post['is_product_enable_reviews'] ? 'checked="checked"': '' ?>/>
599
+ <label for="product_enable_reviews_yes"><?php _e("Yes"); ?></label>
600
+ </div>
601
+ <div class="input fleft">
602
+ <input type="radio" id="product_enable_reviews_no" class="switcher" name="is_product_enable_reviews" value="no" <?php echo 'no' == $post['is_product_enable_reviews'] ? 'checked="checked"': '' ?>/>
603
+ <label for="product_enable_reviews_no"><?php _e("No"); ?></label>
604
+ </div>
605
+ <div class="input fleft" style="position:relative; width:220px;">
606
+ <input type="radio" id="product_enable_reviews_xpath" class="switcher" name="is_product_enable_reviews" value="xpath" <?php echo 'xpath' == $post['is_product_enable_reviews'] ? 'checked="checked"': '' ?>/>
607
+ <label for="product_enable_reviews_xpath"><?php _e('Set with XPath', 'pmxi_plugin' )?></label><br>
608
+ <div class="switcher-target-product_enable_reviews_xpath set_with_xpath">
609
+ <div class="input">
610
+ <input type="text" class="smaller-text" name="single_product_enable_reviews" style="width:300px;" value="<?php echo esc_attr($post['single_product_enable_reviews']) ?>"/>
611
+ <a href="#help" class="help" title="<?php _e('The value of presented XPath should be one of the following: (\'yes\', \'no\').', 'pmxi_plugin') ?>" style="position:relative; top:2px;">?</a>
612
+ </div>
613
+ </div>
614
+ </div>
615
+ </div>
616
+ </div> <!-- End options group -->
617
+ <div class="options_group">
618
+ <p class="form-field"><?php _e('Featured','pmxi_plugin');?></p>
619
+ <div class="input" style="margin-top:-10px;">
620
+ <div class="input fleft">
621
+ <input type="radio" id="product_featured_yes" class="switcher" name="is_product_featured" value="yes" <?php echo 'yes' == $post['is_product_featured'] ? 'checked="checked"': '' ?>/>
622
+ <label for="product_featured_yes"><?php _e("Yes"); ?></label>
623
+ </div>
624
+ <div class="input fleft">
625
+ <input type="radio" id="product_featured_no" class="switcher" name="is_product_featured" value="no" <?php echo 'no' == $post['is_product_featured'] ? 'checked="checked"': '' ?>/>
626
+ <label for="product_featured_no"><?php _e("No"); ?></label>
627
+ </div>
628
+ <div class="input fleft" style="position:relative; width:220px;">
629
+ <input type="radio" id="product_featured_xpath" class="switcher" name="is_product_featured" value="xpath" <?php echo 'xpath' == $post['is_product_featured'] ? 'checked="checked"': '' ?>/>
630
+ <label for="product_featured_xpath"><?php _e('Set with XPath', 'pmxi_plugin' )?></label><br>
631
+ <div class="switcher-target-product_featured_xpath set_with_xpath">
632
+ <div class="input">
633
+ <input type="text" class="smaller-text" name="single_product_featured" style="width:300px;" value="<?php echo esc_attr($post['single_product_featured']) ?>"/>
634
+ <a href="#help" class="help" title="<?php _e('The value of presented XPath should be one of the following: (\'yes\', \'no\').', 'pmxi_plugin') ?>" style="position:relative; top:2px;">?</a>
635
+ </div>
636
+ </div>
637
+ </div>
638
+ </div>
639
+ </div> <!-- End options group -->
640
+ <div class="options_group">
641
+ <p class="form-field"><?php _e('Catalog visibility','pmxi_plugin');?></p>
642
+ <div class="input" style="margin-top:-10px;">
643
+ <div class="input fleft">
644
+ <input type="radio" id="product_visibility_visible" class="switcher" name="is_product_visibility" value="visible" <?php echo 'visible' == $post['is_product_visibility'] ? 'checked="checked"': '' ?>/>
645
+ <label for="product_visibility_visible"><?php _e("Catalog/search"); ?></label>
646
+ </div>
647
+ <div class="input fleft">
648
+ <input type="radio" id="product_visibility_catalog" class="switcher" name="is_product_visibility" value="catalog" <?php echo 'catalog' == $post['is_product_visibility'] ? 'checked="checked"': '' ?>/>
649
+ <label for="product_visibility_catalog"><?php _e("Catalog"); ?></label>
650
+ </div>
651
+ <div class="input fleft">
652
+ <input type="radio" id="product_visibility_search" class="switcher" name="is_product_visibility" value="search" <?php echo 'search' == $post['is_product_visibility'] ? 'checked="checked"': '' ?>/>
653
+ <label for="product_visibility_search"><?php _e("Search"); ?></label>
654
+ </div>
655
+ <div class="input fleft">
656
+ <input type="radio" id="product_visibility_hidden" class="switcher" name="product_visibility" value="hidden" <?php echo 'hidden' == $post['is_product_visibility'] ? 'checked="checked"': '' ?>/>
657
+ <label for="product_visibility_hidden"><?php _e("Hidden"); ?></label>
658
+ </div>
659
+ <div class="input fleft" style="position:relative; width:220px;">
660
+ <input type="radio" id="product_visibility_xpath" class="switcher" name="is_product_visibility" value="xpath" <?php echo 'xpath' == $post['is_product_visibility'] ? 'checked="checked"': '' ?>/>
661
+ <label for="product_visibility_xpath"><?php _e('Set with XPath', 'pmxi_plugin' )?></label><br>
662
+ <div class="switcher-target-product_visibility_xpath set_with_xpath">
663
+ <div class="input">
664
+ <input type="text" class="smaller-text" name="single_product_visibility" style="width:300px;" value="<?php echo esc_attr($post['single_product_visibility']) ?>"/>
665
+ <a href="#help" class="help" title="<?php _e('The value of presented XPath should be one of the following: (\'visible\', \'catalog\', \'search\', \'hidden\').', 'pmxi_plugin') ?>" style="position:relative; top:2px;">?</a>
666
+ </div>
667
+ </div>
668
+ </div>
669
+ </div>
670
+ </div> <!-- End options group -->
671
+ </div><!-- End Product Panel -->
672
+
673
+ <!-- VARIATIONS -->
674
+
675
+ <div class="panel woocommerce_options_panel" id="variable_product_options" style="display:none;">
676
+ <p class="upgrade_template" style='display:none; font-size: 1.3em; font-weight: bold;'>
677
+ <a href="http://www.wpallimport.com/upgrade-to-pro?utm_source=wordpress.org&utm_medium=wooco&utm_campaign=free+plugin+wooco" target="_blank" class="upgrade_link">Upgrade to the pro version of the WooCommerce Add-On to import to grouped, affiliate/external, and variable products.</a>
678
+ </p>
679
+ <div class="options_group" style="padding-bottom:0px;">
680
+ <div class="input" style="padding-bottom:10px;">
681
+ <input type="radio" id="auto_matching_parent" class="switcher" name="matching_parent" value="auto" <?php echo 'manual' != $post['matching_parent'] ? 'checked="checked"': '' ?>/>
682
+ <label for="auto_matching_parent"><?php _e('Automatic Parent Product Matching', 'pmxi_plugin' )?></label><br>
683
+ <div class="switcher-target-auto_matching_parent" style="padding-left:17px;">
684
+ <p class="form-field">
685
+ <label style="width:150px;"><?php _e("Product ID"); ?></label>
686
+ <input type="text" class="short" placeholder="" name="single_product_id" value="<?php echo esc_attr($post['single_product_id']) ?>"/>
687
+ </p>
688
+ <p class="form-field">
689
+ <label style="width:150px;"><?php _e("Parent Product ID"); ?></label>
690
+ <input type="text" class="short" placeholder="" name="single_product_parent_id" value="<?php echo esc_attr($post['single_product_parent_id']) ?>"/>
691
+ </p>
692
+ </div>
693
+ <div class="clear" style="margin-top:5px;"></div>
694
+
695
+ <input type="radio" id="manual_matching_parent" class="switcher" name="matching_parent" value="manual" <?php echo 'manual' == $post['matching_parent'] ? 'checked="checked"': '' ?>/>
696
+ <label for="manual_matching_parent"><?php _e('Manual Parent Product Matching', 'pmxi_plugin' )?></label>
697
+ <a href="#help" class="help" title="<?php _e('This allows you to match products as you would in the Manual Record Matching section of WP All Import.', 'pmxi_plugin') ?>" style="position:relative; top:-2px;">?</a>
698
+ <div class="switcher-target-manual_matching_parent" style="padding-left:17px;">
699
+ <div class="input">
700
+ <input type="radio" id="duplicate_indicator_title_parent" class="switcher" name="parent_indicator" value="title" <?php echo 'title' == $post['parent_indicator'] ? 'checked="checked"': '' ?>/>
701
+ <label for="duplicate_indicator_title_parent"><?php _e('title', 'pmxi_plugin' )?>&nbsp;</label>
702
+ <input type="radio" id="duplicate_indicator_content_parent" class="switcher" name="parent_indicator" value="content" <?php echo 'content' == $post['parent_indicator'] ? 'checked="checked"': '' ?>/>
703
+ <label for="duplicate_indicator_content_parent"><?php _e('content', 'pmxi_plugin' )?>&nbsp;</label>
704
+ <input type="radio" id="duplicate_indicator_custom_field_parent" class="switcher" name="parent_indicator" value="custom field" <?php echo 'custom field' == $post['parent_indicator'] ? 'checked="checked"': '' ?>/>
705
+ <label for="duplicate_indicator_custom_field_parent"><?php _e('custom field', 'pmxi_plugin' )?></label><br>
706
+ <span class="switcher-target-duplicate_indicator_custom_field_parent" style="vertical-align:middle" style="padding-left:17px;">
707
+ <?php _e('Name', 'pmxi_plugin') ?>
708
+ <input type="text" name="custom_parent_indicator_name" value="<?php echo esc_attr($post['custom_parent_indicator_name']) ?>" style="float:none; margin:1px;" /><br>
709
+ <?php _e('Value', 'pmxi_plugin') ?>
710
+ <input type="text" name="custom_parent_indicator_value" value="<?php echo esc_attr($post['custom_parent_indicator_value']) ?>" style="float:none; margin:1px;" />
711
+ </span>
712
+ </div>
713
+ </div>
714
+ <div class="clear" style="margin-top:5px;"></div>
715
+
716
+ <input type="radio" id="xml_matching_parent" class="switcher" name="matching_parent" value="xml" <?php echo 'xml' == $post['matching_parent'] ? 'checked="checked"': '' ?>/>
717
+ <label for="xml_matching_parent"><?php _e('Variation is a child element', 'pmxi_plugin' )?></label>
718
+ <a href="#help" class="help" title="<?php _e('This allows you to set variations that are stored as children XML elements.', 'pmxi_plugin') ?>" style="position:relative; top:-2px;">?</a>
719
+ <div class="switcher-target-xml_matching_parent" style="padding-left:17px;">
720
+ <div class="input">
721
+ <p class="form-field">
722
+ <label style="width:150px;"><?php _e("Variations XPath", "pmxi_plugin"); ?></label>
723
+ <input type="text" class="short" placeholder="" id="variations_xpath" name="variations_xpath" value="<?php echo esc_attr($post['variations_xpath']) ?>" style="width:370px !important;"/>
724
+ </p>
725
+ <p class="form-field">
726
+ <label style="border-right:none;" for="_variable_virtual"><?php _e('Virtual', 'woocommerce');?> </label>
727
+ <input type="checkbox" name="_variable_virtual" id="_variable_virtual" style="position:relative; top:2px; margin-left:5px;" <?php echo ($post['_variable_virtual']) ? 'checked="checked"' : ''; ?>>
728
+ <label for="_variable_downloadable" class="show_if_simple"><?php _e('Downloadable','woocommerce');?></label>
729
+ <input type="checkbox" name="_variable_downloadable" id="_variable_downloadable" style="position:relative; top:2px; margin-left:5px;" <?php echo ($post['_variable_downloadable']) ? 'checked="checked"' : ''; ?>>
730
+ </p>
731
+ <div style="margin-right:2%;">
732
+
733
+ <div class="options_group">
734
+ <p class="form-field">
735
+ <label style="width:150px;"><?php _e('SKU','woocommerce');?></label>
736
+ <input type="text" value="<?php echo esc_attr($post['variable_sku']) ?>" style="" name="variable_sku" class="short">
737
+ </p>
738
+ <p class="form-field">
739
+ <label style="width:150px;"><?php _e('Stock Qty', 'woocommerce');?></label>
740
+ <input type="text" value="<?php echo esc_attr($post['variable_stock']) ?>" style="" name="variable_stock" class="short">
741
+ <a href="#help" class="help" title="<?php _e('Enter a quantity to enable stock management at variation level, oe leave blank to use parent product\'s options', 'pmxi_plugin') ?>" style="position:relative; top:0px;">?</a>
742
+ <span class="use_parent">
743
+ <input type="hidden" name="variable_stock_use_parent" value="0"/>
744
+ <input type="checkbox" name="variable_stock_use_parent" id="variable_stock_use_parent" style="position:relative; top:6px; margin-left:5px;" <?php echo ($post['variable_stock_use_parent']) ? 'checked="checked"' : ''; ?>>
745
+ <label for="variable_stock_use_parent" style="top:2px;">XPath Is From Parent</label>
746
+ <a href="#help" class="help" title="<?php _e('Enable this checkbox to determine XPath from parent element.', 'pmxi_plugin') ?>" style="position:relative; top:2px;">?</a>
747
+ </span>
748
+ </p>
749
+ <p class="form-field">
750
+ <label style="width:150px;"><?php _e('Image','woocommerce');?></label>
751
+ <input type="text" value="<?php echo esc_attr($post['variable_image']) ?>" style="" name="variable_image" class="short">
752
+ <span class="use_parent">
753
+ <input type="hidden" name="variable_image_use_parent" value="0"/>
754
+ <input type="checkbox" name="variable_image_use_parent" id="variable_image_use_parent" style="position:relative; top:2px; margin-left:5px;" <?php echo ($post['variable_image_use_parent']) ? 'checked="checked"' : ''; ?>>
755
+ <label for="variable_image_use_parent" style="top:0px;">XPath Is From Parent</label>
756
+ </span>
757
+ </p>
758
+ </div>
759
+ <div class="options_group">
760
+ <p class="form-field">
761
+ <label style="width:150px;"><?php _e('Regular Price','woocommerce');?> (<?php echo get_woocommerce_currency_symbol(); ?>)</label>
762
+ <input type="text" value="<?php echo esc_attr($post['variable_regular_price']) ?>" style="" name="variable_regular_price" class="short">
763
+ <span class="use_parent">
764
+ <input type="hidden" name="variable_regular_price_use_parent" value="0"/>
765
+ <input type="checkbox" name="variable_regular_price_use_parent" id="variable_regular_price_use_parent" style="position:relative; top:6px; margin-left:5px;" <?php echo ($post['variable_regular_price_use_parent']) ? 'checked="checked"' : ''; ?>>
766
+ <label for="variable_regular_price_use_parent" style="top:0px;">XPath Is From Parent</label>
767
+ </span>
768
+ </p>
769
+ <p class="form-field">
770
+ <label style="width:150px;"><?php _e('Sale Price','woocommerce');?> (<?php echo get_woocommerce_currency_symbol(); ?>)</label>&nbsp;
771
+ <a id="variable_sale_price_shedule" href="javascript:void(0);" style="<?php if ($post['is_variable_sale_price_shedule']):?>display:none;<?php endif; ?>position:relative; top:-10px;"><?php _e('schedule');?></a>
772
+ <input type="text" value="<?php echo esc_attr($post['variable_sale_price']) ?>" style="" name="variable_sale_price" class="short">
773
+ <input type="hidden" name="is_variable_sale_price_shedule" value="<?php echo esc_attr($post['is_variable_sale_price_shedule']) ?>"/>
774
+ <span class="use_parent">
775
+ <input type="hidden" name="variable_sale_price_use_parent" value="0"/>
776
+ <input type="checkbox" name="variable_sale_price_use_parent" id="variable_sale_price_use_parent" style="position:relative; top:3px; margin-left:5px;" <?php echo ($post['variable_sale_price_use_parent']) ? 'checked="checked"' : ''; ?>>
777
+ <label for="variable_sale_price_use_parent">XPath Is From Parent</label>
778
+ </span>
779
+ </p>
780
+ </div>
781
+ <div class="options_group" <?php if ( ! $post['is_variable_sale_price_shedule']):?>style="display:none;"<?php endif; ?> id="variable_sale_price_range">
782
+ <p class="form-field">
783
+ <span style="vertical-align:middle">
784
+ <label style="width:150px;"><?php _e("Variable Sale Price Dates", "woocommerce"); ?></label>
785
+ <span class="use_parent" style="float:right;">
786
+ <input type="hidden" name="variable_sale_dates_use_parent" value="0"/>
787
+ <input type="checkbox" name="variable_sale_dates_use_parent" id="variable_sale_dates_use_parent" style="position:relative; top:4px; margin-left:5px;" <?php echo ($post['variable_sale_dates_use_parent']) ? 'checked="checked"' : ''; ?>>
788
+ <label for="variable_sale_dates_use_parent">XPath Is From Parent</label>
789
+ </span>
790
+ <br>
791
+ <input type="text" class="datepicker" name="variable_sale_price_dates_from" value="<?php echo esc_attr($post['variable_sale_price_dates_from']) ?>" style="float:none;"/>
792
+ <?php _e('and', 'pmxi_plugin') ?>
793
+ <input type="text" class="datepicker" name="variable_sale_price_dates_to" value="<?php echo esc_attr($post['variable_sale_price_dates_to']) ?>" style="float:none;"/>
794
+ &nbsp;<a id="cancel_variable_regular_price_shedule" href="javascript:void(0);"><?php _e('cancel');?></a>
795
+ </span>
796
+
797
+ </p>
798
+ </div>
799
+ <div class="options_group" <?php echo ( ! $post['_variable_virtual']) ? 'style="display:none;"' : ''; ?> id="variable_virtual">
800
+ <div class="input" style="padding-left:0px;">
801
+ <div class="input fleft">
802
+ <input type="radio" id="is_variable_product_virtual_yes" class="switcher" name="is_variable_product_virtual" value="yes" <?php echo 'yes' == $post['is_variable_product_virtual'] ? 'checked="checked"': '' ?>/>
803
+ <label for="is_variable_product_virtual_yes"><?php _e("Virtual"); ?></label>
804
+ </div>
805
+ <div class="input fleft">
806
+ <input type="radio" id="is_variable_product_virtual_no" class="switcher" name="is_variable_product_virtual" value="no" <?php echo 'no' == $post['is_variable_product_virtual'] ? 'checked="checked"': '' ?>/>
807
+ <label for="is_variable_product_virtual_no"><?php _e("Not Virtual"); ?></label>
808
+ </div>
809
+ <div class="input fleft" style="position:relative;width:220px;">
810
+ <input type="radio" id="is_variable_product_virtual_xpath" class="switcher" name="is_variable_product_virtual" value="xpath" <?php echo 'xpath' == $post['is_variable_product_virtual'] ? 'checked="checked"': '' ?>/>
811
+ <label for="is_variable_product_virtual_xpath"><?php _e('Set with XPath', 'pmxi_plugin' )?></label> <br>
812
+ <div class="switcher-target-is_variable_product_virtual_xpath set_with_xpath" style="width:300px;">
813
+ <div class="input" style="width:365px;">
814
+ &nbsp;<input type="text" class="smaller-text" name="single_variable_product_virtual" style="width:300px;" value="<?php echo esc_attr($post['single_variable_product_virtual']) ?>"/>
815
+ <a href="#help" class="help" title="<?php _e('The value of presented XPath should be one of the following: (\'yes\', \'no\').', 'pmxi_plugin') ?>" style="position:relative; top:2px;">?</a>
816
+ <span class="use_parent" style="float:right;">
817
+ <input type="hidden" name="single_variable_product_virtual_use_parent" value="0"/>
818
+ <input type="checkbox" name="single_variable_product_virtual_use_parent" id="single_variable_product_virtual_use_parent" style="position:relative; top:4px; margin-left:5px;" <?php echo ($post['single_variable_product_virtual_use_parent']) ? 'checked="checked"' : ''; ?>>
819
+ <label for="single_variable_product_virtual_use_parent" style="top:3px;">XPath Is From Parent</label>
820
+ </span>
821
+ </div>
822
+ </div>
823
+ </div>
824
+ </div>
825
+ </div>
826
+ <div class="options_group" <?php echo ($post['_variable_virtual']) ? 'style="display:none;"' : ''; ?> id="variable_dimensions">
827
+ <p class="form-field">
828
+ <label style="width:150px;"><?php _e('Weight','woocommerce');?></label>
829
+ <input type="text" placeholder="0.00" value="<?php echo esc_attr($post['variable_weight']) ?>" style="" name="variable_weight" class="short">
830
+ <span class="use_parent">
831
+ <input type="hidden" name="variable_weight_use_parent" value="0"/>
832
+ <input type="checkbox" name="variable_weight_use_parent" id="variable_weight_use_parent" style="position:relative; top:6px; margin-left:5px;" <?php echo ($post['variable_weight_use_parent']) ? 'checked="checked"' : ''; ?>>
833
+ <label for="variable_weight_use_parent">XPath Is From Parent</label>
834
+ </span>
835
+ </p>
836
+ <p class="form-field">
837
+ <label for"product_length"=""><?php _e('Dimensions (L×W×H)','woocommerce');?></label>
838
+ <span class="use_parent" style="float:right;">
839
+ <input type="hidden" name="variable_dimensions_use_parent" value="0"/>
840
+ <input type="checkbox" name="variable_dimensions_use_parent" id="variable_dimensions_use_parent" style="position:relative; top:3px; margin-left:5px;" <?php echo ($post['variable_dimensions_use_parent']) ? 'checked="checked"' : ''; ?>>
841
+ <label for="variable_dimensions_use_parent">XPath Is From Parent</label>
842
+ </span>
843
+ <br>
844
+ <input type="text" placeholder="0" value="<?php echo esc_attr($post['variable_length']) ?>" name="variable_length" class="short" style="margin-right:5px;">
845
+ <input type="text" placeholder="0" value="<?php echo esc_attr($post['variable_width']) ?>" name="variable_width" class="short" style="margin-right:5px;">
846
+ <input type="text" placeholder="0" value="<?php echo esc_attr($post['variable_height']) ?>" style="" name="variable_height" class="short">
847
+
848
+ </p>
849
+ </div>
850
+ <div class="options_group">
851
+ <p class="form-field">
852
+ <div class="input">
853
+ <div class="main_choise">
854
+ <input type="radio" id="multiple_variable_product_shipping_class_yes" class="switcher" name="is_multiple_variable_product_shipping_class" value="yes" <?php echo 'no' != $post['is_multiple_variable_product_shipping_class'] ? 'checked="checked"': '' ?>/>
855
+ <label for="multiple_variable_product_shipping_class_yes" style="width:150px;"><?php _e("Shipping Class"); ?></label>
856
+ </div>
857
+ <div class="switcher-target-multiple_variable_product_shipping_class_yes" style="padding-left:17px;">
858
+ <div class="input">
859
+ <?php
860
+ $classes = get_the_terms( 0, 'product_shipping_class' );
861
+ if ( $classes && ! is_wp_error( $classes ) ) $current_shipping_class = current($classes)->term_id; else $current_shipping_class = '';
862
+
863
+ $args = array(
864
+ 'taxonomy' => 'product_shipping_class',
865
+ 'hide_empty' => 0,
866
+ 'show_option_none' => __( 'No shipping class', 'woocommerce' ),
867
+ 'name' => 'multiple_variable_product_shipping_class',
868
+ 'id' => 'multiple_variable_product_shipping_class',
869
+ 'selected' => $current_shipping_class,
870
+ 'class' => 'select short'
871
+ );
872
+
873
+ wp_dropdown_categories( $args );
874
+ ?>
875
+ </div>
876
+ </div>
877
+ </div>
878
+ <div class="input">
879
+ <div class="main_choise">
880
+ <input type="radio" id="multiple_variable_product_shipping_class_no" class="switcher" name="is_multiple_variable_product_shipping_class" value="no" <?php echo 'no' == $post['is_multiple_variable_product_shipping_class'] ? 'checked="checked"': '' ?>/>
881
+ <label for="multiple_variable_product_shipping_class_no"><?php _e('Set product shipping class with XPath', 'pmxi_plugin' )?></label>
882
+ </div>
883
+ <div class="switcher-target-multiple_variable_product_shipping_class_no" style="padding-left:17px;">
884
+ <div class="input">
885
+ <input type="text" class="smaller-text" name="single_variable_product_shipping_class" style="width:300px;" value="<?php echo esc_attr($post['single_variable_product_shipping_class']) ?>"/>
886
+ <a href="#help" class="help" title="<?php _e('The value of presented XPath should be one of the following: (\'taxable\', \'shipping\', \'none\').', 'pmxi_plugin') ?>">?</a>
887
+ <span class="use_parent">
888
+ <input type="hidden" name="single_variable_product_shipping_class_use_parent" value="0"/>
889
+ <input type="checkbox" name="single_variable_product_shipping_class_use_parent" id="single_variable_product_shipping_class_use_parent" style="position:relative; top:2px; margin-left:5px;" <?php echo ($post['single_variable_product_shipping_class_use_parent']) ? 'checked="checked"' : ''; ?>>
890
+ <label for="single_variable_product_shipping_class_use_parent" style="top:0px;">XPath Is From Parent</label>
891
+ </span>
892
+ </div>
893
+ </div>
894
+ </div>
895
+ </p>
896
+ <p class="form-field">
897
+ <div class="input">
898
+ <div class="main_choise">
899
+ <input type="radio" id="multiple_variable_product_tax_class_yes" class="switcher" name="is_multiple_variable_product_tax_class" value="yes" <?php echo 'no' != $post['is_multiple_variable_product_tax_class'] ? 'checked="checked"': '' ?>/>
900
+ <label for="multiple_variable_product_tax_class_yes" style="width:150px;"><?php _e("Tax Class", "woocommerce"); ?></label>
901
+ </div>
902
+ <div class="switcher-target-multiple_variable_product_tax_class_yes" style="padding-left:17px;">
903
+ <div class="input">
904
+ <select class="select short" name="multiple_variable_product_tax_class">
905
+ <option value="parent" <?php echo 'parent' == $post['multiple_variable_product_tax_class'] ? 'selected="selected"': '' ?>><?php _e('Same as parent', 'woocommerce');?></option>
906
+ <option value="" <?php echo '' == $post['multiple_variable_product_tax_class'] ? 'selected="selected"': '' ?>><?php _e('Standard', 'woocommerce');?></option>
907
+ <option value="reduced-rate" <?php echo 'reduced-rate' == $post['multiple_variable_product_tax_class'] ? 'selected="selected"': '' ?>><?php _e('Reduced Rate', 'woocommerce');?></option>
908
+ <option value="zero-rate" <?php echo 'zero-rate' == $post['multiple_variable_product_tax_class'] ? 'selected="selected"': '' ?>><?php _e('Zero Rate', 'woocommerce');?></option>
909
+ </select>
910
+ </div>
911
+ </div>
912
+ </div>
913
+ <div class="input">
914
+ <div class="main_choise">
915
+ <input type="radio" id="multiple_variable_product_tax_class_no" class="switcher" name="is_multiple_variable_product_tax_class" value="no" <?php echo 'no' == $post['is_multiple_variable_product_tax_class'] ? 'checked="checked"': '' ?>/>
916
+ <label for="multiple_variable_product_tax_class_no"><?php _e('Set product tax class with XPath', 'pmxi_plugin' )?></label>
917
+ </div>
918
+ <div class="switcher-target-multiple_variable_product_tax_class_no" style="padding-left:17px;">
919
+ <div class="input">
920
+ <input type="text" class="smaller-text" name="single_variable_product_tax_class" style="width:300px;" value="<?php echo esc_attr($post['single_variable_product_tax_class']) ?>"/>
921
+ <a href="#help" class="help" title="<?php _e('The value of presented XPath should be one of the following: (\'reduced-rate\', \'zero-rate\').', 'pmxi_plugin') ?>">?</a>
922
+ <span class="use_parent">
923
+ <input type="hidden" name="single_variable_product_tax_class_use_parent" value="0"/>
924
+ <input type="checkbox" name="single_variable_product_tax_class_use_parent" id="single_variable_product_tax_class_use_parent" style="position:relative; top:2px; margin-left:5px;" <?php echo ($post['single_variable_product_tax_class_use_parent']) ? 'checked="checked"' : ''; ?>>
925
+ <label for="single_variable_product_tax_class_use_parent" style="top:0px;">XPath Is From Parent</label>
926
+ </span>
927
+ </div>
928
+ </div>
929
+ </div>
930
+ </p>
931
+ </div>
932
+ <div class="options_group" <?php echo ( ! $post['_variable_downloadable']) ? 'style="display:none;"' : ''; ?> id="variable_downloadable">
933
+ <p class="form-field">
934
+ <div class="input fleft">
935
+ <input type="radio" id="is_variable_product_downloadable_yes" class="switcher" name="is_variable_product_downloadable" value="yes" <?php echo 'yes' == $post['is_variable_product_downloadable'] ? 'checked="checked"': '' ?>/>
936
+ <label for="is_variable_product_downloadable_yes"><?php _e("Downloadable"); ?></label>
937
+ </div>
938
+ <div class="input fleft">
939
+ <input type="radio" id="is_variable_product_downloadable_no" class="switcher" name="is_variable_product_downloadable" value="no" <?php echo 'no' == $post['is_variable_product_downloadable'] ? 'checked="checked"': '' ?>/>
940
+ <label for="is_variable_product_downloadable_no"><?php _e("Not Downloadable"); ?></label>
941
+ </div>
942
+ <div class="input fleft" style="position:relative; width:220px;">
943
+ <input type="radio" id="is_variable_product_downloadable_xpath" class="switcher" name="is_variable_product_downloadable" value="xpath" <?php echo 'xpath' == $post['is_variable_product_downloadable'] ? 'checked="checked"': '' ?>/>
944
+ <label for="is_variable_product_downloadable_xpath"><?php _e('Set with XPath', 'pmxi_plugin' )?></label> <br>
945
+ <div class="switcher-target-is_variable_product_downloadable_xpath set_with_xpath" style="width:300px;">
946
+ <div class="input">
947
+ <input type="text" class="smaller-text" name="single_variable_product_downloadable" style="width:345px;" value="<?php echo esc_attr($post['single_variable_product_downloadable']) ?>"/>
948
+ <a href="#help" class="help" title="<?php _e('The value of presented XPath should be one of the following: (\'yes\', \'no\').', 'pmxi_plugin') ?>" style="position:relative; top:2px;">?</a>
949
+ <span class="use_parent">
950
+ <input type="hidden" name="single_variable_product_downloadable_use_parent" value="0"/>
951
+ <input type="checkbox" name="single_variable_product_downloadable_use_parent" id="single_variable_product_downloadable_use_parent" style="position:relative; top:4px; margin-left:5px;" <?php echo ($post['single_variable_product_downloadable_use_parent']) ? 'checked="checked"' : ''; ?>>
952
+ <label for="single_variable_product_downloadable_use_parent" style="top:2px;">XPath Is From Parent</label>
953
+ </span>
954
+ </div>
955
+ </div>
956
+ </div>
957
+ </p>
958
+ <p class="form-field">
959
+ <label style="width:150px;"><?php _e('File paths','woocommerce');?></label>
960
+ <input type="text" value="<?php echo esc_attr($post['variable_file_paths']) ?>" name="variable_file_paths" class="short" style="width:60% !important;">
961
+ <input type="text" class="small" name="variable_product_files_delim" value="<?php echo esc_attr($post['variable_product_files_delim']) ?>" style="width:5% !important;text-align:center; margin-left:5px;"/>
962
+ <a href="#help" class="help" title="<?php _e('File paths/URLs, comma separated. The delimiter option uses when xml element contains few paths/URLs (http://files.com/1.doc, http://files.com/2.doc).', 'pmxi_plugin') ?>">?</a>
963
+ </p>
964
+ <p class="form-field">
965
+ <label style="width:150px;"><?php _e('Download Limit','woocommerce');?></label>
966
+ <input type="text" value="<?php echo esc_attr($post['variable_download_limit']) ?>" style="" name="variable_download_limit" class="short">
967
+ <span class="use_parent">
968
+ <input type="hidden" name="variable_download_limit_use_parent" value="0"/>
969
+ <input type="checkbox" name="variable_download_limit_use_parent" id="variable_download_limit_use_parent" style="position:relative; top:4px; margin-left:5px;" <?php echo ($post['variable_download_limit_use_parent']) ? 'checked="checked"' : ''; ?>>
970
+ <label for="variable_download_limit_use_parent">XPath Is From Parent</label>
971
+ </span>
972
+ </p>
973
+ <p class="form-field">
974
+ <label style="width:150px;"><?php _e('Download Expiry','woocommerce');?></label>
975
+ <input type="text" value="<?php echo esc_attr($post['variable_download_expiry']) ?>" style="" name="variable_download_expiry" class="short">
976
+ <span class="use_parent">
977
+ <input type="hidden" name="variable_download_expiry_use_parent" value="0"/>
978
+ <input type="checkbox" name="variable_download_expiry_use_parent" id="variable_download_expiry_use_parent" style="position:relative; top:4px; margin-left:5px;" <?php echo ($post['variable_download_expiry_use_parent']) ? 'checked="checked"' : ''; ?>>
979
+ <label for="variable_download_expiry_use_parent">XPath Is From Parent</label>
980
+ </span>
981
+ </p>
982
+ </div>
983
+
984
+ <div class="options_group">
985
+
986
+ <p class="form-field"><?php _e('Variation Enabled','pmxi_plugin');?></p>
987
+ <div class="input" style="margin-top:-10px;">
988
+ <div class="input fleft">
989
+ <input type="radio" id="variable_product_enabled_yes" class="switcher" name="is_variable_product_enabled" value="yes" <?php echo 'yes' == $post['is_variable_product_enabled'] ? 'checked="checked"': '' ?>/>
990
+ <label for="variable_product_enabled_yes"><?php _e("Yes"); ?></label>
991
+ </div>
992
+ <div class="input fleft">
993
+ <input type="radio" id="variable_product_enabled_no" class="switcher" name="is_variable_product_enabled" value="no" <?php echo 'no' == $post['is_variable_product_enabled'] ? 'checked="checked"': '' ?>/>
994
+ <label for="variable_product_enabled_no"><?php _e("No"); ?></label>
995
+ </div>
996
+ <div class="input fleft" style="position:relative; width:220px;">
997
+ <input type="radio" id="variable_product_enabled_xpath" class="switcher" name="is_variable_product_enabled" value="xpath" <?php echo 'xpath' == $post['is_variable_product_enabled'] ? 'checked="checked"': '' ?>/>
998
+ <label for="variable_product_enabled_xpath"><?php _e('Set with XPath', 'pmxi_plugin' )?></label><br>
999
+ <div class="switcher-target-variable_product_enabled_xpath set_with_xpath">
1000
+ <div class="input">
1001
+ <input type="text" class="smaller-text" name="single_variable_product_enabled" style="width:300px;" value="<?php echo esc_attr($post['single_variable_product_enabled']) ?>"/>
1002
+ <a href="#help" class="help" title="<?php _e('The value of presented XPath should be one of the following: (\'yes\', \'no\').', 'pmxi_plugin') ?>" style="position:relative; top:2px;">?</a>
1003
+ </div>
1004
+ </div>
1005
+ </div>
1006
+ </div>
1007
+
1008
+ </div>
1009
+
1010
+ <div class="options_group variation_attributes">
1011
+ <p class="form-field">
1012
+ <label style="width:150px; padding-left:0px;"><?php _e('Variation Attributes','pmxi_plugin');?></label>
1013
+ </p>
1014
+ <div class="input">
1015
+ <table class="form-table custom-params" style="max-width:95%;">
1016
+ <thead>
1017
+ <tr>
1018
+ <td><?php _e('Name', 'pmxi_plugin') ?></td>
1019
+ <td><?php _e('Values', 'pmxi_plugin') ?></td>
1020
+ <td></td>
1021
+ </tr>
1022
+ </thead>
1023
+ <tbody>
1024
+ <?php if (!empty($post['variable_attribute_name'][0])):?>
1025
+ <?php foreach ($post['variable_attribute_name'] as $i => $name): if ("" == $name) continue; ?>
1026
+ <tr class="form-field">
1027
+ <td><input type="text" name="variable_attribute_name[]" value="<?php echo esc_attr($name) ?>" style="width:100%;"/></td>
1028
+ <td><textarea name="variable_attribute_value[]"><?php echo esc_html($post['variable_attribute_value'][$i]) ?></textarea>
1029
+ <br>
1030
+ <span class='in_variations' style="margin-left:0px;">
1031
+ <input type="checkbox" name="variable_in_variations[]" id="variable_in_variations_<?php echo $i; ?>" <?php echo ($post['variable_in_variations'][$i]) ? 'checked="checked"' : ''; ?> style="width: auto; position: relative; top: 1px; left: 0px;" value="1"/>
1032
+ <label for="variable_in_variations_<?php echo $i; ?>"><?php _e('In Variations','pmxi_plugin');?></label>
1033
+ </span>
1034
+
1035
+ <span class='is_visible'>
1036
+ <input type="checkbox" name="variable_is_visible[]" id="variable_is_visible_<?php echo $i; ?>" <?php echo ($post['variable_is_visible'][$i]) ? 'checked="checked"' : ''; ?> style="width: auto; position: relative; top: 1px; left: 0px;" value="1"/>
1037
+ <label for="variable_is_visible_<?php echo $i; ?>"><?php _e('Is Visible','pmxi_plugin');?></label>
1038
+ </span>
1039
+
1040
+ <span class='is_taxonomy'>
1041
+ <input type="checkbox" name="variable_is_taxonomy[]" id="variable_is_taxonomy_<?php echo $i; ?>" <?php echo ($post['variable_is_taxonomy'][$i]) ? 'checked="checked"' : ''; ?> style="width: auto; position: relative; top: 1px; left: 0px;" value="1"/>
1042
+ <label for="variable_is_taxonomy_<?php echo $i; ?>"><?php _e('Taxonomy','pmxi_plugin');?></label>
1043
+ </span>
1044
+
1045
+ <span class='is_create_taxonomy'>
1046
+ <input type="checkbox" name="variable_create_taxonomy_in_not_exists[]" id="variable_create_taxonomy_in_not_exists_<?php echo $i;?>" <?php echo ($post['variable_create_taxonomy_in_not_exists'][$i]) ? 'checked="checked"' : ''; ?> style="width: auto; position: relative; top: 1px; left: 0px;" value="1"/>
1047
+ <label for="variable_create_taxonomy_in_not_exists_<?php echo $i; ?>"><?php _e('Auto-Create Terms','pmxi_plugin');?></label>
1048
+ </span>
1049
+
1050
+ <!--a href="#help" class="help" title="<?php _e('Enable &#39;is taxonomy&#39; and an Attribute on the Products -> Attributes page of WooCommerce will be added or an existing Attribute of the same name will be used. Check this box to auto-create attribute values, if they haven&#39;t already been set up.', 'pmxi_plugin') ?>" style="position:relative; top:-5px; left:24px;">?</a-->
1051
+
1052
+ </td>
1053
+ <td class="action remove"><a href="#remove"></a></td>
1054
+ </tr>
1055
+ <?php endforeach ?>
1056
+ <?php else: ?>
1057
+ <tr class="form-field">
1058
+ <td><input type="text" name="variable_attribute_name[]" value="" style="width:100%;"/></td>
1059
+ <td><textarea name="variable_attribute_value[]"></textarea>
1060
+ <br>
1061
+ <span class='in_variations' style="margin-left:0px;">
1062
+ <input type="checkbox" name="variable_in_variations[]" id="variable_in_variations_0" checked="checked" style="width: auto; position: relative; top: 1px; left: 0px;" value="1"/>
1063
+ <label for="variable_in_variations_0"><?php _e('In Variations','pmxi_plugin');?></label>
1064
+ </span>
1065
+ <span class='is_visible'>
1066
+ <input type="checkbox" name="variable_is_visible[]" id="variable_is_visible_0" checked="checked" style="width: auto; position: relative; top: 1px; left: 0px;" value="1"/>
1067
+ <label for="variable_is_visible_0"><?php _e('Is Visible','pmxi_plugin');?></label>
1068
+ </span>
1069
+ <span class='is_taxonomy'>
1070
+ <input type="checkbox" name="variable_is_taxonomy[]" id="variable_is_taxonomy_0" checked="checked" style="width: auto; position: relative; top: 1px; left: 0px;" value="1"/>
1071
+ <label for="variable_is_taxonomy_0"><?php _e('Taxonomy','pmxi_plugin');?></label>
1072
+ </span>
1073
+ <span class='is_create_taxonomy'>
1074
+ <input type="checkbox" name="variable_create_taxonomy_in_not_exists[]" id="variable_create_taxonomy_in_not_exists_0" checked="checked" style="width: auto; position: relative; top: 1px; left: 0px;" value="1"/>
1075
+ <label for="variable_create_taxonomy_in_not_exists_0"><?php _e('Auto-Create Terms','pmxi_plugin');?></label>
1076
+ </span>
1077
+ <td class="action remove"><a href="#remove"></a></td>
1078
+ </tr>
1079
+ <?php endif;?>
1080
+ <tr class="form-field template">
1081
+ <td><input type="text" name="variable_attribute_name[]" value="" style="width:100%;"/></td>
1082
+ <td><textarea name="variable_attribute_value[]"></textarea>
1083
+ <br>
1084
+ <span class='in_variations' style="margin-left:0px;">
1085
+ <input type="checkbox" name="variable_in_variations[]" checked="checked" style="width: auto; position: relative; top: 1px; left: 0px;" value="1"/>
1086
+ <label for=""><?php _e('In Variations','pmxi_plugin');?></label>
1087
+ </span>
1088
+ <span class='is_visible'>
1089
+ <input type="checkbox" name="variable_is_visible[]" checked="checked" style="width: auto; position: relative; top: 1px; left: 0px;" value="1"/>
1090
+ <label for=""><?php _e('Is Visible','pmxi_plugin');?></label>
1091
+ </span>
1092
+ <span class='is_taxonomy'>
1093
+ <input type="checkbox" name="variable_is_taxonomy[]" checked="checked" style="width: auto; position: relative; top: 1px; left: 0px;" value="1"/>
1094
+ <label for=""><?php _e('Taxonomy','pmxi_plugin');?></label>
1095
+ </span>
1096
+ <span class='is_create_taxonomy'>
1097
+ <input type="checkbox" name="variable_create_taxonomy_in_not_exists[]" checked="checked" style="width: auto; position: relative; top: 1px; left: 0px;" value="1"/>
1098
+ <label for=""><?php _e('Auto-Create Terms','pmxi_plugin');?></label>
1099
+ </span>
1100
+ <td class="action remove"><a href="#remove"></a></td>
1101
+ </tr>
1102
+ <tr>
1103
+ <td colspan="3"><a href="#add" title="<?php _e('add', 'pmxi_plugin')?>" class="action add-new-custom"><?php _e('Add more', 'pmxi_plugin') ?></a></td>
1104
+ </tr>
1105
+ </tbody>
1106
+ </table>
1107
+ </div>
1108
+ </div>
1109
+ </div>
1110
+ </div>
1111
+ </div>
1112
+ </div>
1113
+ </div>
1114
+ <div class="options_group">
1115
+ <p class="form-field"><?php _e('Variable Enabled','pmxi_plugin');?></p>
1116
+ <div class="input" style="margin-top:-10px;">
1117
+ <div class="input fleft">
1118
+ <input type="radio" id="product_enabled_yes" class="switcher" name="is_product_enabled" value="yes" <?php echo 'yes' == $post['is_product_enabled'] ? 'checked="checked"': '' ?>/>
1119
+ <label for="product_enabled_yes"><?php _e("Yes"); ?></label>
1120
+ </div>
1121
+ <div class="input fleft">
1122
+ <input type="radio" id="product_enabled_no" class="switcher" name="is_product_enabled" value="no" <?php echo 'no' == $post['is_product_enabled'] ? 'checked="checked"': '' ?>/>
1123
+ <label for="product_enabled_no"><?php _e("No"); ?></label>
1124
+ </div>
1125
+ <div class="input fleft" style="position:relative; width:220px;">
1126
+ <input type="radio" id="product_enabled_xpath" class="switcher" name="is_product_enabled" value="xpath" <?php echo 'xpath' == $post['is_product_enabled'] ? 'checked="checked"': '' ?>/>
1127
+ <label for="product_enabled_xpath"><?php _e('Set with XPath', 'pmxi_plugin' )?></label><br>
1128
+ <div class="switcher-target-product_enabled_xpath set_with_xpath">
1129
+ <div class="input">
1130
+ <input type="text" class="smaller-text" name="single_product_enabled" style="width:300px;" value="<?php echo esc_attr($post['single_product_enabled']) ?>"/>
1131
+ <a href="#help" class="help" title="<?php _e('The value of presented XPath should be one of the following: (\'yes\', \'no\').', 'pmxi_plugin') ?>" style="position:relative; top:2px;">?</a>
1132
+ </div>
1133
+ </div>
1134
+ </div>
1135
+ </div>
1136
+ </div>
1137
+ </div><!-- End Product Panel -->
1138
+
1139
+
1140
+ <!-- OPTIONS -->
1141
+
1142
+ <div class="panel woocommerce_options_panel" id="add_on_options" style="display:none;">
1143
+ <p class="upgrade_template" style='display:none; font-size: 1.3em; font-weight: bold;'>
1144
+ <a href="http://www.wpallimport.com/upgrade-to-pro?utm_source=wordpress.org&utm_medium=wooco&utm_campaign=free+plugin+wooco" target="_blank" class="upgrade_link">Upgrade to the pro version of the WooCommerce Add-On to import to grouped, affiliate/external, and variable products.</a>
1145
+ </p>
1146
+ <div class="options_group">
1147
+ <p class="form-field" style="font-size:16px; font-weight:bold;"><?php _e('Re-import options','pmxi_plugin');?></p>
1148
+ <div class="input" style="padding-left:20px;">
1149
+ <input type="hidden" name="missing_records_stock_status" value="0" />
1150
+ <input type="checkbox" id="missing_records_stock_status" name="missing_records_stock_status" value="1" <?php echo $post['missing_records_stock_status'] ? 'checked="checked"' : '' ?> />
1151
+ <label for="missing_records_stock_status"><?php _e('Set out of stock status for missing records', 'pmxi_plugin') ?></label>
1152
+ <a href="#help" class="help" title="<?php _e('Option to set the stock status to out of stock instead of deleting the product entirely. This option doesn\'t work when \'Delete missing records\' option is enabled.', 'pmxi_plugin') ?>" style="position:relative; top:-2px;">?</a>
1153
+ </div>
1154
+ </div>
1155
+ </div>
1156
+ </div>
1157
+ </div>
1158
+ </div>
1159
+
1160
+ <div class="clear"></div>
1161
+
1162
+ </td>
1163
+ </tr>
views/controller/error.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php foreach ($errors as $msg): ?>
2
+ <div class="error"><p><?php echo $msg ?></p></div>
3
+ <?php endforeach ?>