PluginProbe ʕ •ᴥ•ʔ
WP All Export – Drag & Drop Export to Any Custom CSV, XML & Excel / 1.2.7
WP All Export – Drag & Drop Export to Any Custom CSV, XML & Excel v1.2.7
trunk 0.9.0 0.9.1 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.2.0 1.2.1 1.2.10 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.10 1.4.11 1.4.12 1.4.13 1.4.14 1.4.15 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0
wp-all-export / wp-all-export.php
wp-all-export Last commit date
actions 5 years ago classes 6 years ago config 6 years ago controllers 5 years ago dist 5 years ago filters 7 years ago helpers 7 years ago history 12 years ago i18n 8 years ago libraries 5 years ago models 7 years ago sessions 10 years ago shortcodes 10 years ago src 5 years ago static 5 years ago views 5 years ago banner-772x250.png 12 years ago readme.txt 5 years ago schema.php 7 years ago screenshot-1.png 10 years ago screenshot-2.png 10 years ago wp-all-export.php 5 years ago wpae_api.php 9 years ago
wp-all-export.php
920 lines
1 <?php
2 /*
3 Plugin Name: WP All Export
4 Plugin URI: http://www.wpallimport.com/upgrade-to-wp-all-export-pro/?utm_source=export-plugin-free&utm_medium=wp-plugins-page&utm_campaign=upgrade-to-pro
5 Description: Export any post type to a CSV or XML file. Edit the exported data, and then re-import it later using WP All Import.
6 Version: 1.2.7
7 Author: Soflyy
8 */
9
10 require_once(__DIR__.'/classes/CdataStrategyFactory.php');
11
12 if( ! defined( 'PMXE_SESSION_COOKIE' ) )
13 define( 'PMXE_SESSION_COOKIE', '_pmxe_session' );
14
15 // Enable error reporting in development
16 if(getenv('WPAE_DEV')) {
17 error_reporting(E_ALL ^ E_DEPRECATED );
18 ini_set('display_errors', 1);
19 // xdebug_disable();
20 }
21
22 /**
23 * Plugin root dir with forward slashes as directory separator regardless of actuall DIRECTORY_SEPARATOR value
24 * @var string
25 */
26 define('PMXE_ROOT_DIR', str_replace('\\', '/', dirname(__FILE__)));
27 /**
28 * Plugin root url for referencing static content
29 * @var string
30 */
31 define('PMXE_ROOT_URL', rtrim(plugin_dir_url(__FILE__), '/'));
32
33 if ( class_exists('PMXE_Plugin') and PMXE_EDITION == "paid"){
34
35 function pmxe_notice(){
36
37 ?>
38 <div class="error">
39 <p>
40 <?php printf(__('Please de-activate and remove the free version of the WP All Export before activating the paid version.', 'wp_all_export_plugin')); ?>
41 </p>
42 </div>
43 <?php
44
45 deactivate_plugins( str_replace('\\', '/', dirname(__FILE__)) . '/wp-all-export.php');
46
47 }
48
49 add_action('admin_notices', 'pmxe_notice');
50
51 }
52 else {
53
54 /**
55 * Plugin prefix for making names unique (be aware that this variable is used in conjuction with naming convention,
56 * i.e. in order to change it one must not only modify this constant but also rename all constants, classes and functions which
57 * names composed using this prefix)
58 * @var string
59 */
60 define('PMXE_PREFIX', 'pmxe_');
61
62 define('PMXE_VERSION', '1.2.7');
63
64 define('PMXE_ASSETS_VERSION', '-1.0.1');
65
66 define('PMXE_EDITION', 'free');
67
68 /**
69 * Plugin root uploads folder name
70 * @var string
71 */
72 define('WP_ALL_EXPORT_UPLOADS_BASE_DIRECTORY', 'wpallexport');
73 /**
74 * Plugin uploads folder name
75 * @var string
76 */
77 define('WP_ALL_EXPORT_UPLOADS_DIRECTORY', WP_ALL_EXPORT_UPLOADS_BASE_DIRECTORY . DIRECTORY_SEPARATOR . 'exports');
78
79 /**
80 * Plugin temp folder name
81 * @var string
82 */
83 define('WP_ALL_EXPORT_TEMP_DIRECTORY', WP_ALL_EXPORT_UPLOADS_BASE_DIRECTORY . DIRECTORY_SEPARATOR . 'temp');
84
85 /**
86 * Plugin temp folder name
87 * @var string
88 */
89 define('WP_ALL_EXPORT_CRON_DIRECTORY', WP_ALL_EXPORT_UPLOADS_BASE_DIRECTORY . DIRECTORY_SEPARATOR . 'exports');
90
91 /**
92 * Main plugin file, Introduces MVC pattern
93 *
94 * @singletone
95 * @author Pavel Kulbakin <p.kulbakin@gmail.com>
96 */
97 final class PMXE_Plugin {
98 /**
99 * Singletone instance
100 * @var PMXE_Plugin
101 */
102 protected static $instance;
103
104 /**
105 * Plugin options
106 * @var array
107 */
108 protected $options = array();
109
110 /**
111 * Plugin root dir
112 * @var string
113 */
114 const ROOT_DIR = PMXE_ROOT_DIR;
115 /**
116 * Plugin root URL
117 * @var string
118 */
119 const ROOT_URL = PMXE_ROOT_URL;
120 /**
121 * Prefix used for names of shortcodes, action handlers, filter functions etc.
122 * @var string
123 */
124 const PREFIX = PMXE_PREFIX;
125 /**
126 * Plugin file path
127 * @var string
128 */
129 const FILE = __FILE__;
130 /**
131 * Max allowed file size (bytes) to import in default mode
132 * @var int
133 */
134 const LARGE_SIZE = 0; // all files will importing in large import mode
135
136 /**
137 * WP All Import temp folder
138 * @var string
139 */
140 const TEMP_DIRECTORY = WP_ALL_EXPORT_TEMP_DIRECTORY;
141 /**
142 * WP All Import uploads folder
143 * @var string
144 */
145 const UPLOADS_DIRECTORY = WP_ALL_EXPORT_UPLOADS_DIRECTORY;
146 /**
147 * WP All Import uploads folder
148 * @var string
149 */
150 const CRON_DIRECTORY = WP_ALL_EXPORT_CRON_DIRECTORY;
151
152 const LANGUAGE_DOMAIN = 'wp_all_export_plugin';
153
154 public static $session = null;
155
156 public static $capabilities = 'manage_options';
157
158 private static $hasActiveSchedulingLicense = null;
159
160 public static $cache_key = '';
161
162 /**
163 * Class constructor containing dispatching logic
164 * @param string $rootDir Plugin root dir
165 * @param string $pluginFilePath Plugin main file
166 */
167 protected function __construct() {
168
169 require_once (self::ROOT_DIR . '/classes/installer.php');
170
171 $installer = new PMXE_Installer();
172 $installer->checkActivationConditions();
173
174 $plugin_basename = plugin_basename( __FILE__ );
175
176 self::$cache_key = md5( 'edd_plugin_' . sanitize_key( $plugin_basename ) . '_version_info' );
177
178 // uncaught exception doesn't prevent plugin from being activated, therefore replace it with fatal error so it does
179 //set_exception_handler(create_function('$e', 'trigger_error($e->getMessage(), E_USER_ERROR);'));
180
181 // register autoloading method
182 spl_autoload_register(array($this, 'autoload'));
183
184 // register helpers
185 if (is_dir(self::ROOT_DIR . '/helpers')) foreach (PMXE_Helper::safe_glob(self::ROOT_DIR . '/helpers/*.php', PMXE_Helper::GLOB_RECURSE | PMXE_Helper::GLOB_PATH) as $filePath) {
186 require_once $filePath;
187 }
188
189 // init plugin options
190 $option_name = get_class($this) . '_Options';
191 $options_default = PMXE_Config::createFromFile(self::ROOT_DIR . '/config/options.php')->toArray();
192 $current_options = get_option($option_name, array());
193 $this->options = array_intersect_key($current_options, $options_default) + $options_default;
194 $this->options = array_intersect_key($options_default, array_flip(array('info_api_url'))) + $this->options; // make sure hidden options apply upon plugin reactivation
195 if ('' == $this->options['cron_job_key']) $this->options['cron_job_key'] = wp_all_export_url_title(wp_all_export_rand_char(12));
196
197 if ($current_options !== $this->options) {
198 update_option($option_name, $this->options);
199 }
200 register_activation_hook(self::FILE, array($this, 'activation'));
201
202 // register action handlers
203 if (is_dir(self::ROOT_DIR . '/actions')) if (is_dir(self::ROOT_DIR . '/actions')) foreach (PMXE_Helper::safe_glob(self::ROOT_DIR . '/actions/*.php', PMXE_Helper::GLOB_RECURSE | PMXE_Helper::GLOB_PATH) as $filePath) {
204 require_once $filePath;
205 $function = $actionName = basename($filePath, '.php');
206 if (preg_match('%^(.+?)[_-](\d+)$%', $actionName, $m)) {
207 $actionName = $m[1];
208 $priority = intval($m[2]);
209 } else {
210 $priority = 10;
211 }
212 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)
213 }
214
215 // register filter handlers
216 if (is_dir(self::ROOT_DIR . '/filters')) foreach (PMXE_Helper::safe_glob(self::ROOT_DIR . '/filters/*.php', PMXE_Helper::GLOB_RECURSE | PMXE_Helper::GLOB_PATH) as $filePath) {
217 require_once $filePath;
218 $function = $actionName = basename($filePath, '.php');
219 if (preg_match('%^(.+?)[_-](\d+)$%', $actionName, $m)) {
220 $actionName = $m[1];
221 $priority = intval($m[2]);
222 } else {
223 $priority = 10;
224 }
225 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)
226 }
227
228 // register shortcodes handlers
229 if (is_dir(self::ROOT_DIR . '/shortcodes')) foreach (PMXE_Helper::safe_glob(self::ROOT_DIR . '/shortcodes/*.php', PMXE_Helper::GLOB_RECURSE | PMXE_Helper::GLOB_PATH) as $filePath) {
230 $tag = strtolower(str_replace('/', '_', preg_replace('%^' . preg_quote(self::ROOT_DIR . '/shortcodes/', '%') . '|\.php$%', '', $filePath)));
231 add_shortcode($tag, array($this, 'shortcodeDispatcher'));
232 }
233
234 // register admin page pre-dispatcher
235 add_action('admin_init', array($this, 'adminInit'));
236 add_action('admin_init', array($this, 'fix_db_schema'));
237 add_action('init', array($this, 'init'));
238
239 }
240
241 /**
242 * Return singletone instance
243 * @return PMXE_Plugin
244 */
245 static public function getInstance() {
246 if (self::$instance == NULL) {
247 self::$instance = new self();
248 }
249 return self::$instance;
250 }
251
252 static public function getSchedulingName(){
253 return 'Automatic Scheduling';
254 }
255
256 static public function hasActiveSchedulingLicense() {
257
258 if(is_null(self::$hasActiveSchedulingLicense)) {
259 $scheduling = \Wpae\Scheduling\Scheduling::create();
260 $hasActiveSchedulingLicense = $scheduling->checkLicense();
261 self::$hasActiveSchedulingLicense = $hasActiveSchedulingLicense;
262 }
263
264 return self::$hasActiveSchedulingLicense;
265 }
266
267 /**
268 * Common logic for requestin plugin info fields
269 */
270 public function __call($method, $args) {
271 if (preg_match('%^get(.+)%i', $method, $mtch)) {
272 $info = get_plugin_data(self::FILE);
273 if (isset($info[$mtch[1]])) {
274 return $info[$mtch[1]];
275 }
276 }
277 throw new Exception("Requested method " . get_class($this) . "::$method doesn't exist.");
278 }
279
280 /**
281 * Get path to plagin dir relative to wordpress root
282 * @param bool[optional] $noForwardSlash Whether path should be returned withot forwarding slash
283 * @return string
284 */
285 public function getRelativePath($noForwardSlash = false) {
286 $wp_root = str_replace('\\', '/', ABSPATH);
287 return ($noForwardSlash ? '' : '/') . str_replace($wp_root, '', self::ROOT_DIR);
288 }
289
290 /**
291 * Check whether plugin is activated as network one
292 * @return bool
293 */
294 public function isNetwork() {
295 if ( !is_multisite() )
296 return false;
297
298 $plugins = get_site_option('active_sitewide_plugins');
299 if (isset($plugins[plugin_basename(self::FILE)]))
300 return true;
301
302 return false;
303 }
304
305 /**
306 * Check whether permalinks is enabled
307 * @return bool
308 */
309 public function isPermalinks() {
310 global $wp_rewrite;
311
312 return $wp_rewrite->using_permalinks();
313 }
314
315 /**
316 * Return prefix for plugin database tables
317 * @return string
318 */
319 public function getTablePrefix() {
320 global $wpdb;
321
322 //return ($this->isNetwork() ? $wpdb->base_prefix : $wpdb->prefix) . self::PREFIX;
323 return $wpdb->prefix . self::PREFIX;
324 }
325
326 /**
327 * Return prefix for wordpress database tables
328 * @return string
329 */
330 public function getWPPrefix() {
331 global $wpdb;
332 return ($this->isNetwork()) ? $wpdb->base_prefix : $wpdb->prefix;
333 }
334
335 public function init(){
336 $this->load_plugin_textdomain();
337 }
338
339 public function showNoticeAndDisablePlugin($message){
340 $this->showNotice($message);
341 deactivate_plugins( str_replace('\\', '/', dirname(__FILE__)) . '/wp-all-export.php');
342 }
343
344 public function showNotice($message)
345 {
346 $notice = new \Wpae\WordPress\AdminErrorNotice($message);
347 $notice->render();
348 }
349
350 /**
351 * pre-dispatching logic for admin page controllers
352 */
353 public function adminInit() {
354
355 // create history folder
356 $uploads = wp_upload_dir();
357
358 $wpallimportDirs = array( WP_ALL_EXPORT_UPLOADS_BASE_DIRECTORY, self::TEMP_DIRECTORY, self::UPLOADS_DIRECTORY, self::CRON_DIRECTORY);
359
360 foreach ($wpallimportDirs as $destination) {
361
362 $dir = $uploads['basedir'] . DIRECTORY_SEPARATOR . $destination;
363
364 if ( !is_dir($dir)) wp_mkdir_p($dir);
365
366 if ( ! @file_exists($dir . DIRECTORY_SEPARATOR . 'index.php') ) @touch( $dir . DIRECTORY_SEPARATOR . 'index.php' );
367
368 }
369
370 if ( ! is_dir($uploads['basedir'] . DIRECTORY_SEPARATOR . WP_ALL_EXPORT_UPLOADS_BASE_DIRECTORY) or ! is_writable($uploads['basedir'] . DIRECTORY_SEPARATOR . WP_ALL_EXPORT_UPLOADS_BASE_DIRECTORY)) {
371 $this->showNoticeAndDisablePlugin(sprintf(__('Uploads folder %s must be writable', 'wp_all_export_plugin'), $uploads['basedir'] . DIRECTORY_SEPARATOR . WP_ALL_EXPORT_UPLOADS_BASE_DIRECTORY));
372 }
373
374 if ( ! is_dir($uploads['basedir'] . DIRECTORY_SEPARATOR . self::UPLOADS_DIRECTORY) or ! is_writable($uploads['basedir'] . DIRECTORY_SEPARATOR . self::UPLOADS_DIRECTORY)) {
375 $this->showNoticeAndDisablePlugin(sprintf(__('Uploads folder %s must be writable', 'wp_all_export_plugin'), $uploads['basedir'] . DIRECTORY_SEPARATOR . self::UPLOADS_DIRECTORY));
376 }
377
378
379 self::$session = new PMXE_Handler();
380
381 $input = new PMXE_Input();
382 $page = strtolower($input->getpost('page', ''));
383
384 if (preg_match('%^' . preg_quote(str_replace('_', '-', self::PREFIX), '%') . '([\w-]+)$%', $page)) {
385 //$this->adminDispatcher($page, strtolower($input->getpost('action', 'index')));
386
387 $action = strtolower($input->getpost('action', 'index'));
388
389 // capitalize prefix and first letters of class name parts
390 $controllerName = preg_replace_callback('%(^' . preg_quote(self::PREFIX, '%') . '|_).%', array($this, "replace_callback"),str_replace('-', '_', $page));
391 $actionName = str_replace('-', '_', $action);
392 if (method_exists($controllerName, $actionName)) {
393
394 if ( ! get_current_user_id() or ! current_user_can(self::$capabilities)) {
395 // This nonce is not valid.
396 die( 'Security check' );
397
398 } else {
399
400 $this->_admin_current_screen = (object)array(
401 'id' => $controllerName,
402 'base' => $controllerName,
403 'action' => $actionName,
404 'is_ajax' => strpos($_SERVER["HTTP_ACCEPT"], 'json') !== false,
405 'is_network' => is_network_admin(),
406 'is_user' => is_user_admin(),
407 );
408 add_filter('current_screen', array($this, 'getAdminCurrentScreen'));
409 add_filter('admin_body_class',
410 function($admin_body_class) {
411 return $admin_body_class.' wpallexport-plugin';
412 }
413 );
414
415 $controller = new $controllerName();
416 if ( ! $controller instanceof PMXE_Controller_Admin) {
417 throw new Exception("Administration page `$page` matches to a wrong controller type.");
418 }
419
420 if($controller instanceof PMXE_Admin_Manage && ($action == 'update' || $action == 'template' || $action == 'options') && isset($_GET['id'])) {
421 $addons = new \Wpae\App\Service\Addons\AddonService();
422 $exportId = intval($_GET['id']);
423
424 $export = new \PMXE_Export_Record();
425 $export->getById($exportId);
426
427 $cpt = $export->options['cpt'];
428 if (!is_array($cpt)) {
429 $cpt = array($cpt);
430 }
431
432 if (
433 ((in_array('users', $cpt) || in_array('shop_customer', $cpt)) && !$addons->isUserAddonActive()) ||
434 ($export->options['export_type'] == 'advanced' && $export->options['wp_query_selector'] == 'wp_user_query' && !$addons->isUserAddonActive())
435 ) {
436 die(\__('The User Export Add-On Pro is required to run this export. You can download the add-on here: <a href="http://www.wpallimport.com/portal/" target="_blank">http://www.wpallimport.com/portal/</a>', \PMXE_Plugin::LANGUAGE_DOMAIN));
437 }
438 }
439
440
441 if ($this->_admin_current_screen->is_ajax) { // ajax request
442 $controller->$action();
443 do_action('wpallexport_action_after');
444 die(); // stop processing since we want to output only what controller is randered, nothing in addition
445 } elseif ( ! $controller->isInline) {
446 @ob_start();
447 $controller->$action();
448 self::$buffer = @ob_get_clean();
449 } else {
450 self::$buffer_callback = array($controller, $action);
451 }
452 }
453
454 } else { // redirect to dashboard if requested page and/or action don't exist
455 wp_redirect(admin_url()); die();
456 }
457
458 }
459 }
460
461
462 /**
463 * Dispatch shorttag: create corresponding controller instance and call its index method
464 * @param array $args Shortcode tag attributes
465 * @param string $content Shortcode tag content
466 * @param string $tag Shortcode tag name which is being dispatched
467 * @return string
468 * @throws Exception
469 */
470 public function shortcodeDispatcher($args, $content, $tag) {
471
472 $controllerName = self::PREFIX . preg_replace_callback('%(^|_).%', array($this, "replace_callback"), $tag);// capitalize first letters of class name parts and add prefix
473 $controller = new $controllerName();
474 if ( ! $controller instanceof PMXE_Controller) {
475 throw new Exception("Shortcode `$tag` matches to a wrong controller type.");
476 }
477 ob_start();
478 $controller->index($args, $content);
479 return ob_get_clean();
480 }
481
482 static $buffer = NULL;
483 static $buffer_callback = NULL;
484
485 /**
486 * Dispatch admin page: call corresponding controller based on get parameter `page`
487 * The method is called twice: 1st time as handler `parse_header` action and then as admin menu item handler
488 * @param string $page
489 * @param string $action
490 * @throws Exception
491 * @internal param $string [optional] $page When $page set to empty string ealier buffered content is outputted, otherwise controller is called based on $page value
492 */
493 public function adminDispatcher($page = '', $action = 'index') {
494 if ('' === $page) {
495 if ( ! is_null(self::$buffer)) {
496 echo '<div class="wrap">';
497 echo self::$buffer;
498 do_action('wpallexport_action_after');
499 echo '</div>';
500 } elseif ( ! is_null(self::$buffer_callback)) {
501 echo '<div class="wrap">';
502 call_user_func(self::$buffer_callback);
503 do_action('wpallexport_action_after');
504 echo '</div>';
505 } else {
506 throw new Exception('There is no previousely buffered content to display.');
507 }
508 }
509 }
510
511 public function replace_callback($matches){
512 return strtoupper($matches[0]);
513 }
514
515 protected $_admin_current_screen = NULL;
516 public function getAdminCurrentScreen()
517 {
518 return $this->_admin_current_screen;
519 }
520
521 /**
522 * Autoloader
523 * It's assumed class name consists of prefix folloed by its name which in turn corresponds to location of source file
524 * if `_` symbols replaced by directory path separator. File name consists of prefix folloed by last part in class name (i.e.
525 * symbols after last `_` in class name)
526 * When class has prefix it's source is looked in `models`, `controllers`, `shortcodes` folders, otherwise it looked in `core` or `library` folder
527 *
528 * @param string $className
529 * @return bool
530 */
531 public function autoload($className) {
532
533 $is_prefix = false;
534 $filePath = str_replace('_', '/', preg_replace('%^' . preg_quote(self::PREFIX, '%') . '%', '', strtolower($className), 1, $is_prefix)) . '.php';
535 if ( ! $is_prefix) { // also check file with original letter case
536 $filePathAlt = $className . '.php';
537 }
538 foreach ($is_prefix ? array('models', 'controllers', 'shortcodes', 'classes') : array('libraries') as $subdir) {
539 $path = self::ROOT_DIR . '/' . $subdir . '/' . $filePath;
540 if (is_file($path)) {
541 require_once $path;
542 return TRUE;
543 }
544 if ( ! $is_prefix) {
545 $pathAlt = self::ROOT_DIR . '/' . $subdir . '/' . $filePathAlt;
546 if(strpos($className, '_') !== false) {
547 $pathAlt = $this->lreplace('_',DIRECTORY_SEPARATOR, $pathAlt);
548 }
549 if (is_file($pathAlt)) {
550 require_once $pathAlt;
551 return TRUE;
552 }
553 }
554 }
555 if($className === 'CdataStrategyFactory') {
556 //TODO: Move this to a namespace
557 require_once (self::ROOT_DIR . '/classes/CdataStrategyFactory.php');
558 }
559
560
561 if(strpos($className, '\\') !== false){
562
563 // project-specific namespace prefix
564 $prefix = 'Wpae\\';
565
566 // base directory for the namespace prefix
567 $base_dir = self::ROOT_DIR . '/src/';
568
569 // does the class use the namespace prefix?
570 $len = strlen($prefix);
571 if (strncmp($prefix, $className, $len) !== 0) {
572 // no, move to the next registered autoloader
573 return;
574 }
575
576 // get the relative class name
577 $relative_class = substr($className, $len);
578
579 // replace the namespace prefix with the base directory, replace namespace
580 // separators with directory separators in the relative class name, append
581 // with .php
582 $file = $base_dir . str_replace('\\', '/', $relative_class) . '.php';
583
584 // if the file exists, require it
585 if (file_exists($file)) {
586 require_once $file;
587 }
588 }
589
590 return FALSE;
591 }
592
593 /**
594 * Get plugin option
595 * @param string [optional] $option Parameter to return, all array of options is returned if not set
596 * @return mixed
597 * @throws Exception
598 */
599 public function getOption($option = NULL) {
600 $options = apply_filters('wp_all_export_config_options', $this->options);
601 if (is_null($option)) {
602 return $options;
603 } else if (isset($options[$option])) {
604 return $options[$option];
605 } else {
606 throw new Exception("Specified option is not defined for the plugin");
607 }
608 }
609
610 /**
611 * Update plugin option value
612 * @param string $option Parameter name or array of name => value pairs
613 * @param null $value
614 * @return array
615 * @throws Exception
616 * @internal param $mixed [optional] $value New value for the option, if not set than 1st parameter is supposed to be array of name => value pairs
617 */
618 public function updateOption($option, $value = NULL) {
619 is_null($value) or $option = array($option => $value);
620 if (array_diff_key($option, $this->options)) {
621 throw new Exception("Specified option is not defined for the plugin");
622 }
623 $this->options = $option + $this->options;
624 update_option(get_class($this) . '_Options', $this->options);
625
626 return $this->options;
627 }
628
629 /**
630 * Plugin activation logic
631 */
632 public function activation() {
633 // uncaught exception doesn't prevent plugin from being activated, therefore replace it with fatal error so it does
634 set_exception_handler(function($e) {trigger_error($e->getMessage(), E_USER_ERROR); });
635
636 // create plugin options
637 $option_name = get_class($this) . '_Options';
638 $options_default = PMXE_Config::createFromFile(self::ROOT_DIR . '/config/options.php')->toArray();
639 $wpai_options = get_option($option_name, false);
640 if ( ! $wpai_options ) update_option($option_name, $options_default);
641
642 // create/update required database tables
643 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
644 require self::ROOT_DIR . '/schema.php';
645 global $wpdb;
646
647 if (function_exists('is_multisite') && is_multisite()) {
648 // check if it is a network activation - if so, run the activation function for each blog id
649 if (isset($_GET['networkwide']) && ($_GET['networkwide'] == 1)) {
650 $old_blog = $wpdb->blogid;
651 // Get all blog ids
652 $blogids = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
653 foreach ($blogids as $blog_id) {
654 switch_to_blog($blog_id);
655 require self::ROOT_DIR . '/schema.php';
656 dbDelta($plugin_queries);
657 }
658 switch_to_blog($old_blog);
659 return;
660 }
661 }
662
663 dbDelta($plugin_queries);
664
665 }
666
667 /**
668 * Load Localisation files.
669 *
670 * Note: the first-loaded translation file overrides any following ones if the same translation is present
671 *
672 * @access public
673 * @return void
674 */
675 public function load_plugin_textdomain() {
676
677 $locale = apply_filters( 'plugin_locale', get_locale(), 'wp_all_export_plugin' );
678
679 load_plugin_textdomain( 'wp_all_export_plugin', false, dirname( plugin_basename( __FILE__ ) ) . "/i18n/languages" );
680 }
681
682 public function fix_db_schema(){
683
684 global $wpdb;
685 $installed_ver = get_option( "wp_all_export_db_version" );
686
687 if ( $installed_ver == PMXE_VERSION ) return true;
688
689 if ( ! empty($wpdb->charset))
690 $charset_collate = "DEFAULT CHARACTER SET $wpdb->charset";
691 if ( ! empty($wpdb->collate))
692 $charset_collate .= " COLLATE $wpdb->collate";
693
694 $table_prefix = $this->getTablePrefix();
695
696 $wpdb->query("CREATE TABLE IF NOT EXISTS {$table_prefix}templates (
697 id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
698 name VARCHAR(200) NOT NULL DEFAULT '',
699 options LONGTEXT,
700 PRIMARY KEY (id)
701 ) $charset_collate;");
702
703 $wpdb->query("CREATE TABLE IF NOT EXISTS {$table_prefix}posts (
704 id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
705 post_id BIGINT(20) UNSIGNED NOT NULL,
706 export_id BIGINT(20) UNSIGNED NOT NULL,
707 iteration BIGINT(20) NOT NULL DEFAULT 0,
708 PRIMARY KEY (id)
709 ) $charset_collate;");
710
711 $googleCatsTableExists = $wpdb->query("SHOW TABLES LIKE '{$table_prefix}google_cats'");
712 if(!$googleCatsTableExists) {
713 require_once self::ROOT_DIR . '/schema.php';
714 $wpdb->query($googleCatsQueryCreate);
715 $wpdb->query($googleCatsQueryData);
716 }
717
718 $table = $this->getTablePrefix() . 'exports';
719 $tablefields = $wpdb->get_results("DESCRIBE {$table};");
720 $iteration = false;
721 $parent_id = false;
722 $export_post_type = false;
723
724 // Check if field exists
725 foreach ($tablefields as $tablefield) {
726 if ('iteration' == $tablefield->Field) $iteration = true;
727 if ('parent_id' == $tablefield->Field) $parent_id = true;
728 if ('export_post_type' == $tablefield->Field) $export_post_type = true;
729 }
730
731 if ( ! $iteration ){
732 $wpdb->query("ALTER TABLE {$table} ADD `iteration` BIGINT(20) NOT NULL DEFAULT 0;");
733 }
734 if ( ! $parent_id ){
735 $wpdb->query("ALTER TABLE {$table} ADD `parent_id` BIGINT(20) NOT NULL DEFAULT 0;");
736 }
737 if ( ! $export_post_type ){
738 $wpdb->query("ALTER TABLE {$table} ADD `export_post_type` TEXT NOT NULL DEFAULT '';");
739 }
740
741 update_option( "wp_all_export_db_version", PMXE_VERSION );
742 }
743
744 /**
745 * Determine is current export was created before current version
746 */
747 public static function isExistingExport( $checkVersion = false ){
748
749 $input = new PMXE_Input();
750 $export_id = $input->get('id', 0);
751
752 if (empty($export_id)) $export_id = $input->get('export_id', 0);
753
754 // ID not found means this is new export
755 if (empty($export_id)) return false;
756
757 if ( ! $checkVersion ) $checkVersion = PMXE_VERSION;
758
759 $export = new PMXE_Export_Record();
760 $export->getById($export_id);
761 if ( ! $export->isEmpty() && (empty($export->options['created_at_version']) || version_compare($export->options['created_at_version'], $checkVersion) < 0 )){
762 return true;
763 }
764
765 return false;
766 }
767
768 /**
769 * Determine is current export is first time running
770 */
771 public static function isNewExport(){
772
773 $input = new PMXE_Input();
774 $export_id = $input->get('id', 0);
775
776 if (empty($export_id)) $export_id = $input->get('export_id', 0);
777
778 if (empty($export_id)) $export_id = XmlExportEngine::$exportID;
779
780 // ID not found means this is new export
781 if (empty($export_id)) return true;
782
783 $export = new PMXE_Export_Record();
784 $export->getById($export_id);
785 if ( ! $export->isEmpty() && ! $export->iteration ){
786 return true;
787 }
788
789 return false;
790 }
791
792 /**
793 * Method returns default import options, main utility of the method is to avoid warnings when new
794 * option is introduced but already registered imports don't have it
795 */
796 public static function get_default_import_options() {
797 return array(
798 'cpt' => array(),
799 'whereclause' => '',
800 'joinclause' => '',
801 'filter_rules_hierarhy' => '',
802 'product_matching_mode' => 'parent',
803 'order_item_per_row' => 1,
804 'order_item_fill_empty_columns' => 1,
805 'filepath' => '',
806 'current_filepath' => '',
807 'bundlepath' => '',
808 'export_type' => 'specific',
809 'wp_query' => '',
810 'wp_query_selector' => 'wp_query',
811 'is_user_export' => false,
812 'is_comment_export' => false,
813 'export_to' => 'csv',
814 'export_to_sheet' => 'csv',
815 'delimiter' => ',',
816 'encoding' => 'UTF-8',
817 'is_generate_templates' => 1,
818 'is_generate_import' => 1,
819 'import_id' => 0,
820 'template_name' => '',
821 'is_scheduled' => 0,
822 'scheduled_period' => '',
823 'scheduled_email' => '',
824 'cc_label' => array(),
825 'cc_type' => array(),
826 'cc_value' => array(),
827 'cc_name' => array(),
828 'cc_php' => array(),
829 'cc_code' => array(),
830 'cc_sql' => array(),
831 'cc_options' => array(),
832 'cc_settings' => array(),
833 'friendly_name' => '',
834 'fields' => array('default', 'other', 'cf', 'cats'),
835 'ids' => array(),
836 'rules' => array(),
837 'records_per_iteration' => 50,
838 'include_bom' => 0,
839 'include_functions' => 1,
840 'split_large_exports' => 0,
841 'split_large_exports_count' => 10000,
842 'split_files_list' => array(),
843 'main_xml_tag' => 'data',
844 'record_xml_tag' => 'post',
845 'save_template_as' => 0,
846 'name' => '',
847 'export_only_new_stuff' => 0,
848 'export_only_modified_stuff' => 0,
849 'creata_a_new_export_file' => 0,
850 'attachment_list' => array(),
851 'order_include_poducts' => 0,
852 'order_include_all_poducts' => 0,
853 'order_include_coupons' => 0,
854 'order_include_all_coupons' => 0,
855 'order_include_customers' => 0,
856 'order_include_all_customers' => 0,
857 'migration' => '',
858 'xml_template_type' => 'simple',
859 'custom_xml_template' => '',
860 'custom_xml_template_header' => '',
861 'custom_xml_template_loop' => '',
862 'custom_xml_template_footer' => '',
863 'custom_xml_template_options' => array(),
864 'custom_xml_cdata_logic' => 'auto',
865 'show_cdata_in_preview' => 0,
866 'taxonomy_to_export' => '',
867 'created_at_version' => '',
868 'export_variations' => XmlExportEngine::VARIABLE_PRODUCTS_EXPORT_PARENT_AND_VARIATION,
869 'export_variations_title' => XmlExportEngine::VARIATION_USE_PARENT_TITLE,
870 'include_header_row' => 1,
871 'wpml_lang' => 'all',
872 'enable_export_scheduling' => 'false',
873 'scheduling_enable' => false,
874 'scheduling_weekly_days' => '',
875 'scheduling_run_on' => 'weekly',
876 'scheduling_monthly_day' => '',
877 'scheduling_times' => array(),
878 'scheduling_timezone' => 'UTC'
879 );
880 }
881
882 public static function is_ajax(){
883 return (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') ? true : false ;
884 }
885
886 public static function encode( $value ){
887 return base64_encode(md5(AUTH_SALT) . $value . md5(md5(AUTH_SALT)));
888 }
889
890 public static function decode( $encoded ){
891 return preg_match('/^[a-f0-9]{32}$/', $encoded) ? $encoded : str_replace(array(md5(AUTH_SALT), md5(md5(AUTH_SALT))), '', base64_decode($encoded));
892 }
893
894
895 /**
896 * Replace last occurence of string
897 * Used in autoloader, that's not muved in string class
898 *
899 * @param $search
900 * @param $replace
901 * @param $subject
902 * @return mixed
903 */
904 private function lreplace($search, $replace, $subject){
905 $pos = strrpos($subject, $search);
906 if($pos !== false){
907 $subject = substr_replace($subject, $replace, $pos, strlen($search));
908 }
909 return $subject;
910 }
911 }
912
913 PMXE_Plugin::getInstance();
914
915 // Include the api front controller
916 include_once('wpae_api.php');
917
918 }
919
920