PluginProbe ʕ •ᴥ•ʔ
WP All Export – Drag & Drop Export to Any Custom CSV, XML & Excel / 0.9.0
WP All Export – Drag & Drop Export to Any Custom CSV, XML & Excel v0.9.0
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 / plugin.php
wp-all-export Last commit date
actions 12 years ago classes 12 years ago config 12 years ago controllers 12 years ago filters 12 years ago helpers 12 years ago history 12 years ago i18n 12 years ago libraries 12 years ago models 12 years ago sessions 12 years ago shortcodes 12 years ago static 12 years ago views 12 years ago banner-772x250.png 12 years ago plugin.php 12 years ago readme.txt 12 years ago schema.php 12 years ago screenshot-1.png 12 years ago screenshot-2.png 12 years ago
plugin.php
499 lines
1 <?php
2 /*
3 Plugin Name: WP All Export
4 Plugin URI: http://wordpress.org/plugins/wp-all-export/
5 Description: The most powerful solution for exporting WordPress data to an XML file.
6 Version: 0.9.0
7 Author: Soflyy
8 */
9
10 if( ! defined( 'PMXE_SESSION_COOKIE' ) )
11 define( 'PMXE_SESSION_COOKIE', '_PMXE_session' );
12
13 /**
14 * Plugin root dir with forward slashes as directory separator regardless of actuall DIRECTORY_SEPARATOR value
15 * @var string
16 */
17 define('PMXE_ROOT_DIR', str_replace('\\', '/', dirname(__FILE__)));
18 /**
19 * Plugin root url for referencing static content
20 * @var string
21 */
22 define('PMXE_ROOT_URL', rtrim(plugin_dir_url(__FILE__), '/'));
23 /**
24 * Plugin prefix for making names unique (be aware that this variable is used in conjuction with naming convention,
25 * i.e. in order to change it one must not only modify this constant but also rename all constants, classes and functions which
26 * names composed using this prefix)
27 * @var string
28 */
29 define('PMXE_PREFIX', 'pmxe_');
30
31 define('PMXE_VERSION', '0.9.0');
32
33 define('PMXE_EDITION', 'free');
34
35 /**
36 * Main plugin file, Introduces MVC pattern
37 *
38 * @singletone
39 * @author Pavel Kulbakin <p.kulbakin@gmail.com>
40 */
41 final class PMXE_Plugin {
42 /**
43 * Singletone instance
44 * @var PMXE_Plugin
45 */
46 protected static $instance;
47
48 /**
49 * Plugin options
50 * @var array
51 */
52 protected $options = array();
53
54 /**
55 * Plugin root dir
56 * @var string
57 */
58 const ROOT_DIR = PMXE_ROOT_DIR;
59 /**
60 * Plugin root URL
61 * @var string
62 */
63 const ROOT_URL = PMXE_ROOT_URL;
64 /**
65 * Prefix used for names of shortcodes, action handlers, filter functions etc.
66 * @var string
67 */
68 const PREFIX = PMXE_PREFIX;
69 /**
70 * Plugin file path
71 * @var string
72 */
73 const FILE = __FILE__;
74 /**
75 * Max allowed file size (bytes) to import in default mode
76 * @var int
77 */
78 const LARGE_SIZE = 0; // all files will importing in large import mode
79
80 public static $session;
81
82 /**
83 * Return singletone instance
84 * @return PMXE_Plugin
85 */
86 static public function getInstance() {
87 if (self::$instance == NULL) {
88 self::$instance = new self();
89 }
90 return self::$instance;
91 }
92
93 /**
94 * Common logic for requestin plugin info fields
95 */
96 public function __call($method, $args) {
97 if (preg_match('%^get(.+)%i', $method, $mtch)) {
98 $info = get_plugin_data(self::FILE);
99 if (isset($info[$mtch[1]])) {
100 return $info[$mtch[1]];
101 }
102 }
103 throw new Exception("Requested method " . get_class($this) . "::$method doesn't exist.");
104 }
105
106 /**
107 * Get path to plagin dir relative to wordpress root
108 * @param bool[optional] $noForwardSlash Whether path should be returned withot forwarding slash
109 * @return string
110 */
111 public function getRelativePath($noForwardSlash = false) {
112 $wp_root = str_replace('\\', '/', ABSPATH);
113 return ($noForwardSlash ? '' : '/') . str_replace($wp_root, '', self::ROOT_DIR);
114 }
115
116 /**
117 * Check whether plugin is activated as network one
118 * @return bool
119 */
120 public function isNetwork() {
121 if ( !is_multisite() )
122 return false;
123
124 $plugins = get_site_option('active_sitewide_plugins');
125 if (isset($plugins[plugin_basename(self::FILE)]))
126 return true;
127
128 return false;
129 }
130
131 /**
132 * Check whether permalinks is enabled
133 * @return bool
134 */
135 public function isPermalinks() {
136 global $wp_rewrite;
137
138 return $wp_rewrite->using_permalinks();
139 }
140
141 /**
142 * Return prefix for plugin database tables
143 * @return string
144 */
145 public function getTablePrefix() {
146 global $wpdb;
147
148 //return ($this->isNetwork() ? $wpdb->base_prefix : $wpdb->prefix) . self::PREFIX;
149 return $wpdb->prefix . self::PREFIX;
150 }
151
152 /**
153 * Return prefix for wordpress database tables
154 * @return string
155 */
156 public function getWPPrefix() {
157 global $wpdb;
158 return ($this->isNetwork()) ? $wpdb->base_prefix : $wpdb->prefix;
159 }
160
161 /**
162 * Class constructor containing dispatching logic
163 * @param string $rootDir Plugin root dir
164 * @param string $pluginFilePath Plugin main file
165 */
166 protected function __construct() {
167
168 $this->load_plugin_textdomain();
169
170 // regirster autoloading method
171 if (function_exists('__autoload') and ! in_array('__autoload', spl_autoload_functions())) { // make sure old way of autoloading classes is not broken
172 spl_autoload_register('__autoload');
173 }
174 spl_autoload_register(array($this, '__autoload'));
175
176 // register helpers
177 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) {
178 require_once $filePath;
179 }
180
181 // create history folder
182 $uploads = wp_upload_dir();
183
184 // init plugin options
185 $option_name = get_class($this) . '_Options';
186 $options_default = PMXE_Config::createFromFile(self::ROOT_DIR . '/config/options.php')->toArray();
187 $this->options = array_intersect_key(get_option($option_name, array()), $options_default) + $options_default;
188 $this->options = array_intersect_key($options_default, array_flip(array('info_api_url'))) + $this->options; // make sure hidden options apply upon plugin reactivation
189
190 update_option($option_name, $this->options);
191 $this->options = get_option(get_class($this) . '_Options');
192
193 register_activation_hook(self::FILE, array($this, '__activation'));
194
195 // register action handlers
196 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) {
197 require_once $filePath;
198 $function = $actionName = basename($filePath, '.php');
199 if (preg_match('%^(.+?)[_-](\d+)$%', $actionName, $m)) {
200 $actionName = $m[1];
201 $priority = intval($m[2]);
202 } else {
203 $priority = 10;
204 }
205 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)
206 }
207
208 // register filter handlers
209 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) {
210 require_once $filePath;
211 $function = $actionName = basename($filePath, '.php');
212 if (preg_match('%^(.+?)[_-](\d+)$%', $actionName, $m)) {
213 $actionName = $m[1];
214 $priority = intval($m[2]);
215 } else {
216 $priority = 10;
217 }
218 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)
219 }
220
221 // register shortcodes handlers
222 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) {
223 $tag = strtolower(str_replace('/', '_', preg_replace('%^' . preg_quote(self::ROOT_DIR . '/shortcodes/', '%') . '|\.php$%', '', $filePath)));
224 add_shortcode($tag, array($this, 'shortcodeDispatcher'));
225 }
226
227 // register admin page pre-dispatcher
228 add_action('admin_init', array($this, '__adminInit'));
229 }
230
231 /**
232 * pre-dispatching logic for admin page controllers
233 */
234 public function __adminInit() {
235 $input = new PMXE_Input();
236 $page = strtolower($input->getpost('page', ''));
237 if (preg_match('%^' . preg_quote(str_replace('_', '-', self::PREFIX), '%') . '([\w-]+)$%', $page)) {
238 $this->adminDispatcher($page, strtolower($input->getpost('action', 'index')));
239 }
240 }
241
242 /**
243 * Dispatch shorttag: create corresponding controller instance and call its index method
244 * @param array $args Shortcode tag attributes
245 * @param string $content Shortcode tag content
246 * @param string $tag Shortcode tag name which is being dispatched
247 * @return string
248 */
249 public function shortcodeDispatcher($args, $content, $tag) {
250
251 $controllerName = self::PREFIX . preg_replace('%(^|_).%e', 'strtoupper("$0")', $tag); // capitalize first letters of class name parts and add prefix
252 $controller = new $controllerName();
253 if ( ! $controller instanceof PMXE_Controller) {
254 throw new Exception("Shortcode `$tag` matches to a wrong controller type.");
255 }
256 ob_start();
257 $controller->index($args, $content);
258 return ob_get_clean();
259 }
260
261 /**
262 * Dispatch admin page: call corresponding controller based on get parameter `page`
263 * The method is called twice: 1st time as handler `parse_header` action and then as admin menu item handler
264 * @param string[optional] $page When $page set to empty string ealier buffered content is outputted, otherwise controller is called based on $page value
265 */
266 public function adminDispatcher($page = '', $action = 'index') {
267 static $buffer = NULL;
268 static $buffer_callback = NULL;
269 if ('' === $page) {
270 if ( ! is_null($buffer)) {
271 echo '<div class="wrap">';
272 echo $buffer;
273 do_action('pmxe_action_after');
274 echo '</div>';
275 } elseif ( ! is_null($buffer_callback)) {
276 echo '<div class="wrap">';
277 call_user_func($buffer_callback);
278 do_action('pmxe_action_after');
279 echo '</div>';
280 } else {
281 throw new Exception('There is no previousely buffered content to display.');
282 }
283 } else {
284 $controllerName = preg_replace('%(^' . preg_quote(self::PREFIX, '%') . '|_).%e', 'strtoupper("$0")', str_replace('-', '_', $page)); // capitalize prefix and first letters of class name parts
285 $actionName = str_replace('-', '_', $action);
286 if (method_exists($controllerName, $actionName)) {
287 $this->_admin_current_screen = (object)array(
288 'id' => $controllerName,
289 'base' => $controllerName,
290 'action' => $actionName,
291 'is_ajax' => isset($_SERVER['HTTP_X_REQUESTED_WITH']) and strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest',
292 'is_network' => is_network_admin(),
293 'is_user' => is_user_admin(),
294 );
295 add_filter('current_screen', array($this, 'getAdminCurrentScreen'));
296 add_filter('admin_body_class', create_function('', 'return "' . PMXE_Plugin::PREFIX . 'plugin";'));
297
298 $controller = new $controllerName();
299 if ( ! $controller instanceof PMXE_Controller_Admin) {
300 throw new Exception("Administration page `$page` matches to a wrong controller type.");
301 }
302
303 if ($this->_admin_current_screen->is_ajax) { // ajax request
304 $controller->$action();
305 do_action('pmxe_action_after');
306 die(); // stop processing since we want to output only what controller is randered, nothing in addition
307 } elseif ( ! $controller->isInline) {
308 ob_start();
309 $controller->$action();
310 $buffer = ob_get_clean();
311 } else {
312 $buffer_callback = array($controller, $action);
313 }
314 } else { // redirect to dashboard if requested page and/or action don't exist
315 wp_redirect(admin_url()); die();
316 }
317 }
318 }
319
320 protected $_admin_current_screen = NULL;
321 public function getAdminCurrentScreen()
322 {
323 return $this->_admin_current_screen;
324 }
325
326 /**
327 * Autoloader
328 * It's assumed class name consists of prefix folloed by its name which in turn corresponds to location of source file
329 * if `_` symbols replaced by directory path separator. File name consists of prefix folloed by last part in class name (i.e.
330 * symbols after last `_` in class name)
331 * When class has prefix it's source is looked in `models`, `controllers`, `shortcodes` folders, otherwise it looked in `core` or `library` folder
332 *
333 * @param string $className
334 * @return bool
335 */
336 public function __autoload($className) {
337 $is_prefix = false;
338 $filePath = str_replace('_', '/', preg_replace('%^' . preg_quote(self::PREFIX, '%') . '%', '', strtolower($className), 1, $is_prefix)) . '.php';
339 if ( ! $is_prefix) { // also check file with original letter case
340 $filePathAlt = $className . '.php';
341 }
342 foreach ($is_prefix ? array('models', 'controllers', 'shortcodes', 'classes') : array('libraries') as $subdir) {
343 $path = self::ROOT_DIR . '/' . $subdir . '/' . $filePath;
344 if (is_file($path)) {
345 require $path;
346 return TRUE;
347 }
348 if ( ! $is_prefix) {
349 $pathAlt = self::ROOT_DIR . '/' . $subdir . '/' . $filePathAlt;
350 if (is_file($pathAlt)) {
351 require $pathAlt;
352 return TRUE;
353 }
354 }
355 }
356
357 return FALSE;
358 }
359
360 /**
361 * Get plugin option
362 * @param string[optional] $option Parameter to return, all array of options is returned if not set
363 * @return mixed
364 */
365 public function getOption($option = NULL) {
366 if (is_null($option)) {
367 return $this->options;
368 } else if (isset($this->options[$option])) {
369 return $this->options[$option];
370 } else {
371 throw new Exception("Specified option is not defined for the plugin");
372 }
373 }
374 /**
375 * Update plugin option value
376 * @param string $option Parameter name or array of name => value pairs
377 * @param mixed[optional] $value New value for the option, if not set than 1st parameter is supposed to be array of name => value pairs
378 * @return array
379 */
380 public function updateOption($option, $value = NULL) {
381 is_null($value) or $option = array($option => $value);
382 if (array_diff_key($option, $this->options)) {
383 throw new Exception("Specified option is not defined for the plugin");
384 }
385 $this->options = $option + $this->options;
386 update_option(get_class($this) . '_Options', $this->options);
387
388 return $this->options;
389 }
390
391 /**
392 * Plugin activation logic
393 */
394 public function __activation() {
395 // uncaught exception doesn't prevent plugin from being activated, therefore replace it with fatal error so it does
396 set_exception_handler(create_function('$e', 'trigger_error($e->getMessage(), E_USER_ERROR);'));
397
398 // create plugin options
399 $option_name = get_class($this) . '_Options';
400 $options_default = PMXE_Config::createFromFile(self::ROOT_DIR . '/config/options.php')->toArray();
401 $wpai_options = get_option($option_name, false);
402 if ( ! $wpai_options ) update_option($option_name, $options_default);
403
404 // create/update required database tables
405 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
406 require self::ROOT_DIR . '/schema.php';
407 global $wpdb;
408
409 if (function_exists('is_multisite') && is_multisite()) {
410 // check if it is a network activation - if so, run the activation function for each blog id
411 if (isset($_GET['networkwide']) && ($_GET['networkwide'] == 1)) {
412 $old_blog = $wpdb->blogid;
413 // Get all blog ids
414 $blogids = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs");
415 foreach ($blogids as $blog_id) {
416 switch_to_blog($blog_id);
417 require self::ROOT_DIR . '/schema.php';
418 dbDelta($plugin_queries);
419 }
420 switch_to_blog($old_blog);
421 return;
422 }
423 }
424
425 dbDelta($plugin_queries);
426
427 }
428
429 /**
430 * Load Localisation files.
431 *
432 * Note: the first-loaded translation file overrides any following ones if the same translation is present
433 *
434 * @access public
435 * @return void
436 */
437 public function load_plugin_textdomain() {
438 $locale = apply_filters( 'plugin_locale', get_locale(), 'pmxe_plugin' );
439
440 load_plugin_textdomain( 'PMXE_plugin', false, dirname( plugin_basename( __FILE__ ) ) . "/i18n/languages" );
441 }
442
443 /**
444 * Method returns default import options, main utility of the method is to avoid warnings when new
445 * option is introduced but already registered imports don't have it
446 */
447 public static function get_default_import_options() {
448 return array(
449 'cpt' => array(),
450 'export_to' => 'xml',
451 'is_export_title' => 1,
452 'is_export_content' => 1,
453 'custom_fields_list' => array(),
454 'is_export_custom_fields' => 1,
455 'export_custom_fields_logic' => 'full_export',
456 'taxonomies_list' => array(),
457 'is_export_categories' => 1,
458 'export_categories_logic' => 'full_export',
459 'is_export_images' => 1,
460 'export_images_logic' => array('urls', 'meta_data'),
461 'is_export_other' => 1,
462 'is_export_dates' => 1,
463 'is_export_parent' => 1,
464 'is_export_template' => 1,
465 'is_export_menu_order' => 1,
466 'is_export_status' => 1,
467 'is_export_format' => 1,
468 'is_export_author' => 1,
469 'is_export_slug' => 1,
470 'is_export_excerpt' => 1,
471 'is_export_attachments' => 1
472 );
473 }
474
475 /*
476 * Convert csv to xml
477 */
478 public static function csv_to_xml($csv_url){
479
480 include_once(self::ROOT_DIR.'/libraries/XmlImportCsvParse.php');
481
482 $csv = new PMXE_CsvParser($csv_url);
483
484 $wp_uploads = wp_upload_dir();
485 $tmpname = wp_unique_filename($wp_uploads['path'], str_replace("csv", "xml", basename($csv_url)));
486 $xml_file = $wp_uploads['path'] .'/'. $tmpname;
487 file_put_contents($xml_file, $csv->toXML());
488 return $xml_file;
489
490 }
491
492 public static function is_ajax(){
493 return (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') ? true : false ;
494 }
495
496 }
497
498 PMXE_Plugin::getInstance();
499