PluginProbe ʕ •ᴥ•ʔ
WP All Export – Drag & Drop Export to Any Custom CSV, XML & Excel / 1.3.6
WP All Export – Drag & Drop Export to Any Custom CSV, XML & Excel v1.3.6
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 4 years ago classes 4 years ago config 6 years ago controllers 4 years ago dist 4 years ago filters 7 years ago helpers 4 years ago history 12 years ago i18n 8 years ago libraries 4 years ago models 4 years ago sessions 10 years ago shortcodes 10 years ago src 4 years ago static 4 years ago views 4 years ago banner-772x250.png 12 years ago readme.txt 4 years ago schema.php 7 years ago screenshot-1.png 10 years ago screenshot-2.png 10 years ago wp-all-export.php 4 years ago wpae_api.php 9 years ago
wp-all-export.php
1029 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.3.6
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(esc_html__('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.3.6');
63
64 define('PMXE_ASSETS_VERSION', '-1.0.2');
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 /** @var \Wpae\App\Service\Addons\AddonService */
161 private $addons;
162
163 public static $cache_key = '';
164
165 /**
166 * Class constructor containing dispatching logic
167 * @param string $rootDir Plugin root dir
168 * @param string $pluginFilePath Plugin main file
169 */
170 protected function __construct() {
171
172 require_once (self::ROOT_DIR . '/classes/installer.php');
173
174 $installer = new PMXE_Installer();
175 $installer->checkActivationConditions();
176
177 $plugin_basename = plugin_basename( __FILE__ );
178
179 self::$cache_key = md5( 'edd_plugin_' . sanitize_key( $plugin_basename ) . '_version_info' );
180
181 // uncaught exception doesn't prevent plugin from being activated, therefore replace it with fatal error so it does
182 //set_exception_handler(create_function('$e', 'trigger_error($e->getMessage(), E_USER_ERROR);'));
183
184 // register autoloading method
185 spl_autoload_register(array($this, 'autoload'));
186
187 // register helpers
188 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) {
189 require_once $filePath;
190 }
191
192 $this->addons = new \Wpae\App\Service\Addons\AddonService();
193
194 // init plugin options
195 $option_name = get_class($this) . '_Options';
196 $options_default = PMXE_Config::createFromFile(self::ROOT_DIR . '/config/options.php')->toArray();
197 $current_options = get_option($option_name, array());
198 $this->options = array_intersect_key($current_options, $options_default) + $options_default;
199 $this->options = array_intersect_key($options_default, array_flip(array('info_api_url'))) + $this->options; // make sure hidden options apply upon plugin reactivation
200 if ('' == $this->options['cron_job_key']) $this->options['cron_job_key'] = wp_all_export_url_title(wp_all_export_rand_char(12));
201
202 if ($current_options !== $this->options) {
203 update_option($option_name, $this->options);
204 }
205 register_activation_hook(self::FILE, array($this, 'activation'));
206
207 // register action handlers
208 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) {
209 require_once $filePath;
210 $function = $actionName = basename($filePath, '.php');
211 if (preg_match('%^(.+?)[_-](\d+)$%', $actionName, $m)) {
212 $actionName = $m[1];
213 $priority = intval($m[2]);
214 } else {
215 $priority = 10;
216 }
217 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)
218 }
219
220 // register filter handlers
221 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) {
222 require_once $filePath;
223 $function = $actionName = basename($filePath, '.php');
224 if (preg_match('%^(.+?)[_-](\d+)$%', $actionName, $m)) {
225 $actionName = $m[1];
226 $priority = intval($m[2]);
227 } else {
228 $priority = 10;
229 }
230 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)
231 }
232
233 // register shortcodes handlers
234 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) {
235 $tag = strtolower(str_replace('/', '_', preg_replace('%^' . preg_quote(self::ROOT_DIR . '/shortcodes/', '%') . '|\.php$%', '', $filePath)));
236 add_shortcode($tag, array($this, 'shortcodeDispatcher'));
237 }
238
239 // register admin page pre-dispatcher
240 add_action('admin_init', array($this, 'adminInit'), 11);
241 add_action('admin_init', array($this, 'fix_db_schema'), 10);
242 add_action('init', array($this, 'init'), 10);
243 }
244
245 /**
246 * Return singletone instance
247 * @return PMXE_Plugin
248 */
249 static public function getInstance() {
250 if (self::$instance == NULL) {
251 self::$instance = new self();
252 }
253 return self::$instance;
254 }
255
256 static public function getSchedulingName(){
257 return 'Automatic Scheduling';
258 }
259
260 static public function hasActiveSchedulingLicense() {
261
262 if(is_null(self::$hasActiveSchedulingLicense)) {
263 $scheduling = \Wpae\Scheduling\Scheduling::create();
264 $hasActiveSchedulingLicense = $scheduling->checkLicense();
265 self::$hasActiveSchedulingLicense = $hasActiveSchedulingLicense;
266 }
267
268 return self::$hasActiveSchedulingLicense;
269 }
270
271 /**
272 * Common logic for requestin plugin info fields
273 */
274 public function __call($method, $args) {
275 if (preg_match('%^get(.+)%i', $method, $mtch)) {
276 $info = get_plugin_data(self::FILE);
277 if (isset($info[$mtch[1]])) {
278 return $info[$mtch[1]];
279 }
280 }
281 throw new Exception("Requested method " . get_class($this) . "::$method doesn't exist.");
282 }
283
284 /**
285 * Get path to plagin dir relative to wordpress root
286 * @param bool[optional] $noForwardSlash Whether path should be returned withot forwarding slash
287 * @return string
288 */
289 public function getRelativePath($noForwardSlash = false) {
290 $wp_root = str_replace('\\', '/', ABSPATH);
291 return ($noForwardSlash ? '' : '/') . str_replace($wp_root, '', self::ROOT_DIR);
292 }
293
294 /**
295 * Check whether plugin is activated as network one
296 * @return bool
297 */
298 public function isNetwork() {
299 if ( !is_multisite() )
300 return false;
301
302 $plugins = get_site_option('active_sitewide_plugins');
303 if (isset($plugins[plugin_basename(self::FILE)]))
304 return true;
305
306 return false;
307 }
308
309 /**
310 * Check whether permalinks is enabled
311 * @return bool
312 */
313 public function isPermalinks() {
314 global $wp_rewrite;
315
316 return $wp_rewrite->using_permalinks();
317 }
318
319 /**
320 * Return prefix for plugin database tables
321 * @return string
322 */
323 public function getTablePrefix() {
324 global $wpdb;
325
326 //return ($this->isNetwork() ? $wpdb->base_prefix : $wpdb->prefix) . self::PREFIX;
327 return $wpdb->prefix . self::PREFIX;
328 }
329
330 /**
331 * Return prefix for wordpress database tables
332 * @return string
333 */
334 public function getWPPrefix() {
335 global $wpdb;
336 return ($this->isNetwork()) ? $wpdb->base_prefix : $wpdb->prefix;
337 }
338
339 public function init(){
340 $this->load_plugin_textdomain();
341 }
342
343 public function showNoticeAndDisablePlugin($message){
344 $this->showNotice($message);
345 deactivate_plugins( str_replace('\\', '/', dirname(__FILE__)) . '/wp-all-export.php');
346 }
347
348 public function showNotice($message)
349 {
350 $notice = new \Wpae\WordPress\AdminErrorNotice($message);
351 $notice->render();
352 }
353
354 public function showDismissibleNotice($message, $noticeId)
355 {
356 $notice = new \Wpae\WordPress\SitewideAdminDismissibleNotice($message, $noticeId);
357 if (!$notice->isDismissed()) {
358 $notice->render();
359 }
360 }
361
362 /**
363 * pre-dispatching logic for admin page controllers
364 */
365 public function adminInit() {
366
367 $addons_not_included = get_option('wp_all_export_free_addons_not_included',false);
368
369 if ( !get_option('wp_all_export_free_addons_not_included',false) && current_user_can( 'manage_options' ) && (!XmlExportEngine::get_addons_service()->isAcfAddonActive() || !XmlExportEngine::get_addons_service()->isWooCommerceAddonActive())){
370
371 $website = get_site_url();
372 $salt = "datacaptain";
373 $hash = base64_encode( $website . $salt );
374 $product = "wpae-free-upgrade";
375
376 $wpae_add_on_discount_link = "https://www.wpallimport.com?discount-site=" . urlencode( $website ) . "&discount-hash=" . $hash . "&discount-item=" . $product;
377
378 $this->showDismissibleNotice( '<h1 style="padding-top:0">Important Notice Regarding WP All Export</h1><br><strong>WP All Export now requires paid add-ons to export ACF and WooCommerce data.<br/>We are providing these Pro add-ons to everyone who was using WP All Export before the change, free of charge.
379 <br/><br/>
380 <a href="'.$wpae_add_on_discount_link.'&utm_source=export-plugin-free&utm_medium=wpae-addons-notice&utm_campaign=free-export-acf-woo-add-ons
381 " target="_blank">Click here to download your free Pro add-ons.</a></strong>', 'wpae_free_export_addons_notice' );
382 }
383
384 // create history folder
385 $uploads = wp_upload_dir();
386
387 $wpallimportDirs = array( WP_ALL_EXPORT_UPLOADS_BASE_DIRECTORY, self::TEMP_DIRECTORY, self::UPLOADS_DIRECTORY, self::CRON_DIRECTORY);
388
389 foreach ($wpallimportDirs as $destination) {
390
391 $dir = $uploads['basedir'] . DIRECTORY_SEPARATOR . $destination;
392
393 if ( !is_dir($dir)) wp_mkdir_p($dir);
394
395 if ( ! @file_exists($dir . DIRECTORY_SEPARATOR . 'index.php') ) @touch( $dir . DIRECTORY_SEPARATOR . 'index.php' );
396
397 }
398
399 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)) {
400 $this->showNoticeAndDisablePlugin(sprintf(esc_html__('Uploads folder %s must be writable', 'wp_all_export_plugin'), $uploads['basedir'] . DIRECTORY_SEPARATOR . WP_ALL_EXPORT_UPLOADS_BASE_DIRECTORY));
401 }
402
403 if ( ! is_dir($uploads['basedir'] . DIRECTORY_SEPARATOR . self::UPLOADS_DIRECTORY) or ! is_writable($uploads['basedir'] . DIRECTORY_SEPARATOR . self::UPLOADS_DIRECTORY)) {
404 $this->showNoticeAndDisablePlugin(sprintf(esc_html__('Uploads folder %s must be writable', 'wp_all_export_plugin'), $uploads['basedir'] . DIRECTORY_SEPARATOR . self::UPLOADS_DIRECTORY));
405 }
406
407 if (!$addons_not_included && $this->addons->userExportsExistAndAddonNotInstalled() && current_user_can('manage_options')) {
408 $this->showDismissibleNotice(__('<strong style="font-size:16px">A Configured Export Requires the User Export Add-On</strong><p>Your User exports will not be able to run until you install the User Export Add-On. That add-on is available from <a href="https://wordpress.org/plugins/export-wp-users-xml-csv/" target="_blank">wordpress.org</a>.</p>', PMXE_Plugin::LANGUAGE_DOMAIN), 'wpae_user_addon_not_installed_notice');
409 }
410
411 if (!$addons_not_included && $this->addons->wooCommerceExportsExistAndAddonNotInstalled() && current_user_can('manage_options') && \class_exists('WooCommerce')) {
412 $this->showDismissibleNotice(__('<strong style="font-size:16px">A Configured Export Requires the WooCommerce Export Add-On Pro</strong><p>Your Products, Orders, and Coupons exports will not be able to run until you install the WooCommerce Export Add-On Pro. That add-on is available to those who were using WP All Export Free before this requirement.</p>', PMXE_Plugin::LANGUAGE_DOMAIN)
413 . '<p><a class="button button-primary" href="https://wpallimport.com/portal/downloads" target="_blank">' . __('Download Add-On', PMXE_Plugin::LANGUAGE_DOMAIN) . '</a></p>', 'wpae_woocommerce_addon_not_installed_notice');
414 }
415
416 if (!$addons_not_included && $this->addons->acfExportsExistAndNotInstalled() && current_user_can('manage_options')) {
417 $this->showDismissibleNotice(__('<strong style="font-size:16px">A Configured Export Requires the ACF Export Add-On Pro</strong><p>Exports that contain ACF fields will not be able to run until you install the ACF Export Add-On Pro. That add-on is available to those who were using WP All Export Free before this requirement.</p>', PMXE_Plugin::LANGUAGE_DOMAIN)
418 . '<p><a class="button button-primary" href="https://wpallimport.com/portal/downloads" target="_blank">' . __('Download Add-On', PMXE_Plugin::LANGUAGE_DOMAIN) . '</a></p>', 'wpae_acf_addon_not_installed_notice');
419 }
420
421 self::$session = new PMXE_Handler();
422
423 $input = new PMXE_Input();
424 $page = strtolower($input->getpost('page', ''));
425
426 if (preg_match('%^' . preg_quote(str_replace('_', '-', self::PREFIX), '%') . '([\w-]+)$%', $page)) {
427
428 $action = strtolower($input->getpost('action', 'index'));
429
430 // capitalize prefix and first letters of class name parts
431 $controllerName = preg_replace_callback('%(^' . preg_quote(self::PREFIX, '%') . '|_).%', array($this, "replace_callback"),str_replace('-', '_', $page));
432 $actionName = str_replace('-', '_', $action);
433 if (method_exists($controllerName, $actionName)) {
434
435 if ( ! get_current_user_id() or ! current_user_can(self::$capabilities)) {
436 // This nonce is not valid.
437 die( 'Security check' );
438
439 } else {
440
441 $this->_admin_current_screen = (object)array(
442 'id' => $controllerName,
443 'base' => $controllerName,
444 'action' => $actionName,
445 'is_ajax' => strpos($_SERVER["HTTP_ACCEPT"], 'json') !== false,
446 'is_network' => is_network_admin(),
447 'is_user' => is_user_admin(),
448 );
449 add_filter('current_screen', array($this, 'getAdminCurrentScreen'));
450 add_filter('admin_body_class',
451 function($admin_body_class) {
452 return $admin_body_class.' wpallexport-plugin';
453 }
454 );
455
456 $controller = new $controllerName();
457 if ( ! $controller instanceof PMXE_Controller_Admin) {
458 throw new Exception("Administration page `$page` matches to a wrong controller type.");
459 }
460
461 $reviewsUI = new \Wpae\Reviews\ReviewsUI();
462
463 add_action('admin_notices', [$reviewsUI, 'render']);
464
465 if($controller instanceof PMXE_Admin_Manage && ($action == 'update' || $action == 'template' || $action == 'options') && isset($_GET['id'])) {
466 $addons = new \Wpae\App\Service\Addons\AddonService();
467 $exportId = intval($_GET['id']);
468
469 $export = new \PMXE_Export_Record();
470 $export->getById($exportId);
471
472 $cpt = $export->options['cpt'];
473 if (!is_array($cpt)) {
474 $cpt = array($cpt);
475 }
476
477 if(isset($export->options['export_type']) && $export->options['export_type'] === 'advanced') {
478
479 if(!XmlExportEngine::get_addons_service()->isWooCommerceAddonActive() && strpos($export->options['wp_query'], 'product') !== false && \class_exists('WooCommerce')) {
480 die(\__('The WooCommerce Export Add-On Pro is required to run this export. If you already own it, you can download the add-on here: <a href="http://www.wpallimport.com/portal/downloads" target="_blank">http://www.wpallimport.com/portal/downloads</a>', \PMXE_Plugin::LANGUAGE_DOMAIN));
481 }
482 else if( (!XmlExportEngine::get_addons_service()->isWooCommerceAddonActive() || !XmlExportEngine::get_addons_service()->isWooCommerceOrderAddonActive() ) && strpos($export->options['wp_query'], 'shop_order') !== false) {
483 die(\__('The WooCommerce Export Add-On Pro is required to run this export. If you already own it, you can download the add-on here: <a href="http://www.wpallimport.com/portal/downloads" target="_blank">http://www.wpallimport.com/portal/downloads</a>', \PMXE_Plugin::LANGUAGE_DOMAIN));
484 }
485 else if(!XmlExportEngine::get_addons_service()->isWooCommerceAddonActive() && strpos($export->options['wp_query'], 'shop_coupon') !== false) {
486 die(\__('The WooCommerce Export Add-On Pro is required to run this export. If you already own it, you can download the add-on here: <a href="http://www.wpallimport.com/portal/downloads" target="_blank">http://www.wpallimport.com/portal/downloads</a>', \PMXE_Plugin::LANGUAGE_DOMAIN));
487 }
488 }
489
490 if (
491 ((in_array('users', $cpt) || in_array('shop_customer', $cpt)) && !$addons->isUserAddonActive()) ||
492 ($export->options['export_type'] == 'advanced' && $export->options['wp_query_selector'] == 'wp_user_query' && !$addons->isUserAddonActive())
493 ) {
494 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));
495 }
496
497 if (
498 (
499 (
500 ( in_array( 'product', $cpt ) && \class_exists('WooCommerce') && ! XmlExportEngine::get_addons_service()->isWooCommerceProductAddonActive() ) ||
501 ( in_array( 'shop_order', $cpt ) && ! XmlExportEngine::get_addons_service()->isWooCommerceOrderAddonActive() ) ||
502 in_array( 'shop_review', $cpt ) ||
503 in_array( 'shop_coupon', $cpt )
504 ) && ! $addons->isWooCommerceAddonActive()
505 ) ||
506 ( $export->options['export_type'] == 'advanced' && $export->options['wp_query_selector'] == 'wp_user_query' && ! $addons->isUserAddonActive() )
507 ) {
508 die( \__( 'The WooCommerce 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 ) );
509 }
510
511 if(in_array('acf', $export->options['cc_type']) && !$addons->isAcfAddonActive()) {
512 die(\__('The ACF 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));
513 }
514 }
515
516
517 if ($this->_admin_current_screen->is_ajax) { // ajax request
518 $controller->$action();
519 do_action('wpallexport_action_after');
520 die(); // stop processing since we want to output only what controller is randered, nothing in addition
521 } elseif ( ! $controller->isInline) {
522 @ob_start();
523 $controller->$action();
524 self::$buffer = @ob_get_clean();
525 } else {
526 self::$buffer_callback = array($controller, $action);
527 }
528 }
529
530 } else { // redirect to dashboard if requested page and/or action don't exist
531 wp_redirect(admin_url()); die();
532 }
533
534 }
535 }
536
537
538 /**
539 * Dispatch shorttag: create corresponding controller instance and call its index method
540 * @param array $args Shortcode tag attributes
541 * @param string $content Shortcode tag content
542 * @param string $tag Shortcode tag name which is being dispatched
543 * @return string
544 * @throws Exception
545 */
546 public function shortcodeDispatcher($args, $content, $tag) {
547
548 $controllerName = self::PREFIX . preg_replace_callback('%(^|_).%', array($this, "replace_callback"), $tag);// capitalize first letters of class name parts and add prefix
549 $controller = new $controllerName();
550 if ( ! $controller instanceof PMXE_Controller) {
551 throw new Exception("Shortcode `$tag` matches to a wrong controller type.");
552 }
553 ob_start();
554 $controller->index($args, $content);
555 return ob_get_clean();
556 }
557
558 static $buffer = NULL;
559 static $buffer_callback = NULL;
560
561 /**
562 * Dispatch admin page: call corresponding controller based on get parameter `page`
563 * The method is called twice: 1st time as handler `parse_header` action and then as admin menu item handler
564 * @param string $page
565 * @param string $action
566 * @throws Exception
567 * @internal param $string [optional] $page When $page set to empty string ealier buffered content is outputted, otherwise controller is called based on $page value
568 */
569 public function adminDispatcher($page = '', $action = 'index') {
570 if ('' === $page) {
571 if ( ! is_null(self::$buffer)) {
572 echo '<div class="wrap">';
573 // Contents are sanitized at a lower level
574 echo self::$buffer;
575 do_action('wpallexport_action_after');
576 echo '</div>';
577 } elseif ( ! is_null(self::$buffer_callback)) {
578 echo '<div class="wrap">';
579 call_user_func(self::$buffer_callback);
580 do_action('wpallexport_action_after');
581 echo '</div>';
582 } else {
583 throw new Exception('There is no previousely buffered content to display.');
584 }
585 }
586 }
587
588 public function replace_callback($matches){
589 return strtoupper($matches[0]);
590 }
591
592 protected $_admin_current_screen = NULL;
593 public function getAdminCurrentScreen()
594 {
595 return $this->_admin_current_screen;
596 }
597
598 /**
599 * Autoloader
600 * It's assumed class name consists of prefix folloed by its name which in turn corresponds to location of source file
601 * if `_` symbols replaced by directory path separator. File name consists of prefix folloed by last part in class name (i.e.
602 * symbols after last `_` in class name)
603 * When class has prefix it's source is looked in `models`, `controllers`, `shortcodes` folders, otherwise it looked in `core` or `library` folder
604 *
605 * @param string $className
606 * @return bool
607 */
608 public function autoload($className) {
609
610 $is_prefix = false;
611 $filePath = str_replace('_', '/', preg_replace('%^' . preg_quote(self::PREFIX, '%') . '%', '', strtolower($className), 1, $is_prefix)) . '.php';
612 if ( ! $is_prefix) { // also check file with original letter case
613 $filePathAlt = $className . '.php';
614 }
615 foreach ($is_prefix ? array('models', 'controllers', 'shortcodes', 'classes') : array('libraries') as $subdir) {
616 $path = self::ROOT_DIR . '/' . $subdir . '/' . $filePath;
617 if (is_file($path)) {
618 require_once $path;
619 return TRUE;
620 }
621 if (!$is_prefix) {
622 if (strpos($className, '_') !== false) {
623 $filePathAlt = $this->lreplace('_', DIRECTORY_SEPARATOR, $filePathAlt);
624 }
625
626 $pathAlt = self::ROOT_DIR . DIRECTORY_SEPARATOR . $subdir . DIRECTORY_SEPARATOR . $filePathAlt;
627
628 if (is_file($pathAlt)) {
629 require_once $pathAlt;
630 return TRUE;
631 }
632 }
633 }
634 if($className === 'CdataStrategyFactory') {
635 //TODO: Move this to a namespace
636 require_once (self::ROOT_DIR . '/classes/CdataStrategyFactory.php');
637 }
638
639
640 if(strpos($className, '\\') !== false){
641
642 // project-specific namespace prefix
643 $prefix = 'Wpae\\';
644
645 // base directory for the namespace prefix
646 $base_dir = self::ROOT_DIR . '/src/';
647
648 // does the class use the namespace prefix?
649 $len = strlen($prefix);
650 if (strncmp($prefix, $className, $len) !== 0) {
651 // no, move to the next registered autoloader
652 return;
653 }
654
655 // get the relative class name
656 $relative_class = substr($className, $len);
657
658 // replace the namespace prefix with the base directory, replace namespace
659 // separators with directory separators in the relative class name, append
660 // with .php
661 $file = $base_dir . str_replace('\\', '/', $relative_class) . '.php';
662
663 // if the file exists, require it
664 if (file_exists($file)) {
665 require_once $file;
666 }
667 }
668
669 return FALSE;
670 }
671
672 /**
673 * Get plugin option
674 * @param string [optional] $option Parameter to return, all array of options is returned if not set
675 * @return mixed
676 * @throws Exception
677 */
678 public function getOption($option = NULL) {
679 $options = apply_filters('wp_all_export_config_options', $this->options);
680 if (is_null($option)) {
681 return $options;
682 } else if (isset($options[$option])) {
683 return $options[$option];
684 } else {
685 throw new Exception("Specified option is not defined for the plugin");
686 }
687 }
688
689 /**
690 * Update plugin option value
691 * @param string $option Parameter name or array of name => value pairs
692 * @param null $value
693 * @return array
694 * @throws Exception
695 * @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
696 */
697 public function updateOption($option, $value = NULL) {
698 is_null($value) or $option = array($option => $value);
699 if (array_diff_key($option, $this->options)) {
700 throw new Exception("Specified option is not defined for the plugin");
701 }
702 $this->options = $option + $this->options;
703 update_option(get_class($this) . '_Options', $this->options);
704
705 return $this->options;
706 }
707
708 /**
709 * Plugin activation logic
710 */
711 public function activation() {
712 // uncaught exception doesn't prevent plugin from being activated, therefore replace it with fatal error so it does
713 set_exception_handler(function($e) {trigger_error($e->getMessage(), E_USER_ERROR); });
714
715 // create plugin options
716 $option_name = get_class($this) . '_Options';
717 $options_default = PMXE_Config::createFromFile(self::ROOT_DIR . '/config/options.php')->toArray();
718 $wpai_options = get_option($option_name, false);
719 if ( ! $wpai_options ) update_option($option_name, $options_default);
720
721 // create/update required database tables
722 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
723 require self::ROOT_DIR . '/schema.php';
724 global $wpdb;
725
726 if (function_exists('is_multisite') && is_multisite()) {
727 // check if it is a network activation - if so, run the activation function for each blog id
728 if (isset($_GET['networkwide']) && ($_GET['networkwide'] == 1)) {
729 $old_blog = $wpdb->blogid;
730 // Get all blog ids
731 $blogids = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
732 foreach ($blogids as $blog_id) {
733 switch_to_blog($blog_id);
734 require self::ROOT_DIR . '/schema.php';
735 dbDelta($plugin_queries);
736 }
737 switch_to_blog($old_blog);
738 return;
739 }
740 }
741
742 dbDelta($plugin_queries);
743
744 }
745
746 /**
747 * Load Localisation files.
748 *
749 * Note: the first-loaded translation file overrides any following ones if the same translation is present
750 *
751 * @access public
752 * @return void
753 */
754 public function load_plugin_textdomain() {
755
756 $locale = apply_filters( 'plugin_locale', get_locale(), 'wp_all_export_plugin' );
757
758 load_plugin_textdomain( 'wp_all_export_plugin', false, dirname( plugin_basename( __FILE__ ) ) . "/i18n/languages" );
759 }
760
761 public function fix_db_schema(){
762
763 global $wpdb;
764
765 $db_version_old = get_option('wp_all_export_db_version');
766 $installed_ver = get_option('wp_all_export_free_db_version');
767
768 // We leave the old option so if it doesn't exist then this was installed after the export addons release.
769 // If it does exist we make sure it's not a Pro version.
770 if(!$db_version_old || version_compare($db_version_old, '1.2.10') == 1) {
771 update_option("wp_all_export_free_addons_not_included", true);
772 }
773
774 if ( $installed_ver == PMXE_VERSION ) return true;
775
776 // Declare variable to avoid nuisance notices when charset and collate aren't set.
777 $charset_collate = '';
778
779 if ( ! empty($wpdb->charset))
780 $charset_collate = "DEFAULT CHARACTER SET $wpdb->charset";
781 if ( ! empty($wpdb->collate))
782 $charset_collate .= " COLLATE $wpdb->collate";
783
784 $table_prefix = $this->getTablePrefix();
785
786 $wpdb->query("CREATE TABLE IF NOT EXISTS {$table_prefix}templates (
787 id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
788 name VARCHAR(200) NOT NULL DEFAULT '',
789 options LONGTEXT,
790 PRIMARY KEY (id)
791 ) $charset_collate;");
792
793 $wpdb->query("CREATE TABLE IF NOT EXISTS {$table_prefix}posts (
794 id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
795 post_id BIGINT(20) UNSIGNED NOT NULL,
796 export_id BIGINT(20) UNSIGNED NOT NULL,
797 iteration BIGINT(20) NOT NULL DEFAULT 0,
798 PRIMARY KEY (id)
799 ) $charset_collate;");
800
801 $googleCatsTableExists = $wpdb->query("SHOW TABLES LIKE '{$table_prefix}google_cats'");
802 if(!$googleCatsTableExists) {
803 require_once self::ROOT_DIR . '/schema.php';
804 $wpdb->query($googleCatsQueryCreate);
805 $wpdb->query($googleCatsQueryData);
806 }
807
808 $table = $this->getTablePrefix() . 'exports';
809 $tablefields = $wpdb->get_results("DESCRIBE {$table};");
810 $iteration = false;
811 $parent_id = false;
812 $export_post_type = false;
813 $created_at = false;
814
815 // Check if field exists
816 foreach ($tablefields as $tablefield) {
817 if ('iteration' == $tablefield->Field) $iteration = true;
818 if ('parent_id' == $tablefield->Field) $parent_id = true;
819 if ('export_post_type' == $tablefield->Field) $export_post_type = true;
820 if ('created_at' == $tablefield->Field) $created_at = true;
821 }
822
823 if ( ! $iteration ){
824 $wpdb->query("ALTER TABLE {$table} ADD `iteration` BIGINT(20) NOT NULL DEFAULT 0;");
825 }
826 if ( ! $parent_id ){
827 $wpdb->query("ALTER TABLE {$table} ADD `parent_id` BIGINT(20) NOT NULL DEFAULT 0;");
828 }
829 if ( ! $export_post_type ){
830 $wpdb->query("ALTER TABLE {$table} ADD `export_post_type` TEXT NOT NULL DEFAULT '';");
831 }
832
833 if ( ! $created_at ){
834 $wpdb->query("ALTER TABLE {$table} ADD `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;");
835 $wpdb->query("UPDATE {$table} SET `created_at` = `registered_on` WHERE 1");
836 }
837
838
839 update_option( "wp_all_export_free_db_version", PMXE_VERSION );
840 }
841
842 /**
843 * Determine is current export was created before current version
844 */
845 public static function isExistingExport( $checkVersion = false ){
846
847 $input = new PMXE_Input();
848 $export_id = $input->get('id', 0);
849
850 if (empty($export_id)) $export_id = $input->get('export_id', 0);
851
852 // ID not found means this is new export
853 if (empty($export_id)) return false;
854
855 if ( ! $checkVersion ) $checkVersion = PMXE_VERSION;
856
857 $export = new PMXE_Export_Record();
858 $export->getById($export_id);
859 if ( ! $export->isEmpty() && (empty($export->options['created_at_version']) || version_compare($export->options['created_at_version'], $checkVersion) < 0 )){
860 return true;
861 }
862
863 return false;
864 }
865
866 /**
867 * Determine is current export is first time running
868 */
869 public static function isNewExport(){
870
871 $input = new PMXE_Input();
872 $export_id = $input->get('id', 0);
873
874 if (empty($export_id)) $export_id = $input->get('export_id', 0);
875
876 if (empty($export_id)) $export_id = XmlExportEngine::$exportID;
877
878 // ID not found means this is new export
879 if (empty($export_id)) return true;
880
881 $export = new PMXE_Export_Record();
882 $export->getById($export_id);
883 if ( ! $export->isEmpty() && ! $export->iteration ){
884 return true;
885 }
886
887 return false;
888 }
889
890 /**
891 * Method returns default import options, main utility of the method is to avoid warnings when new
892 * option is introduced but already registered imports don't have it
893 */
894 public static function get_default_import_options() {
895 return array(
896 'cpt' => array(),
897 'whereclause' => '',
898 'joinclause' => '',
899 'filter_rules_hierarhy' => '',
900 'product_matching_mode' => 'parent',
901 'order_item_per_row' => 1,
902 'order_item_fill_empty_columns' => 1,
903 'filepath' => '',
904 'current_filepath' => '',
905 'bundlepath' => '',
906 'export_type' => 'specific',
907 'wp_query' => '',
908 'wp_query_selector' => 'wp_query',
909 'is_user_export' => false,
910 'is_comment_export' => false,
911 'export_to' => 'csv',
912 'export_to_sheet' => 'csv',
913 'delimiter' => ',',
914 'encoding' => 'UTF-8',
915 'is_generate_templates' => 1,
916 'is_generate_import' => 1,
917 'import_id' => 0,
918 'template_name' => '',
919 'is_scheduled' => 0,
920 'scheduled_period' => '',
921 'scheduled_email' => '',
922 'cc_label' => array(),
923 'cc_type' => array(),
924 'cc_value' => array(),
925 'cc_name' => array(),
926 'cc_php' => array(),
927 'cc_code' => array(),
928 'cc_sql' => array(),
929 'cc_options' => array(),
930 'cc_settings' => array(),
931 'friendly_name' => '',
932 'fields' => array('default', 'other', 'cf', 'cats'),
933 'ids' => array(),
934 'rules' => array(),
935 'records_per_iteration' => 50,
936 'include_bom' => 0,
937 'include_functions' => 1,
938 'split_large_exports' => 0,
939 'split_large_exports_count' => 10000,
940 'split_files_list' => array(),
941 'main_xml_tag' => 'data',
942 'record_xml_tag' => 'post',
943 'save_template_as' => 0,
944 'name' => '',
945 'export_only_new_stuff' => 0,
946 'export_only_modified_stuff' => 0,
947 'creata_a_new_export_file' => 0,
948 'attachment_list' => array(),
949 'order_include_poducts' => 0,
950 'order_include_all_poducts' => 0,
951 'order_include_coupons' => 0,
952 'order_include_all_coupons' => 0,
953 'order_include_customers' => 0,
954 'order_include_all_customers' => 0,
955 'migration' => '',
956 'xml_template_type' => 'simple',
957 'custom_xml_template' => '',
958 'custom_xml_template_header' => '',
959 'custom_xml_template_loop' => '',
960 'custom_xml_template_footer' => '',
961 'custom_xml_template_options' => array(),
962 'custom_xml_cdata_logic' => 'auto',
963 'show_cdata_in_preview' => 0,
964 'taxonomy_to_export' => '',
965 'created_at_version' => '',
966 'export_variations' => XmlExportEngine::VARIABLE_PRODUCTS_EXPORT_PARENT_AND_VARIATION,
967 'export_variations_title' => XmlExportEngine::VARIATION_USE_PARENT_TITLE,
968 'include_header_row' => 1,
969 'wpml_lang' => 'all',
970 'enable_export_scheduling' => 'false',
971 'scheduling_enable' => false,
972 'scheduling_weekly_days' => '',
973 'scheduling_run_on' => 'weekly',
974 'scheduling_monthly_day' => '',
975 'scheduling_times' => array(),
976 'scheduling_timezone' => 'UTC',
977 'sub_post_type_to_export' => ''
978
979 );
980 }
981
982 public static function is_ajax(){
983 return (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') ? true : false ;
984 }
985
986 /**
987 * @param $value
988 * @return string
989 */
990 public static function encode($value){
991 $salt = defined('AUTH_SALT') ? AUTH_SALT : wp_salt();
992 return base64_encode(md5($salt) . $value . md5(md5($salt)));
993 }
994
995 /**
996 * @param $encoded
997 * @return mixed
998 */
999 public static function decode($encoded){
1000 $salt = defined('AUTH_SALT') ? AUTH_SALT : wp_salt();
1001 return preg_match('/^[a-f0-9]{32}$/', $encoded) ? $encoded : str_replace(array(md5($salt), md5(md5($salt))), '', base64_decode($encoded));
1002 }
1003
1004 /**
1005 * Replace last occurence of string
1006 * Used in autoloader, that's not muved in string class
1007 *
1008 * @param $search
1009 * @param $replace
1010 * @param $subject
1011 * @return mixed
1012 */
1013 private function lreplace($search, $replace, $subject){
1014 $pos = strrpos($subject, $search);
1015 if($pos !== false){
1016 $subject = substr_replace($subject, $replace, $pos, strlen($search));
1017 }
1018 return $subject;
1019 }
1020 }
1021
1022 PMXE_Plugin::getInstance();
1023
1024 // Include the api front controller
1025 include_once('wpae_api.php');
1026
1027 }
1028
1029