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