Acme Demo Setup - Version 1.0.3

Version Description

Download this release

Release Info

Developer acmethemes
Plugin Icon 128x128 Acme Demo Setup
Version 1.0.3
Comparing to
See all releases

Version 1.0.3

acme-demo-setup.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Plugin Name: Acme Demo Setup
4
+ Plugin URI:
5
+ Description: One click demo import
6
+ Version: 1.0.3
7
+ Author: Acme Themes
8
+ Author URI: https://www.acmethemes.com/
9
+ License: GPLv2 or later
10
+ */
11
+
12
+ /*Make sure we don't expose any info if called directly*/
13
+ if ( !function_exists( 'add_action' ) ) {
14
+ echo 'Hi there! I\'m just a plugin, not much I can do when called directly.';
15
+ exit;
16
+ }
17
+ /*Define Constants for this plugin*/
18
+ define( 'ACME_DEMO_SETUP_VERSION', '1.0' );
19
+ define( 'ACME_DEMO_SETUP_PATH', plugin_dir_path( __FILE__ ) );
20
+ define( 'ACME_DEMO_SETUP_URL', plugin_dir_url( __FILE__ ) );
21
+
22
+ /*Now lets init the functionality of this plugin*/
23
+ require_once( ACME_DEMO_SETUP_PATH . '/inc/init.php' );
24
+
25
+ /**
26
+ * Load plugin textdomain.
27
+ * see here https://ulrich.pogson.ch/load-theme-plugin-translations
28
+ */
29
+ if ( ! function_exists( 'acme_demo_setup_load_textdomain' ) ) :
30
+ function acme_demo_setup_load_textdomain() {
31
+
32
+ $domain = 'acme-demo-setup';
33
+ $locale = apply_filters( 'plugin_locale', get_locale(), $domain );
34
+
35
+ // wp-content/languages/plugin-name/plugin-name-de_DE.mo
36
+ load_textdomain( 'acme-demo-setup', trailingslashit( WP_LANG_DIR ) . $domain . '/' . $domain . '-' . $locale . '.mo' );
37
+
38
+ // wp-content/plugins/plugin-name/languages/plugin-name-de_DE.mo
39
+ load_plugin_textdomain( 'acme-demo-setup', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );
40
+ }
41
+ endif;
42
+ add_action( 'plugins_loaded', 'acme_demo_setup_load_textdomain' );
43
+
44
+
inc/admin/upload.php ADDED
@@ -0,0 +1,217 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Acme Demo Setup
4
+ *
5
+ * @package Acme Themes
6
+ * @subpackage Acme Demo Setup
7
+ */
8
+ if( !class_exists( 'Acme_Demo_Setup') ):
9
+ class Acme_Demo_Setup {
10
+ /**
11
+ * @return void
12
+ */
13
+ function __construct( ) {
14
+ add_action( 'mime_types', array( $this, 'mime_types' ) );
15
+ add_action( 'admin_menu', array( $this, 'menu' ) );
16
+ /* enqueue script and style for about page */
17
+ add_action( 'admin_enqueue_scripts', array( $this, 'style_and_scripts' ) );
18
+ /*ajax callback for demo content installation*/
19
+ add_action( 'wp_ajax_acme_demo_setup_ajax_setup', array( $this, 'handler' ) );
20
+
21
+ }
22
+ /**
23
+ * Load css and scripts for the about page
24
+ */
25
+ public function style_and_scripts( $hook_suffix ) {
26
+ if ( 'appearance_page_acme-demo-setup' == $hook_suffix ) {
27
+ wp_enqueue_script( 'acme-demo-setup', ACME_DEMO_SETUP_URL.'inc/assets/js/acme-demo-setup.js', array( 'jquery' ) );
28
+ wp_localize_script( 'acme-demo-setup', 'acme_demo_setup_object', array(
29
+ 'ajaxurl' => admin_url( 'admin-ajax.php' ),
30
+ 'importing' => esc_html__('Importing','education-base'),
31
+ 'imported' => esc_html__('Task Completed, view the log below','education-base')
32
+ ) );
33
+ }
34
+ }
35
+ /**
36
+ * @return array
37
+ */
38
+ function mime_types( $mimes ) {
39
+ $add_mimes = array(
40
+ 'dat' => 'text/plain',
41
+ 'xml' => 'application/xml',
42
+ 'wie' => 'text/html'
43
+ );
44
+
45
+ return array_merge( $mimes, $add_mimes );
46
+ }
47
+
48
+ /**
49
+ * Create admin pages in menu
50
+ *
51
+ * @return void
52
+ */
53
+ function menu() {
54
+ add_theme_page( __( 'Acme Demo Setup', 'acme-demo-setup' ), __( 'Acme Demo Setup', 'acme-demo-setup' ), 'upload_files', 'acme-demo-setup', array( $this, 'screen' ) );
55
+ }
56
+
57
+ /**
58
+ * The Admin Screen
59
+ */
60
+ function screen() {
61
+ echo '<div class="wrap">';
62
+ echo '<h2>' . __( 'Acme Demo Setup', 'acme-demo-setup' ) . '</h2>';
63
+ $this->handler();
64
+ $this->import_form();
65
+ echo '</div>';
66
+ }
67
+
68
+ /**
69
+ * Handle the demo content upload and called to process
70
+ *
71
+ * @return string HTML Results or Error message
72
+ */
73
+ function handler() {
74
+ $error = '';
75
+ $required_files = array();
76
+ if ( isset( $_FILES[ 'upload-zip-archive' ][ 'name' ] ) && ! empty( $_FILES[ 'upload-zip-archive' ][ 'name' ] ) ) {
77
+
78
+ /*check for security*/
79
+ if ( ! current_user_can( 'upload_files' ) ) {
80
+ wp_die( __( 'Sorry, you are not allowed to install demo on this site.', 'acme-demo-setup' ) );
81
+ }
82
+ check_admin_referer( 'acme-demo-setup' );
83
+
84
+ /*file process*/
85
+ esc_html_e('Uploading Zip...','acme-demo-import');
86
+ echo "<br />";
87
+ $upload_zip_archive = $_FILES[ 'upload-zip-archive' ];
88
+ WP_Filesystem();
89
+ global $wp_filesystem;
90
+ $upload_dir = wp_upload_dir();
91
+ $destination = $upload_dir['basedir'] . '/acme-demo-importer/';
92
+
93
+ /*the zip file shouldn't content greater than 3 files*/
94
+ $za = new ZipArchive();
95
+ $za->open( $upload_zip_archive['tmp_name'] );
96
+ $file_on_zip = $za->numFiles;
97
+ if( $file_on_zip > 3 ){
98
+ $error[] = __( "Invalid ZIP greater than 3 files" ,'acme-demo-importer');
99
+ }
100
+
101
+ /*unzip file*/
102
+ esc_html_e('Unzipping File...','acme-demo-import');
103
+ echo "<br />";
104
+ $unzipfile = unzip_file( $upload_zip_archive['tmp_name'], $destination);
105
+ if ( !$unzipfile ) {
106
+ $error[] = __( "Error on unzipping, Please try again" ,'acme-demo-importer');
107
+ }
108
+
109
+ /*get required file*/
110
+ $dirlist = $wp_filesystem->dirlist($destination);
111
+ foreach ( (array) $dirlist as $filename => $fileinfo ) {
112
+ $filetype = wp_check_filetype($filename);
113
+ if( 'xml' == $filetype['ext'] ){
114
+ $required_files['xml'] = $destination.$filename;
115
+ }
116
+ elseif ('wie' == $filetype['ext'] ){
117
+ $required_files['wie'] = $destination.$filename;
118
+ }
119
+ elseif ( 'dat' == $filetype['ext'] ){
120
+ $required_files['dat'] = $destination.$filename;
121
+ }
122
+ else{
123
+ $wp_filesystem->rmdir($destination, true );
124
+ $error[] = __( "Invalid ZIP destination file" ,'acme-demo-importer');
125
+ }
126
+ }
127
+
128
+ /*prepare array of files to import*/
129
+ if( !isset( $required_files['xml'] ) || empty( $required_files['xml'] )){
130
+ $error[] = __( "xml file not included" ,'acme-demo-importer');
131
+
132
+ }
133
+ if( !isset( $required_files['wie'] ) && empty( $required_files['wie'] )){
134
+ $error[] = __( "wie file not included" ,'acme-demo-importer');
135
+
136
+ }
137
+ if( !isset( $required_files['dat'] ) && empty( $required_files['dat'] )){
138
+ $error[] = __( "dat file not included" ,'acme-demo-importer');
139
+ }
140
+ if( is_array( $error ) && !empty( $error ) ){
141
+ foreach ( $error as $e ){
142
+ echo $e;
143
+ echo "<br />";
144
+ }
145
+ }
146
+
147
+ /*process import*/
148
+ $this->import( $required_files );
149
+ }
150
+ }
151
+
152
+ /*import */
153
+ function import( $required_files ){
154
+ /*before import*/
155
+ do_action( 'acme_demo_setup_before_import',$required_files );
156
+
157
+ /*xml demo import*/
158
+ if( isset( $required_files['xml'] ) && !empty( $required_files['xml'] ) ){
159
+ esc_html_e('Importing Demo Content...','acme-demo-import');
160
+ echo "<br /><br />";
161
+
162
+ // Try to update PHP memory limit (so that it does not run out of it).
163
+ ini_set( 'memory_limit', apply_filters( 'acme_demo_setup_memory_limit', '50M' ) );
164
+
165
+ $xml_import = new Acme_Demo_Setup_Wp_Import();
166
+ $xml_import->fetch_attachments = true;
167
+ set_time_limit(0);
168
+ $xml_import -> import( $required_files['xml'] );
169
+ }
170
+
171
+ /*customizer import*/
172
+ if( isset( $required_files['dat'] ) && !empty( $required_files['dat'] ) ){
173
+ esc_html_e('Importing Customizer Data...','acme-demo-import');
174
+ echo "<br /><br />";
175
+
176
+ $wie_import = new Acme_Demo_Setup_CEI_Core();
177
+ $wie_import -> _import( $required_files['dat'] );
178
+ }
179
+
180
+ /*widget import*/
181
+ if( isset( $required_files['dat'] ) && !empty( $required_files['dat'] ) ){
182
+ esc_html_e('Importing Widget Data...','acme-demo-import');
183
+ echo "<br /><br />";
184
+
185
+ acme_demo_setup_wie_process_import_file( $required_files['wie'] );
186
+ }
187
+
188
+ do_action( 'acme_demo_setup_after_import',$required_files );
189
+
190
+ printf( esc_html__('All Done Visit your %s site %s','acme-demo-import'),'<a href='.esc_url( get_home_url()).' target="_blank">','</a>' );
191
+ echo "<br /><br />";
192
+
193
+ exit;
194
+ }
195
+
196
+ /**
197
+ * The upload form
198
+ *
199
+ * @param null
200
+ */
201
+ function import_form( ) {
202
+ echo '<form action="" method="post" enctype="multipart/form-data" id="acme-demo-setup-upload-zip-form">';
203
+ echo '<h3 class="media-title">'. __( 'Upload a zip file containing demo content', 'acme-demo-setup' ) .'</h3>';
204
+ echo '<p><input type="file" name="upload-zip-archive" id="upload-zip-archive" size="50" /></p>';
205
+ echo '<p>'. sprintf( __( 'Maximum upload file size: %s','acme-demo-setup' ), size_format( wp_max_upload_size() ) ) .'</p>';
206
+ wp_nonce_field( 'acme-demo-setup' );
207
+ submit_button( __( 'Upload and Import', 'acme-demo-setup' ) );
208
+ echo "<div id='at-demo-ajax-install-error' style='display: none;color: #d54e21'>".esc_html__('Select File and Try Again!','education-base')."</div>";
209
+ echo '</form>';
210
+ echo "<span id='at-demo-ajax-install-result-loading' class='button button-primary' style='display: none'>".esc_html__('Importing...','education-base')."</span>";
211
+ echo "<h4 id='at-demo-ajax-install-result-title' style='display: none'>".esc_html__('Task Completed, view the log below','education-base')."</h4>";
212
+ echo "<div id='at-demo-ajax-install-result'></div>";
213
+ }
214
+
215
+ }//end class
216
+ endif;
217
+ $Acme_Demo_Setup = new Acme_Demo_Setup();
inc/assets/js/acme-demo-setup.js ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function ($) {
2
+ $('#acme-demo-setup-upload-zip-form').submit(function (e) {
3
+ if( window.FormData === undefined ){
4
+ return true;
5
+ }
6
+ e.preventDefault();
7
+ var fd = new FormData();
8
+ var file = $(this).find('#upload-zip-archive');
9
+ if(!file.val()){
10
+ jQuery('#at-demo-ajax-install-error').show();
11
+ return false;
12
+ }
13
+ else{
14
+ jQuery('#at-demo-ajax-install-error').hide();
15
+ }
16
+ var _wpnonce = $(this).find('input[name=_wpnonce]');
17
+ var _wp_http_referer = $(this).find('input[name=_wp_http_referer]');
18
+
19
+ var individual_file = file[0].files[0];
20
+
21
+ fd.append("upload-zip-archive", individual_file);
22
+ fd.append('action', 'acme_demo_setup_ajax_setup');
23
+ fd.append('_wpnonce', _wpnonce.val());
24
+ fd.append('_wp_http_referer', _wp_http_referer.val());
25
+
26
+ jQuery.ajax({
27
+ type: 'POST',
28
+ url: acme_demo_setup_object.ajaxurl,
29
+ data: fd,
30
+ contentType: false,
31
+ processData: false,
32
+ beforeSend: function (data, settings) {
33
+ jQuery('#acme-demo-setup-upload-zip-form').remove();
34
+ jQuery('#at-demo-ajax-install-result-loading').show();
35
+ jQuery('#at-demo-ajax-install').html(acme_demo_setup_object.importing);
36
+ },
37
+ success : function (data) {
38
+ jQuery('#at-demo-ajax-install-result-loading').hide();
39
+ jQuery('#at-demo-ajax-install-result-title').show();
40
+ jQuery('#at-demo-ajax-install-result').html(data);
41
+ },
42
+ error : function (jqXHR, textStatus, errorThrown) {
43
+ console.log(jqXHR + " :: " + textStatus + " :: " + errorThrown);
44
+ }
45
+ });
46
+ return false;
47
+ });
48
+
49
+ });
inc/frameworks/customizer-export-import/class-cei-core.php ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The main export/import class from customizer-export-import.
4
+ * Renaming CEI_Core to Acme_Demo_Setup_CEI_Core
5
+ * @since 1.0.0
6
+ */
7
+ final class Acme_Demo_Setup_CEI_Core {
8
+
9
+ /**
10
+ * An array of core options that shouldn't be imported.
11
+ *
12
+ * @since 1.0.0
13
+ * @access private
14
+ * @var array $core_options
15
+ */
16
+ static private $core_options = array(
17
+ 'blogname',
18
+ 'blogdescription',
19
+ 'show_on_front',
20
+ 'page_on_front',
21
+ 'page_for_posts',
22
+ );
23
+
24
+ /**
25
+ * Acme Customized Version
26
+ * Imports uploaded mods and calls WordPress core customize_save actions so
27
+ * themes that hook into them can act before mods are saved to the database.
28
+ *
29
+ * @since 1.0
30
+ * @access public
31
+ * @param object $wp_customize An instance of WP_Customize_Manager.
32
+ */
33
+ function _import( $file_url ) {
34
+ $template = get_template();
35
+
36
+ WP_Filesystem();
37
+
38
+ // Setup global vars.
39
+ global $wp_filesystem;
40
+ global $wp_customize;
41
+
42
+
43
+ $raw = $wp_filesystem->get_contents( $file_url );
44
+ if ( $error = is_wp_error( $raw ) ) {
45
+ return $error;
46
+ }
47
+
48
+ $data = @unserialize( $raw );
49
+
50
+ // Data checks.
51
+ if ( 'array' != gettype( $data ) ) {
52
+ esc_html_e( 'Error importing settings! Please check that you uploaded a customizer export file.', 'acme-demo-setup' );
53
+ return;
54
+ }
55
+ if ( ! isset( $data['template'] ) || ! isset( $data['mods'] ) ) {
56
+ esc_html_e( 'Error importing settings! Please check that you uploaded a customizer export file.', 'acme-demo-setup' );
57
+ return;
58
+ }
59
+ if ( $data['template'] != $template ) {
60
+ esc_html_e( 'Error importing settings! The settings you uploaded are not for the current theme.', 'acme-demo-setup' );
61
+ return;
62
+ }
63
+
64
+ // Import images.
65
+ $data['mods'] = self::_import_images( $data['mods'] );
66
+
67
+ // Import custom options.
68
+ if ( isset( $data['options'] ) ) {
69
+
70
+ foreach ( $data['options'] as $option_key => $option_value ) {
71
+
72
+ $option = new Acme_Demo_Setup_CEI_Option( $wp_customize, $option_key, array(
73
+ 'default' => '',
74
+ 'type' => 'option',
75
+ 'capability' => 'edit_theme_options'
76
+ ) );
77
+
78
+ $option->import( $option_value );
79
+ }
80
+ }
81
+
82
+ // Call the customize_save action.
83
+ do_action( 'customize_save', $wp_customize );
84
+
85
+ // Loop through the mods.
86
+ foreach ( $data['mods'] as $key => $val ) {
87
+
88
+ // Call the customize_save_ dynamic action.
89
+ do_action( 'customize_save_' . $key, $wp_customize );
90
+
91
+ // Save the mod.
92
+ set_theme_mod( $key, $val );
93
+ }
94
+
95
+ }
96
+
97
+ /**
98
+ * Imports images for settings saved as mods.
99
+ *
100
+ * @since 0.1
101
+ * @access private
102
+ * @param array $mods An array of customizer mods.
103
+ * @return array The mods array with any new import data.
104
+ */
105
+ static private function _import_images( $mods )
106
+ {
107
+ foreach ( $mods as $key => $val ) {
108
+
109
+ if ( self::_is_image_url( $val ) ) {
110
+
111
+ $data = self::_sideload_image( $val );
112
+
113
+ if ( ! is_wp_error( $data ) ) {
114
+
115
+ $mods[ $key ] = $data->url;
116
+
117
+ // Handle header image controls.
118
+ if ( isset( $mods[ $key . '_data' ] ) ) {
119
+ $mods[ $key . '_data' ] = $data;
120
+ update_post_meta( $data->attachment_id, '_wp_attachment_is_custom_header', get_stylesheet() );
121
+ }
122
+ }
123
+ }
124
+ }
125
+
126
+ return $mods;
127
+ }
128
+
129
+ /**
130
+ * Taken from the core media_sideload_image function and
131
+ * modified to return an array of data instead of html.
132
+ *
133
+ * @since 0.1
134
+ * @access private
135
+ * @param string $file The image file path.
136
+ * @return stdClass An array of image data.
137
+ */
138
+ static private function _sideload_image( $file )
139
+ {
140
+ $data = new stdClass();
141
+
142
+ if ( ! function_exists( 'media_handle_sideload' ) ) {
143
+ require_once( ABSPATH . 'wp-admin/includes/media.php' );
144
+ require_once( ABSPATH . 'wp-admin/includes/file.php' );
145
+ require_once( ABSPATH . 'wp-admin/includes/image.php' );
146
+ }
147
+ if ( ! empty( $file ) ) {
148
+
149
+ // Set variables for storage, fix file filename for query strings.
150
+ preg_match( '/[^\?]+\.(jpe?g|jpe|gif|png)\b/i', $file, $matches );
151
+ $file_array = array();
152
+ $file_array['name'] = basename( $matches[0] );
153
+
154
+ // Download file to temp location.
155
+ $file_array['tmp_name'] = download_url( $file );
156
+
157
+ // If error storing temporarily, return the error.
158
+ if ( is_wp_error( $file_array['tmp_name'] ) ) {
159
+ return $file_array['tmp_name'];
160
+ }
161
+
162
+ // Do the validation and storage stuff.
163
+ $id = media_handle_sideload( $file_array, 0 );
164
+
165
+ // If error storing permanently, unlink.
166
+ if ( is_wp_error( $id ) ) {
167
+ @unlink( $file_array['tmp_name'] );
168
+ return $id;
169
+ }
170
+
171
+ // Build the object to return.
172
+ $meta = wp_get_attachment_metadata( $id );
173
+ $data->attachment_id = $id;
174
+ $data->url = wp_get_attachment_url( $id );
175
+ $data->thumbnail_url = wp_get_attachment_thumb_url( $id );
176
+ $data->height = $meta['height'];
177
+ $data->width = $meta['width'];
178
+ }
179
+
180
+ return $data;
181
+ }
182
+
183
+ /**
184
+ * Checks to see whether a string is an image url or not.
185
+ *
186
+ * @since 0.1
187
+ * @access private
188
+ * @param string $string The string to check.
189
+ * @return bool Whether the string is an image url or not.
190
+ */
191
+ static private function _is_image_url( $string = '' ){
192
+ if ( is_string( $string ) ) {
193
+ if ( preg_match( '/\.(jpg|jpeg|png|gif)/i', $string ) ) {
194
+ return true;
195
+ }
196
+ }
197
+ return false;
198
+ }
199
+ }
inc/frameworks/customizer-export-import/class-cei-option.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * A class that extends WP_Customize_Setting so we can access
4
+ * the protected updated method when importing options.
5
+ *
6
+ * @since 1.0.0
7
+ *
8
+ * Renaming CEI_Option to Acme_Demo_Setup_CEI_Option
9
+ */
10
+ // Load WordPress Customize Setting Class.
11
+ if ( ! class_exists( 'WP_Customize_Setting' ) ) {
12
+ require_once( ABSPATH . WPINC . '/class-wp-customize-setting.php' );
13
+ }
14
+
15
+ final class Acme_Demo_Setup_CEI_Option extends WP_Customize_Setting {
16
+
17
+ /**
18
+ * Import an option value for this setting.
19
+ *
20
+ * @since 1.0.0
21
+ * @param mixed $value The option value.
22
+ * @return void
23
+ */
24
+ public function import( $value )
25
+ {
26
+ $this->update( $value );
27
+ }
28
+ }
inc/frameworks/widget-importer-exporter/import.php ADDED
@@ -0,0 +1,244 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Process import file
4
+ *
5
+ * This parses a file and triggers importation of its widgets.
6
+ *
7
+ * @since 1.0.0
8
+ * @param string $file Path to .wie file uploaded
9
+ * @global string $wie_import_results
10
+ *
11
+ * Renaming wie_process_import_file to acme_demo_setup_wie_process_import_file
12
+ */
13
+ function acme_demo_setup_wie_process_import_file( $file ) {
14
+
15
+ global $wie_import_results;
16
+
17
+ // File exists?
18
+ if ( ! file_exists( $file ) ) {
19
+ wp_die(
20
+ esc_html__( 'Import file could not be found. Please try again.', 'acme-demo-setup' ),
21
+ '',
22
+ array( 'back_link' => true )
23
+ );
24
+ }
25
+
26
+ // Get file contents and decode
27
+ $data = file_get_contents( $file );
28
+ $data = json_decode( $data );
29
+
30
+ // Import the widget data
31
+ // Make results available for display on import/export page
32
+ $wie_import_results = acme_demo_setup_wie_import_data( $data );
33
+ }
34
+
35
+ /**
36
+ * Import widget JSON data
37
+ *
38
+ * @since 1.0.0
39
+ * @global array $wp_registered_sidebars
40
+ * @param object $data JSON widget data from .wie file
41
+ * @return array Results array
42
+ */
43
+ function acme_demo_setup_wie_import_data( $data ) {
44
+
45
+ global $wp_registered_sidebars;
46
+
47
+ // Have valid data?
48
+ // If no data or could not decode
49
+ if ( empty( $data ) || ! is_object( $data ) ) {
50
+ wp_die(
51
+ esc_html__( 'Import data could not be read. Please try a different file.', 'acme-demo-setup' ),
52
+ '',
53
+ array( 'back_link' => true )
54
+ );
55
+ }
56
+
57
+ // Hook before import
58
+ do_action( 'wie_before_import' );
59
+ $data = apply_filters( 'wie_import_data', $data );
60
+
61
+ // Get all available widgets site supports
62
+ $available_widgets = acme_demo_setup_wie_available_widgets();
63
+
64
+ // Get all existing widget instances
65
+ $widget_instances = array();
66
+ foreach ( $available_widgets as $widget_data ) {
67
+ $widget_instances[$widget_data['id_base']] = get_option( 'widget_' . $widget_data['id_base'] );
68
+ }
69
+
70
+ // Begin results
71
+ $results = array();
72
+
73
+ // Loop import data's sidebars
74
+ foreach ( $data as $sidebar_id => $widgets ) {
75
+
76
+ // Skip inactive widgets
77
+ // (should not be in export file)
78
+ if ( 'wp_inactive_widgets' == $sidebar_id ) {
79
+ continue;
80
+ }
81
+
82
+ // Check if sidebar is available on this site
83
+ // Otherwise add widgets to inactive, and say so
84
+ if ( isset( $wp_registered_sidebars[$sidebar_id] ) ) {
85
+ $sidebar_available = true;
86
+ $use_sidebar_id = $sidebar_id;
87
+ $sidebar_message_type = 'success';
88
+ $sidebar_message = '';
89
+ } else {
90
+ $sidebar_available = false;
91
+ $use_sidebar_id = 'wp_inactive_widgets'; // add to inactive if sidebar does not exist in theme
92
+ $sidebar_message_type = 'error';
93
+ $sidebar_message = esc_html__( 'Widget area does not exist in theme (using Inactive)', 'acme-demo-setup' );
94
+ }
95
+
96
+ // Result for sidebar
97
+ $results[$sidebar_id]['name'] = ! empty( $wp_registered_sidebars[$sidebar_id]['name'] ) ? $wp_registered_sidebars[$sidebar_id]['name'] : $sidebar_id; // sidebar name if theme supports it; otherwise ID
98
+ $results[$sidebar_id]['message_type'] = $sidebar_message_type;
99
+ $results[$sidebar_id]['message'] = $sidebar_message;
100
+ $results[$sidebar_id]['widgets'] = array();
101
+
102
+ // Loop widgets
103
+ foreach ( $widgets as $widget_instance_id => $widget ) {
104
+
105
+ $fail = false;
106
+
107
+ // Get id_base (remove -# from end) and instance ID number
108
+ $id_base = preg_replace( '/-[0-9]+$/', '', $widget_instance_id );
109
+ $instance_id_number = str_replace( $id_base . '-', '', $widget_instance_id );
110
+
111
+ // Does site support this widget?
112
+ if ( ! $fail && ! isset( $available_widgets[$id_base] ) ) {
113
+ $fail = true;
114
+ $widget_message_type = 'error';
115
+ $widget_message = esc_html__( 'Site does not support widget', 'acme-demo-setup' ); // explain why widget not imported
116
+ }
117
+
118
+ // Filter to modify settings object before conversion to array and import
119
+ // Leave this filter here for backwards compatibility with manipulating objects (before conversion to array below)
120
+ // Ideally the newer wie_widget_settings_array below will be used instead of this
121
+ $widget = apply_filters( 'wie_widget_settings', $widget ); // object
122
+
123
+ // Convert multidimensional objects to multidimensional arrays
124
+ // Some plugins like Jetpack Widget Visibility store settings as multidimensional arrays
125
+ // Without this, they are imported as objects and cause fatal error on Widgets page
126
+ // If this creates problems for plugins that do actually intend settings in objects then may need to consider other approach: https://wordpress.org/support/topic/problem-with-array-of-arrays
127
+ // It is probably much more likely that arrays are used than objects, however
128
+ $widget = json_decode( wp_json_encode( $widget ), true );
129
+
130
+ // Filter to modify settings array
131
+ // This is preferred over the older wie_widget_settings filter above
132
+ // Do before identical check because changes may make it identical to end result (such as URL replacements)
133
+ $widget = apply_filters( 'wie_widget_settings_array', $widget );
134
+
135
+ // Does widget with identical settings already exist in same sidebar?
136
+ if ( ! $fail && isset( $widget_instances[$id_base] ) ) {
137
+
138
+ // Get existing widgets in this sidebar
139
+ $sidebars_widgets = get_option( 'sidebars_widgets' );
140
+ $sidebar_widgets = isset( $sidebars_widgets[$use_sidebar_id] ) ? $sidebars_widgets[$use_sidebar_id] : array(); // check Inactive if that's where will go
141
+
142
+ // Loop widgets with ID base
143
+ $single_widget_instances = ! empty( $widget_instances[$id_base] ) ? $widget_instances[$id_base] : array();
144
+ foreach ( $single_widget_instances as $check_id => $check_widget ) {
145
+
146
+ // Is widget in same sidebar and has identical settings?
147
+ if ( in_array( "$id_base-$check_id", $sidebar_widgets ) && (array) $widget == $check_widget ) {
148
+
149
+ $fail = true;
150
+ $widget_message_type = 'warning';
151
+ $widget_message = esc_html__( 'Widget already exists', 'acme-demo-setup' ); // explain why widget not imported
152
+
153
+ break;
154
+
155
+ }
156
+
157
+ }
158
+
159
+ }
160
+
161
+ // No failure
162
+ if ( ! $fail ) {
163
+
164
+ // Add widget instance
165
+ $single_widget_instances = get_option( 'widget_' . $id_base ); // all instances for that widget ID base, get fresh every time
166
+ $single_widget_instances = ! empty( $single_widget_instances ) ? $single_widget_instances : array( '_multiwidget' => 1 ); // start fresh if have to
167
+ $single_widget_instances[] = $widget; // add it
168
+
169
+ // Get the key it was given
170
+ end( $single_widget_instances );
171
+ $new_instance_id_number = key( $single_widget_instances );
172
+
173
+ // If key is 0, make it 1
174
+ // When 0, an issue can occur where adding a widget causes data from other widget to load, and the widget doesn't stick (reload wipes it)
175
+ if ( '0' === strval( $new_instance_id_number ) ) {
176
+ $new_instance_id_number = 1;
177
+ $single_widget_instances[$new_instance_id_number] = $single_widget_instances[0];
178
+ unset( $single_widget_instances[0] );
179
+ }
180
+
181
+ // Move _multiwidget to end of array for uniformity
182
+ if ( isset( $single_widget_instances['_multiwidget'] ) ) {
183
+ $multiwidget = $single_widget_instances['_multiwidget'];
184
+ unset( $single_widget_instances['_multiwidget'] );
185
+ $single_widget_instances['_multiwidget'] = $multiwidget;
186
+ }
187
+
188
+ // Update option with new widget
189
+ update_option( 'widget_' . $id_base, $single_widget_instances );
190
+
191
+ // Assign widget instance to sidebar
192
+ $sidebars_widgets = get_option( 'sidebars_widgets' ); // which sidebars have which widgets, get fresh every time
193
+
194
+ // Avoid rarely fatal error when the option is an empty string
195
+ // https://github.com/churchthemes/widget-importer-exporter/pull/11
196
+ if ( ! $sidebars_widgets ) {
197
+ $sidebars_widgets = array();
198
+ }
199
+
200
+ $new_instance_id = $id_base . '-' . $new_instance_id_number; // use ID number from new widget instance
201
+ $sidebars_widgets[$use_sidebar_id][] = $new_instance_id; // add new instance to sidebar
202
+ update_option( 'sidebars_widgets', $sidebars_widgets ); // save the amended data
203
+
204
+ // After widget import action
205
+ $after_widget_import = array(
206
+ 'sidebar' => $use_sidebar_id,
207
+ 'sidebar_old' => $sidebar_id,
208
+ 'widget' => $widget,
209
+ 'widget_type' => $id_base,
210
+ 'widget_id' => $new_instance_id,
211
+ 'widget_id_old' => $widget_instance_id,
212
+ 'widget_id_num' => $new_instance_id_number,
213
+ 'widget_id_num_old' => $instance_id_number
214
+ );
215
+ do_action( 'wie_after_widget_import', $after_widget_import );
216
+
217
+ // Success message
218
+ if ( $sidebar_available ) {
219
+ $widget_message_type = 'success';
220
+ $widget_message = esc_html__( 'Imported', 'acme-demo-setup' );
221
+ } else {
222
+ $widget_message_type = 'warning';
223
+ $widget_message = esc_html__( 'Imported to Inactive', 'acme-demo-setup' );
224
+ }
225
+
226
+ }
227
+
228
+ // Result for widget instance
229
+ $results[$sidebar_id]['widgets'][$widget_instance_id]['name'] = isset( $available_widgets[$id_base]['name'] ) ? $available_widgets[$id_base]['name'] : $id_base; // widget name or ID if name not available (not supported by site)
230
+ $results[$sidebar_id]['widgets'][$widget_instance_id]['title'] = ! empty( $widget['title'] ) ? $widget['title'] : esc_html__( 'No Title', 'acme-demo-setup' ); // show "No Title" if widget instance is untitled
231
+ $results[$sidebar_id]['widgets'][$widget_instance_id]['message_type'] = $widget_message_type;
232
+ $results[$sidebar_id]['widgets'][$widget_instance_id]['message'] = $widget_message;
233
+
234
+ }
235
+
236
+ }
237
+
238
+ // Hook after import
239
+ do_action( 'wie_after_import' );
240
+
241
+ // Return results
242
+ return apply_filters( 'wie_import_results', $results );
243
+
244
+ }
inc/frameworks/widget-importer-exporter/widgets.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Widget Functions
4
+ * @since 1.0.0
5
+ */
6
+
7
+ // No direct access
8
+ if ( ! defined( 'ABSPATH' ) ) exit;
9
+
10
+ /**
11
+ * Available widgets
12
+ *
13
+ * Gather site's widgets into array with ID base, name, etc.
14
+ * Used by export and import functions.
15
+ *
16
+ * @since 0.4
17
+ * @global array $wp_registered_widget_updates
18
+ * @return array Widget information
19
+ *
20
+ * Remaning wie_available_widgets to acme_demo_setup_wie_available_widgets
21
+ */
22
+ function acme_demo_setup_wie_available_widgets() {
23
+ global $wp_registered_widget_controls;
24
+ $widget_controls = $wp_registered_widget_controls;
25
+ $available_widgets = array();
26
+ foreach ( $widget_controls as $widget ) {
27
+ if ( ! empty( $widget['id_base'] ) && ! isset( $available_widgets[$widget['id_base']] ) ) { // no dupes
28
+ $available_widgets[$widget['id_base']]['id_base'] = $widget['id_base'];
29
+ $available_widgets[$widget['id_base']]['name'] = $widget['name'];
30
+ }
31
+ }
32
+ return apply_filters( 'acme_demo_setup_wie_available_widgets', $available_widgets );
33
+ }
inc/frameworks/wordpress-importer/parsers.php ADDED
@@ -0,0 +1,689 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * WordPress eXtended RSS file parser implementations
4
+ */
5
+
6
+ /**
7
+ * WordPress Importer class for managing parsing of WXR files.
8
+ * Renaming WXR_Parser to Acme_Demo_Setup_WXR_Parser
9
+ */
10
+ class Acme_Demo_Setup_WXR_Parser {
11
+ function parse( $file ) {
12
+ // Attempt to use proper XML parsers first
13
+ if ( extension_loaded( 'simplexml' ) ) {
14
+ $parser = new Acme_Demo_Setup_WXR_Parser_SimpleXML;
15
+ $result = $parser->parse( $file );
16
+
17
+ // If SimpleXML succeeds or this is an invalid WXR file then return the results
18
+ if ( ! is_wp_error( $result ) || 'SimpleXML_parse_error' != $result->get_error_code() )
19
+ return $result;
20
+ } else if ( extension_loaded( 'xml' ) ) {
21
+ $parser = new Acme_Demo_Setup_WXR_Parser_XML;
22
+ $result = $parser->parse( $file );
23
+
24
+ // If XMLParser succeeds or this is an invalid WXR file then return the results
25
+ if ( ! is_wp_error( $result ) || 'XML_parse_error' != $result->get_error_code() )
26
+ return $result;
27
+ }
28
+
29
+ // We have a malformed XML file, so display the error and fallthrough to regex
30
+ if ( isset($result) && defined('IMPORT_DEBUG') && IMPORT_DEBUG ) {
31
+ echo '<pre>';
32
+ if ( 'SimpleXML_parse_error' == $result->get_error_code() ) {
33
+ foreach ( $result->get_error_data() as $error )
34
+ echo $error->line . ':' . $error->column . ' ' . esc_html( $error->message ) . "\n";
35
+ } else if ( 'XML_parse_error' == $result->get_error_code() ) {
36
+ $error = $result->get_error_data();
37
+ echo $error[0] . ':' . $error[1] . ' ' . esc_html( $error[2] );
38
+ }
39
+ echo '</pre>';
40
+ echo '<p><strong>' . __( 'There was an error when reading this WXR file', 'wordpress-importer' ) . '</strong><br />';
41
+ echo __( 'Details are shown above. The importer will now try again with a different parser...', 'wordpress-importer' ) . '</p>';
42
+ }
43
+
44
+ // use regular expressions if nothing else available or this is bad XML
45
+ $parser = new Acme_Demo_Setup_WXR_Parser_Regex;
46
+ return $parser->parse( $file );
47
+ }
48
+ }
49
+
50
+ /**
51
+ * WXR Parser that makes use of the SimpleXML PHP extension.
52
+ */
53
+ class Acme_Demo_Setup_WXR_Parser_SimpleXML {
54
+ function parse( $file ) {
55
+ $authors = $posts = $categories = $tags = $terms = array();
56
+
57
+ $internal_errors = libxml_use_internal_errors(true);
58
+
59
+ $dom = new DOMDocument;
60
+ $old_value = null;
61
+ if ( function_exists( 'libxml_disable_entity_loader' ) ) {
62
+ $old_value = libxml_disable_entity_loader( true );
63
+ }
64
+ $success = $dom->loadXML( file_get_contents( $file ) );
65
+ if ( ! is_null( $old_value ) ) {
66
+ libxml_disable_entity_loader( $old_value );
67
+ }
68
+
69
+ if ( ! $success || isset( $dom->doctype ) ) {
70
+ return new WP_Error( 'SimpleXML_parse_error', __( 'There was an error when reading this WXR file', 'wordpress-importer' ), libxml_get_errors() );
71
+ }
72
+
73
+ $xml = simplexml_import_dom( $dom );
74
+ unset( $dom );
75
+
76
+ // halt if loading produces an error
77
+ if ( ! $xml )
78
+ return new WP_Error( 'SimpleXML_parse_error', __( 'There was an error when reading this WXR file', 'wordpress-importer' ), libxml_get_errors() );
79
+
80
+ $wxr_version = $xml->xpath('/rss/channel/wp:wxr_version');
81
+ if ( ! $wxr_version )
82
+ return new WP_Error( 'WXR_parse_error', __( 'This does not appear to be a WXR file, missing/invalid WXR version number', 'wordpress-importer' ) );
83
+
84
+ $wxr_version = (string) trim( $wxr_version[0] );
85
+ // confirm that we are dealing with the correct file format
86
+ if ( ! preg_match( '/^\d+\.\d+$/', $wxr_version ) )
87
+ return new WP_Error( 'WXR_parse_error', __( 'This does not appear to be a WXR file, missing/invalid WXR version number', 'wordpress-importer' ) );
88
+
89
+ $base_url = $xml->xpath('/rss/channel/wp:base_site_url');
90
+ $base_url = (string) trim( $base_url[0] );
91
+
92
+ $namespaces = $xml->getDocNamespaces();
93
+ if ( ! isset( $namespaces['wp'] ) )
94
+ $namespaces['wp'] = 'http://wordpress.org/export/1.1/';
95
+ if ( ! isset( $namespaces['excerpt'] ) )
96
+ $namespaces['excerpt'] = 'http://wordpress.org/export/1.1/excerpt/';
97
+
98
+ // grab authors
99
+ foreach ( $xml->xpath('/rss/channel/wp:author') as $author_arr ) {
100
+ $a = $author_arr->children( $namespaces['wp'] );
101
+ $login = (string) $a->author_login;
102
+ $authors[$login] = array(
103
+ 'author_id' => (int) $a->author_id,
104
+ 'author_login' => $login,
105
+ 'author_email' => (string) $a->author_email,
106
+ 'author_display_name' => (string) $a->author_display_name,
107
+ 'author_first_name' => (string) $a->author_first_name,
108
+ 'author_last_name' => (string) $a->author_last_name
109
+ );
110
+ }
111
+
112
+ // grab cats, tags and terms
113
+ foreach ( $xml->xpath('/rss/channel/wp:category') as $term_arr ) {
114
+ $t = $term_arr->children( $namespaces['wp'] );
115
+ $category = array(
116
+ 'term_id' => (int) $t->term_id,
117
+ 'category_nicename' => (string) $t->category_nicename,
118
+ 'category_parent' => (string) $t->category_parent,
119
+ 'cat_name' => (string) $t->cat_name,
120
+ 'category_description' => (string) $t->category_description
121
+ );
122
+
123
+ foreach ( $t->termmeta as $meta ) {
124
+ $category['termmeta'][] = array(
125
+ 'key' => (string) $meta->meta_key,
126
+ 'value' => (string) $meta->meta_value
127
+ );
128
+ }
129
+
130
+ $categories[] = $category;
131
+ }
132
+
133
+ foreach ( $xml->xpath('/rss/channel/wp:tag') as $term_arr ) {
134
+ $t = $term_arr->children( $namespaces['wp'] );
135
+ $tag = array(
136
+ 'term_id' => (int) $t->term_id,
137
+ 'tag_slug' => (string) $t->tag_slug,
138
+ 'tag_name' => (string) $t->tag_name,
139
+ 'tag_description' => (string) $t->tag_description
140
+ );
141
+
142
+ foreach ( $t->termmeta as $meta ) {
143
+ $tag['termmeta'][] = array(
144
+ 'key' => (string) $meta->meta_key,
145
+ 'value' => (string) $meta->meta_value
146
+ );
147
+ }
148
+
149
+ $tags[] = $tag;
150
+ }
151
+
152
+ foreach ( $xml->xpath('/rss/channel/wp:term') as $term_arr ) {
153
+ $t = $term_arr->children( $namespaces['wp'] );
154
+ $term = array(
155
+ 'term_id' => (int) $t->term_id,
156
+ 'term_taxonomy' => (string) $t->term_taxonomy,
157
+ 'slug' => (string) $t->term_slug,
158
+ 'term_parent' => (string) $t->term_parent,
159
+ 'term_name' => (string) $t->term_name,
160
+ 'term_description' => (string) $t->term_description
161
+ );
162
+
163
+ foreach ( $t->termmeta as $meta ) {
164
+ $term['termmeta'][] = array(
165
+ 'key' => (string) $meta->meta_key,
166
+ 'value' => (string) $meta->meta_value
167
+ );
168
+ }
169
+
170
+ $terms[] = $term;
171
+ }
172
+
173
+ // grab posts
174
+ foreach ( $xml->channel->item as $item ) {
175
+ $post = array(
176
+ 'post_title' => (string) $item->title,
177
+ 'guid' => (string) $item->guid,
178
+ );
179
+
180
+ $dc = $item->children( 'http://purl.org/dc/elements/1.1/' );
181
+ $post['post_author'] = (string) $dc->creator;
182
+
183
+ $content = $item->children( 'http://purl.org/rss/1.0/modules/content/' );
184
+ $excerpt = $item->children( $namespaces['excerpt'] );
185
+ $post['post_content'] = (string) $content->encoded;
186
+ $post['post_excerpt'] = (string) $excerpt->encoded;
187
+
188
+ $wp = $item->children( $namespaces['wp'] );
189
+ $post['post_id'] = (int) $wp->post_id;
190
+ $post['post_date'] = (string) $wp->post_date;
191
+ $post['post_date_gmt'] = (string) $wp->post_date_gmt;
192
+ $post['comment_status'] = (string) $wp->comment_status;
193
+ $post['ping_status'] = (string) $wp->ping_status;
194
+ $post['post_name'] = (string) $wp->post_name;
195
+ $post['status'] = (string) $wp->status;
196
+ $post['post_parent'] = (int) $wp->post_parent;
197
+ $post['menu_order'] = (int) $wp->menu_order;
198
+ $post['post_type'] = (string) $wp->post_type;
199
+ $post['post_password'] = (string) $wp->post_password;
200
+ $post['is_sticky'] = (int) $wp->is_sticky;
201
+
202
+ if ( isset($wp->attachment_url) )
203
+ $post['attachment_url'] = (string) $wp->attachment_url;
204
+
205
+ foreach ( $item->category as $c ) {
206
+ $att = $c->attributes();
207
+ if ( isset( $att['nicename'] ) )
208
+ $post['terms'][] = array(
209
+ 'name' => (string) $c,
210
+ 'slug' => (string) $att['nicename'],
211
+ 'domain' => (string) $att['domain']
212
+ );
213
+ }
214
+
215
+ foreach ( $wp->postmeta as $meta ) {
216
+ $post['postmeta'][] = array(
217
+ 'key' => (string) $meta->meta_key,
218
+ 'value' => (string) $meta->meta_value
219
+ );
220
+ }
221
+
222
+ foreach ( $wp->comment as $comment ) {
223
+ $meta = array();
224
+ if ( isset( $comment->commentmeta ) ) {
225
+ foreach ( $comment->commentmeta as $m ) {
226
+ $meta[] = array(
227
+ 'key' => (string) $m->meta_key,
228
+ 'value' => (string) $m->meta_value
229
+ );
230
+ }
231
+ }
232
+
233
+ $post['comments'][] = array(
234
+ 'comment_id' => (int) $comment->comment_id,
235
+ 'comment_author' => (string) $comment->comment_author,
236
+ 'comment_author_email' => (string) $comment->comment_author_email,
237
+ 'comment_author_IP' => (string) $comment->comment_author_IP,
238
+ 'comment_author_url' => (string) $comment->comment_author_url,
239
+ 'comment_date' => (string) $comment->comment_date,
240
+ 'comment_date_gmt' => (string) $comment->comment_date_gmt,
241
+ 'comment_content' => (string) $comment->comment_content,
242
+ 'comment_approved' => (string) $comment->comment_approved,
243
+ 'comment_type' => (string) $comment->comment_type,
244
+ 'comment_parent' => (string) $comment->comment_parent,
245
+ 'comment_user_id' => (int) $comment->comment_user_id,
246
+ 'commentmeta' => $meta,
247
+ );
248
+ }
249
+
250
+ $posts[] = $post;
251
+ }
252
+
253
+ return array(
254
+ 'authors' => $authors,
255
+ 'posts' => $posts,
256
+ 'categories' => $categories,
257
+ 'tags' => $tags,
258
+ 'terms' => $terms,
259
+ 'base_url' => $base_url,
260
+ 'version' => $wxr_version
261
+ );
262
+ }
263
+ }
264
+
265
+ /**
266
+ * WXR Parser that makes use of the XML Parser PHP extension.
267
+ */
268
+ class Acme_Demo_Setup_WXR_Parser_XML {
269
+ var $wp_tags = array(
270
+ 'wp:post_id', 'wp:post_date', 'wp:post_date_gmt', 'wp:comment_status', 'wp:ping_status', 'wp:attachment_url',
271
+ 'wp:status', 'wp:post_name', 'wp:post_parent', 'wp:menu_order', 'wp:post_type', 'wp:post_password',
272
+ 'wp:is_sticky', 'wp:term_id', 'wp:category_nicename', 'wp:category_parent', 'wp:cat_name', 'wp:category_description',
273
+ 'wp:tag_slug', 'wp:tag_name', 'wp:tag_description', 'wp:term_taxonomy', 'wp:term_parent',
274
+ 'wp:term_name', 'wp:term_description', 'wp:author_id', 'wp:author_login', 'wp:author_email', 'wp:author_display_name',
275
+ 'wp:author_first_name', 'wp:author_last_name',
276
+ );
277
+ var $wp_sub_tags = array(
278
+ 'wp:comment_id', 'wp:comment_author', 'wp:comment_author_email', 'wp:comment_author_url',
279
+ 'wp:comment_author_IP', 'wp:comment_date', 'wp:comment_date_gmt', 'wp:comment_content',
280
+ 'wp:comment_approved', 'wp:comment_type', 'wp:comment_parent', 'wp:comment_user_id',
281
+ );
282
+
283
+ function parse( $file ) {
284
+ $this->wxr_version = $this->in_post = $this->cdata = $this->data = $this->sub_data = $this->in_tag = $this->in_sub_tag = false;
285
+ $this->authors = $this->posts = $this->term = $this->category = $this->tag = array();
286
+
287
+ $xml = xml_parser_create( 'UTF-8' );
288
+ xml_parser_set_option( $xml, XML_OPTION_SKIP_WHITE, 1 );
289
+ xml_parser_set_option( $xml, XML_OPTION_CASE_FOLDING, 0 );
290
+ xml_set_object( $xml, $this );
291
+ xml_set_character_data_handler( $xml, 'cdata' );
292
+ xml_set_element_handler( $xml, 'tag_open', 'tag_close' );
293
+
294
+ if ( ! xml_parse( $xml, file_get_contents( $file ), true ) ) {
295
+ $current_line = xml_get_current_line_number( $xml );
296
+ $current_column = xml_get_current_column_number( $xml );
297
+ $error_code = xml_get_error_code( $xml );
298
+ $error_string = xml_error_string( $error_code );
299
+ return new WP_Error( 'XML_parse_error', 'There was an error when reading this WXR file', array( $current_line, $current_column, $error_string ) );
300
+ }
301
+ xml_parser_free( $xml );
302
+
303
+ if ( ! preg_match( '/^\d+\.\d+$/', $this->wxr_version ) )
304
+ return new WP_Error( 'WXR_parse_error', __( 'This does not appear to be a WXR file, missing/invalid WXR version number', 'wordpress-importer' ) );
305
+
306
+ return array(
307
+ 'authors' => $this->authors,
308
+ 'posts' => $this->posts,
309
+ 'categories' => $this->category,
310
+ 'tags' => $this->tag,
311
+ 'terms' => $this->term,
312
+ 'base_url' => $this->base_url,
313
+ 'version' => $this->wxr_version
314
+ );
315
+ }
316
+
317
+ function tag_open( $parse, $tag, $attr ) {
318
+ if ( in_array( $tag, $this->wp_tags ) ) {
319
+ $this->in_tag = substr( $tag, 3 );
320
+ return;
321
+ }
322
+
323
+ if ( in_array( $tag, $this->wp_sub_tags ) ) {
324
+ $this->in_sub_tag = substr( $tag, 3 );
325
+ return;
326
+ }
327
+
328
+ switch ( $tag ) {
329
+ case 'category':
330
+ if ( isset($attr['domain'], $attr['nicename']) ) {
331
+ $this->sub_data['domain'] = $attr['domain'];
332
+ $this->sub_data['slug'] = $attr['nicename'];
333
+ }
334
+ break;
335
+ case 'item': $this->in_post = true;
336
+ case 'title': if ( $this->in_post ) $this->in_tag = 'post_title'; break;
337
+ case 'guid': $this->in_tag = 'guid'; break;
338
+ case 'dc:creator': $this->in_tag = 'post_author'; break;
339
+ case 'content:encoded': $this->in_tag = 'post_content'; break;
340
+ case 'excerpt:encoded': $this->in_tag = 'post_excerpt'; break;
341
+
342
+ case 'wp:term_slug': $this->in_tag = 'slug'; break;
343
+ case 'wp:meta_key': $this->in_sub_tag = 'key'; break;
344
+ case 'wp:meta_value': $this->in_sub_tag = 'value'; break;
345
+ }
346
+ }
347
+
348
+ function cdata( $parser, $cdata ) {
349
+ if ( ! trim( $cdata ) )
350
+ return;
351
+
352
+ if ( false !== $this->in_tag || false !== $this->in_sub_tag ) {
353
+ $this->cdata .= $cdata;
354
+ } else {
355
+ $this->cdata .= trim( $cdata );
356
+ }
357
+ }
358
+
359
+ function tag_close( $parser, $tag ) {
360
+ switch ( $tag ) {
361
+ case 'wp:comment':
362
+ unset( $this->sub_data['key'], $this->sub_data['value'] ); // remove meta sub_data
363
+ if ( ! empty( $this->sub_data ) )
364
+ $this->data['comments'][] = $this->sub_data;
365
+ $this->sub_data = false;
366
+ break;
367
+ case 'wp:commentmeta':
368
+ $this->sub_data['commentmeta'][] = array(
369
+ 'key' => $this->sub_data['key'],
370
+ 'value' => $this->sub_data['value']
371
+ );
372
+ break;
373
+ case 'category':
374
+ if ( ! empty( $this->sub_data ) ) {
375
+ $this->sub_data['name'] = $this->cdata;
376
+ $this->data['terms'][] = $this->sub_data;
377
+ }
378
+ $this->sub_data = false;
379
+ break;
380
+ case 'wp:postmeta':
381
+ if ( ! empty( $this->sub_data ) )
382
+ $this->data['postmeta'][] = $this->sub_data;
383
+ $this->sub_data = false;
384
+ break;
385
+ case 'item':
386
+ $this->posts[] = $this->data;
387
+ $this->data = false;
388
+ break;
389
+ case 'wp:category':
390
+ case 'wp:tag':
391
+ case 'wp:term':
392
+ $n = substr( $tag, 3 );
393
+ array_push( $this->$n, $this->data );
394
+ $this->data = false;
395
+ break;
396
+ case 'wp:author':
397
+ if ( ! empty($this->data['author_login']) )
398
+ $this->authors[$this->data['author_login']] = $this->data;
399
+ $this->data = false;
400
+ break;
401
+ case 'wp:base_site_url':
402
+ $this->base_url = $this->cdata;
403
+ break;
404
+ case 'wp:wxr_version':
405
+ $this->wxr_version = $this->cdata;
406
+ break;
407
+
408
+ default:
409
+ if ( $this->in_sub_tag ) {
410
+ $this->sub_data[$this->in_sub_tag] = ! empty( $this->cdata ) ? $this->cdata : '';
411
+ $this->in_sub_tag = false;
412
+ } else if ( $this->in_tag ) {
413
+ $this->data[$this->in_tag] = ! empty( $this->cdata ) ? $this->cdata : '';
414
+ $this->in_tag = false;
415
+ }
416
+ }
417
+
418
+ $this->cdata = false;
419
+ }
420
+ }
421
+
422
+ /**
423
+ * WXR Parser that uses regular expressions. Fallback for installs without an XML parser.
424
+ */
425
+ class Acme_Demo_Setup_WXR_Parser_Regex {
426
+ var $authors = array();
427
+ var $posts = array();
428
+ var $categories = array();
429
+ var $tags = array();
430
+ var $terms = array();
431
+ var $base_url = '';
432
+
433
+ function __construct() {
434
+ $this->has_gzip = is_callable( 'gzopen' );
435
+ }
436
+
437
+ function parse( $file ) {
438
+ $wxr_version = $in_post = false;
439
+
440
+ $fp = $this->fopen( $file, 'r' );
441
+ if ( $fp ) {
442
+ while ( ! $this->feof( $fp ) ) {
443
+ $importline = rtrim( $this->fgets( $fp ) );
444
+
445
+ if ( ! $wxr_version && preg_match( '|<wp:wxr_version>(\d+\.\d+)</wp:wxr_version>|', $importline, $version ) )
446
+ $wxr_version = $version[1];
447
+
448
+ if ( false !== strpos( $importline, '<wp:base_site_url>' ) ) {
449
+ preg_match( '|<wp:base_site_url>(.*?)</wp:base_site_url>|is', $importline, $url );
450
+ $this->base_url = $url[1];
451
+ continue;
452
+ }
453
+ if ( false !== strpos( $importline, '<wp:category>' ) ) {
454
+ preg_match( '|<wp:category>(.*?)</wp:category>|is', $importline, $category );
455
+ $this->categories[] = $this->process_category( $category[1] );
456
+ continue;
457
+ }
458
+ if ( false !== strpos( $importline, '<wp:tag>' ) ) {
459
+ preg_match( '|<wp:tag>(.*?)</wp:tag>|is', $importline, $tag );
460
+ $this->tags[] = $this->process_tag( $tag[1] );
461
+ continue;
462
+ }
463
+ if ( false !== strpos( $importline, '<wp:term>' ) ) {
464
+ preg_match( '|<wp:term>(.*?)</wp:term>|is', $importline, $term );
465
+ $this->terms[] = $this->process_term( $term[1] );
466
+ continue;
467
+ }
468
+ if ( false !== strpos( $importline, '<wp:author>' ) ) {
469
+ preg_match( '|<wp:author>(.*?)</wp:author>|is', $importline, $author );
470
+ $a = $this->process_author( $author[1] );
471
+ $this->authors[$a['author_login']] = $a;
472
+ continue;
473
+ }
474
+ if ( false !== strpos( $importline, '<item>' ) ) {
475
+ $post = '';
476
+ $in_post = true;
477
+ continue;
478
+ }
479
+ if ( false !== strpos( $importline, '</item>' ) ) {
480
+ $in_post = false;
481
+ $this->posts[] = $this->process_post( $post );
482
+ continue;
483
+ }
484
+ if ( $in_post ) {
485
+ $post .= $importline . "\n";
486
+ }
487
+ }
488
+
489
+ $this->fclose($fp);
490
+ }
491
+
492
+ if ( ! $wxr_version )
493
+ return new WP_Error( 'WXR_parse_error', __( 'This does not appear to be a WXR file, missing/invalid WXR version number', 'wordpress-importer' ) );
494
+
495
+ return array(
496
+ 'authors' => $this->authors,
497
+ 'posts' => $this->posts,
498
+ 'categories' => $this->categories,
499
+ 'tags' => $this->tags,
500
+ 'terms' => $this->terms,
501
+ 'base_url' => $this->base_url,
502
+ 'version' => $wxr_version
503
+ );
504
+ }
505
+
506
+ function get_tag( $string, $tag ) {
507
+ preg_match( "|<$tag.*?>(.*?)</$tag>|is", $string, $return );
508
+ if ( isset( $return[1] ) ) {
509
+ if ( substr( $return[1], 0, 9 ) == '<![CDATA[' ) {
510
+ if ( strpos( $return[1], ']]]]><![CDATA[>' ) !== false ) {
511
+ preg_match_all( '|<!\[CDATA\[(.*?)\]\]>|s', $return[1], $matches );
512
+ $return = '';
513
+ foreach( $matches[1] as $match )
514
+ $return .= $match;
515
+ } else {
516
+ $return = preg_replace( '|^<!\[CDATA\[(.*)\]\]>$|s', '$1', $return[1] );
517
+ }
518
+ } else {
519
+ $return = $return[1];
520
+ }
521
+ } else {
522
+ $return = '';
523
+ }
524
+ return $return;
525
+ }
526
+
527
+ function process_category( $c ) {
528
+ return array(
529
+ 'term_id' => $this->get_tag( $c, 'wp:term_id' ),
530
+ 'cat_name' => $this->get_tag( $c, 'wp:cat_name' ),
531
+ 'category_nicename' => $this->get_tag( $c, 'wp:category_nicename' ),
532
+ 'category_parent' => $this->get_tag( $c, 'wp:category_parent' ),
533
+ 'category_description' => $this->get_tag( $c, 'wp:category_description' ),
534
+ );
535
+ }
536
+
537
+ function process_tag( $t ) {
538
+ return array(
539
+ 'term_id' => $this->get_tag( $t, 'wp:term_id' ),
540
+ 'tag_name' => $this->get_tag( $t, 'wp:tag_name' ),
541
+ 'tag_slug' => $this->get_tag( $t, 'wp:tag_slug' ),
542
+ 'tag_description' => $this->get_tag( $t, 'wp:tag_description' ),
543
+ );
544
+ }
545
+
546
+ function process_term( $t ) {
547
+ return array(
548
+ 'term_id' => $this->get_tag( $t, 'wp:term_id' ),
549
+ 'term_taxonomy' => $this->get_tag( $t, 'wp:term_taxonomy' ),
550
+ 'slug' => $this->get_tag( $t, 'wp:term_slug' ),
551
+ 'term_parent' => $this->get_tag( $t, 'wp:term_parent' ),
552
+ 'term_name' => $this->get_tag( $t, 'wp:term_name' ),
553
+ 'term_description' => $this->get_tag( $t, 'wp:term_description' ),
554
+ );
555
+ }
556
+
557
+ function process_author( $a ) {
558
+ return array(
559
+ 'author_id' => $this->get_tag( $a, 'wp:author_id' ),
560
+ 'author_login' => $this->get_tag( $a, 'wp:author_login' ),
561
+ 'author_email' => $this->get_tag( $a, 'wp:author_email' ),
562
+ 'author_display_name' => $this->get_tag( $a, 'wp:author_display_name' ),
563
+ 'author_first_name' => $this->get_tag( $a, 'wp:author_first_name' ),
564
+ 'author_last_name' => $this->get_tag( $a, 'wp:author_last_name' ),
565
+ );
566
+ }
567
+
568
+ function process_post( $post ) {
569
+ $post_id = $this->get_tag( $post, 'wp:post_id' );
570
+ $post_title = $this->get_tag( $post, 'title' );
571
+ $post_date = $this->get_tag( $post, 'wp:post_date' );
572
+ $post_date_gmt = $this->get_tag( $post, 'wp:post_date_gmt' );
573
+ $comment_status = $this->get_tag( $post, 'wp:comment_status' );
574
+ $ping_status = $this->get_tag( $post, 'wp:ping_status' );
575
+ $status = $this->get_tag( $post, 'wp:status' );
576
+ $post_name = $this->get_tag( $post, 'wp:post_name' );
577
+ $post_parent = $this->get_tag( $post, 'wp:post_parent' );
578
+ $menu_order = $this->get_tag( $post, 'wp:menu_order' );
579
+ $post_type = $this->get_tag( $post, 'wp:post_type' );
580
+ $post_password = $this->get_tag( $post, 'wp:post_password' );
581
+ $is_sticky = $this->get_tag( $post, 'wp:is_sticky' );
582
+ $guid = $this->get_tag( $post, 'guid' );
583
+ $post_author = $this->get_tag( $post, 'dc:creator' );
584
+
585
+ $post_excerpt = $this->get_tag( $post, 'excerpt:encoded' );
586
+ $post_excerpt = preg_replace_callback( '|<(/?[A-Z]+)|', array( &$this, '_normalize_tag' ), $post_excerpt );
587
+ $post_excerpt = str_replace( '<br>', '<br />', $post_excerpt );
588
+ $post_excerpt = str_replace( '<hr>', '<hr />', $post_excerpt );
589
+
590
+ $post_content = $this->get_tag( $post, 'content:encoded' );
591
+ $post_content = preg_replace_callback( '|<(/?[A-Z]+)|', array( &$this, '_normalize_tag' ), $post_content );
592
+ $post_content = str_replace( '<br>', '<br />', $post_content );
593
+ $post_content = str_replace( '<hr>', '<hr />', $post_content );
594
+
595
+ $postdata = compact( 'post_id', 'post_author', 'post_date', 'post_date_gmt', 'post_content', 'post_excerpt',
596
+ 'post_title', 'status', 'post_name', 'comment_status', 'ping_status', 'guid', 'post_parent',
597
+ 'menu_order', 'post_type', 'post_password', 'is_sticky'
598
+ );
599
+
600
+ $attachment_url = $this->get_tag( $post, 'wp:attachment_url' );
601
+ if ( $attachment_url )
602
+ $postdata['attachment_url'] = $attachment_url;
603
+
604
+ preg_match_all( '|<category domain="([^"]+?)" nicename="([^"]+?)">(.+?)</category>|is', $post, $terms, PREG_SET_ORDER );
605
+ foreach ( $terms as $t ) {
606
+ $post_terms[] = array(
607
+ 'slug' => $t[2],
608
+ 'domain' => $t[1],
609
+ 'name' => str_replace( array( '<![CDATA[', ']]>' ), '', $t[3] ),
610
+ );
611
+ }
612
+ if ( ! empty( $post_terms ) ) $postdata['terms'] = $post_terms;
613
+
614
+ preg_match_all( '|<wp:comment>(.+?)</wp:comment>|is', $post, $comments );
615
+ $comments = $comments[1];
616
+ if ( $comments ) {
617
+ foreach ( $comments as $comment ) {
618
+ preg_match_all( '|<wp:commentmeta>(.+?)</wp:commentmeta>|is', $comment, $commentmeta );
619
+ $commentmeta = $commentmeta[1];
620
+ $c_meta = array();
621
+ foreach ( $commentmeta as $m ) {
622
+ $c_meta[] = array(
623
+ 'key' => $this->get_tag( $m, 'wp:meta_key' ),
624
+ 'value' => $this->get_tag( $m, 'wp:meta_value' ),
625
+ );
626
+ }
627
+
628
+ $post_comments[] = array(
629
+ 'comment_id' => $this->get_tag( $comment, 'wp:comment_id' ),
630
+ 'comment_author' => $this->get_tag( $comment, 'wp:comment_author' ),
631
+ 'comment_author_email' => $this->get_tag( $comment, 'wp:comment_author_email' ),
632
+ 'comment_author_IP' => $this->get_tag( $comment, 'wp:comment_author_IP' ),
633
+ 'comment_author_url' => $this->get_tag( $comment, 'wp:comment_author_url' ),
634
+ 'comment_date' => $this->get_tag( $comment, 'wp:comment_date' ),
635
+ 'comment_date_gmt' => $this->get_tag( $comment, 'wp:comment_date_gmt' ),
636
+ 'comment_content' => $this->get_tag( $comment, 'wp:comment_content' ),
637
+ 'comment_approved' => $this->get_tag( $comment, 'wp:comment_approved' ),
638
+ 'comment_type' => $this->get_tag( $comment, 'wp:comment_type' ),
639
+ 'comment_parent' => $this->get_tag( $comment, 'wp:comment_parent' ),
640
+ 'comment_user_id' => $this->get_tag( $comment, 'wp:comment_user_id' ),
641
+ 'commentmeta' => $c_meta,
642
+ );
643
+ }
644
+ }
645
+ if ( ! empty( $post_comments ) ) $postdata['comments'] = $post_comments;
646
+
647
+ preg_match_all( '|<wp:postmeta>(.+?)</wp:postmeta>|is', $post, $postmeta );
648
+ $postmeta = $postmeta[1];
649
+ if ( $postmeta ) {
650
+ foreach ( $postmeta as $p ) {
651
+ $post_postmeta[] = array(
652
+ 'key' => $this->get_tag( $p, 'wp:meta_key' ),
653
+ 'value' => $this->get_tag( $p, 'wp:meta_value' ),
654
+ );
655
+ }
656
+ }
657
+ if ( ! empty( $post_postmeta ) ) $postdata['postmeta'] = $post_postmeta;
658
+
659
+ return $postdata;
660
+ }
661
+
662
+ function _normalize_tag( $matches ) {
663
+ return '<' . strtolower( $matches[1] );
664
+ }
665
+
666
+ function fopen( $filename, $mode = 'r' ) {
667
+ if ( $this->has_gzip )
668
+ return gzopen( $filename, $mode );
669
+ return fopen( $filename, $mode );
670
+ }
671
+
672
+ function feof( $fp ) {
673
+ if ( $this->has_gzip )
674
+ return gzeof( $fp );
675
+ return feof( $fp );
676
+ }
677
+
678
+ function fgets( $fp, $len = 8192 ) {
679
+ if ( $this->has_gzip )
680
+ return gzgets( $fp, $len );
681
+ return fgets( $fp, $len );
682
+ }
683
+
684
+ function fclose( $fp ) {
685
+ if ( $this->has_gzip )
686
+ return gzclose( $fp );
687
+ return fclose( $fp );
688
+ }
689
+ }
inc/frameworks/wordpress-importer/wordpress-importer.php ADDED
@@ -0,0 +1,1023 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /** Display verbose errors */
4
+ define( 'IMPORT_DEBUG', false );
5
+
6
+ // Load Importer API
7
+ require_once ABSPATH . 'wp-admin/includes/import.php';
8
+
9
+ if ( ! class_exists( 'WP_Importer' ) ) {
10
+ $class_wp_importer = ABSPATH . 'wp-admin/includes/class-wp-importer.php';
11
+ if ( file_exists( $class_wp_importer ) )
12
+ require $class_wp_importer;
13
+ }
14
+
15
+ // include WXR file parsers
16
+ require dirname( __FILE__ ) . '/parsers.php';
17
+
18
+ /**
19
+ * WordPress Importer class for managing the import process of a WXR file
20
+ *
21
+ * @package WordPress
22
+ * @subpackage Importer
23
+ *
24
+ * Renaming WP_Import to Acme_Demo_Setup_Wp_Import
25
+ */
26
+ if ( class_exists( 'WP_Importer' ) ) {
27
+ class Acme_Demo_Setup_Wp_Import extends WP_Importer {
28
+ var $max_wxr_version = 1.2; // max. supported WXR version
29
+
30
+ var $id; // WXR attachment ID
31
+
32
+ // information to import from WXR file
33
+ var $version;
34
+ var $authors = array();
35
+ var $posts = array();
36
+ var $terms = array();
37
+ var $categories = array();
38
+ var $tags = array();
39
+ var $base_url = '';
40
+
41
+ // mappings from old information to new
42
+ var $processed_authors = array();
43
+ var $author_mapping = array();
44
+ var $processed_terms = array();
45
+ var $processed_posts = array();
46
+ var $post_orphans = array();
47
+ var $processed_menu_items = array();
48
+ var $menu_item_orphans = array();
49
+ var $missing_menu_items = array();
50
+
51
+ var $fetch_attachments = false;
52
+ var $url_remap = array();
53
+ var $featured_images = array();
54
+
55
+ /**
56
+ * The main controller for the actual import stage.
57
+ *
58
+ * @param string $file Path to the WXR file for importing
59
+ */
60
+ function import( $file ) {
61
+
62
+ add_filter( 'import_post_meta_key', array( $this, 'is_valid_meta_key' ) );
63
+ add_filter( 'http_request_timeout', array( &$this, 'bump_request_timeout' ) );
64
+
65
+ $this->import_start( $file );
66
+
67
+ $this->get_author_mapping();
68
+
69
+ wp_suspend_cache_invalidation( true );
70
+ $this->process_categories();
71
+ $this->process_tags();
72
+ $this->process_terms();
73
+ $this->process_posts();
74
+ wp_suspend_cache_invalidation( false );
75
+
76
+ // update incorrect/missing information in the DB
77
+ $this->backfill_parents();
78
+ $this->backfill_attachment_urls();
79
+ $this->remap_featured_images();
80
+
81
+ $this->import_end();
82
+ }
83
+
84
+ /**
85
+ * Parses the WXR file and prepares us for the task of processing parsed data
86
+ *
87
+ * @param string $file Path to the WXR file for importing
88
+ */
89
+ function import_start( $file ) {
90
+
91
+ if ( ! is_file($file) ) {
92
+ echo '<p><strong>' . __( 'Sorry, there has been an error.', 'wordpress-importer' ) . '</strong><br />';
93
+ echo __( 'The file does not exist, please try again.', 'wordpress-importer' ) . '</p>';
94
+ die();
95
+ }
96
+
97
+ $import_data = $this->parse( $file );
98
+
99
+ if ( is_wp_error( $import_data ) ) {
100
+ echo '<p><strong>' . __( 'Sorry, there has been an error.', 'wordpress-importer' ) . '</strong><br />';
101
+ echo esc_html( $import_data->get_error_message() ) . '</p>';
102
+ die();
103
+ }
104
+
105
+ $this->version = $import_data['version'];
106
+ $this->get_authors_from_import( $import_data );
107
+ $this->posts = $import_data['posts'];
108
+ $this->terms = $import_data['terms'];
109
+ $this->categories = $import_data['categories'];
110
+ $this->tags = $import_data['tags'];
111
+ $this->base_url = esc_url( $import_data['base_url'] );
112
+
113
+ wp_defer_term_counting( true );
114
+ wp_defer_comment_counting( true );
115
+
116
+ do_action( 'import_start' );
117
+ }
118
+
119
+ /**
120
+ * Performs post-import cleanup of files and the cache
121
+ */
122
+ function import_end() {
123
+ wp_import_cleanup( $this->id );
124
+
125
+ wp_cache_flush();
126
+ foreach ( get_taxonomies() as $tax ) {
127
+ delete_option( "{$tax}_children" );
128
+ _get_term_hierarchy( $tax );
129
+ }
130
+
131
+ wp_defer_term_counting( false );
132
+ wp_defer_comment_counting( false );
133
+
134
+ echo '<p>' . __( 'Remember to update the passwords and roles of imported users.', 'wordpress-importer' ) . '</p>';
135
+
136
+ do_action( 'import_end' );
137
+ }
138
+
139
+
140
+ /**
141
+ * Retrieve authors from parsed WXR data
142
+ *
143
+ * Uses the provided author information from WXR 1.1 files
144
+ * or extracts info from each post for WXR 1.0 files
145
+ *
146
+ * @param array $import_data Data returned by a WXR parser
147
+ */
148
+ function get_authors_from_import( $import_data ) {
149
+ if ( ! empty( $import_data['authors'] ) ) {
150
+ $this->authors = $import_data['authors'];
151
+ // no author information, grab it from the posts
152
+ } else {
153
+ foreach ( $import_data['posts'] as $post ) {
154
+ $login = sanitize_user( $post['post_author'], true );
155
+ if ( empty( $login ) ) {
156
+ printf( __( 'Failed to import author %s. Their posts will be attributed to the current user.', 'wordpress-importer' ), esc_html( $post['post_author'] ) );
157
+ echo '<br />';
158
+ continue;
159
+ }
160
+
161
+ if ( ! isset($this->authors[$login]) )
162
+ $this->authors[$login] = array(
163
+ 'author_login' => $login,
164
+ 'author_display_name' => $post['post_author']
165
+ );
166
+ }
167
+ }
168
+ }
169
+
170
+ /**
171
+ * Map old author logins to local user IDs based on decisions made
172
+ * in import options form. Can map to an existing user, create a new user
173
+ * or falls back to the current user in case of error with either of the previous
174
+ */
175
+ function get_author_mapping() {
176
+ if ( ! isset( $_POST['imported_authors'] ) )
177
+ return;
178
+
179
+ $create_users = $this->allow_create_users();
180
+
181
+ foreach ( (array) $_POST['imported_authors'] as $i => $old_login ) {
182
+ // Multisite adds strtolower to sanitize_user. Need to sanitize here to stop breakage in process_posts.
183
+ $santized_old_login = sanitize_user( $old_login, true );
184
+ $old_id = isset( $this->authors[$old_login]['author_id'] ) ? intval($this->authors[$old_login]['author_id']) : false;
185
+
186
+ if ( ! empty( $_POST['user_map'][$i] ) ) {
187
+ $user = get_userdata( intval($_POST['user_map'][$i]) );
188
+ if ( isset( $user->ID ) ) {
189
+ if ( $old_id )
190
+ $this->processed_authors[$old_id] = $user->ID;
191
+ $this->author_mapping[$santized_old_login] = $user->ID;
192
+ }
193
+ } else if ( $create_users ) {
194
+ if ( ! empty($_POST['user_new'][$i]) ) {
195
+ $user_id = wp_create_user( $_POST['user_new'][$i], wp_generate_password() );
196
+ } else if ( $this->version != '1.0' ) {
197
+ $user_data = array(
198
+ 'user_login' => $old_login,
199
+ 'user_pass' => wp_generate_password(),
200
+ 'user_email' => isset( $this->authors[$old_login]['author_email'] ) ? $this->authors[$old_login]['author_email'] : '',
201
+ 'display_name' => $this->authors[$old_login]['author_display_name'],
202
+ 'first_name' => isset( $this->authors[$old_login]['author_first_name'] ) ? $this->authors[$old_login]['author_first_name'] : '',
203
+ 'last_name' => isset( $this->authors[$old_login]['author_last_name'] ) ? $this->authors[$old_login]['author_last_name'] : '',
204
+ );
205
+ $user_id = wp_insert_user( $user_data );
206
+ }
207
+
208
+ if ( ! is_wp_error( $user_id ) ) {
209
+ if ( $old_id )
210
+ $this->processed_authors[$old_id] = $user_id;
211
+ $this->author_mapping[$santized_old_login] = $user_id;
212
+ } else {
213
+ printf( __( 'Failed to create new user for %s. Their posts will be attributed to the current user.', 'wordpress-importer' ), esc_html($this->authors[$old_login]['author_display_name']) );
214
+ if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG )
215
+ echo ' ' . $user_id->get_error_message();
216
+ echo '<br />';
217
+ }
218
+ }
219
+
220
+ // failsafe: if the user_id was invalid, default to the current user
221
+ if ( ! isset( $this->author_mapping[$santized_old_login] ) ) {
222
+ if ( $old_id )
223
+ $this->processed_authors[$old_id] = (int) get_current_user_id();
224
+ $this->author_mapping[$santized_old_login] = (int) get_current_user_id();
225
+ }
226
+ }
227
+ }
228
+
229
+ /**
230
+ * Create new categories based on import information
231
+ *
232
+ * Doesn't create a new category if its slug already exists
233
+ */
234
+ function process_categories() {
235
+ $this->categories = apply_filters( 'wp_import_categories', $this->categories );
236
+
237
+ if ( empty( $this->categories ) )
238
+ return;
239
+
240
+ foreach ( $this->categories as $cat ) {
241
+ // if the category already exists leave it alone
242
+ $term_id = term_exists( $cat['category_nicename'], 'category' );
243
+ if ( $term_id ) {
244
+ if ( is_array($term_id) ) $term_id = $term_id['term_id'];
245
+ if ( isset($cat['term_id']) )
246
+ $this->processed_terms[intval($cat['term_id'])] = (int) $term_id;
247
+ continue;
248
+ }
249
+
250
+ $category_parent = empty( $cat['category_parent'] ) ? 0 : category_exists( $cat['category_parent'] );
251
+ $category_description = isset( $cat['category_description'] ) ? $cat['category_description'] : '';
252
+ $catarr = array(
253
+ 'category_nicename' => $cat['category_nicename'],
254
+ 'category_parent' => $category_parent,
255
+ 'cat_name' => $cat['cat_name'],
256
+ 'category_description' => $category_description
257
+ );
258
+ $catarr = wp_slash( $catarr );
259
+
260
+ $id = wp_insert_category( $catarr );
261
+ if ( ! is_wp_error( $id ) ) {
262
+ if ( isset($cat['term_id']) )
263
+ $this->processed_terms[intval($cat['term_id'])] = $id;
264
+ } else {
265
+ printf( __( 'Failed to import category %s', 'wordpress-importer' ), esc_html($cat['category_nicename']) );
266
+ if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG )
267
+ echo ': ' . $id->get_error_message();
268
+ echo '<br />';
269
+ continue;
270
+ }
271
+
272
+ $this->process_termmeta( $cat, $id['term_id'] );
273
+ }
274
+
275
+ unset( $this->categories );
276
+ }
277
+
278
+ /**
279
+ * Create new post tags based on import information
280
+ *
281
+ * Doesn't create a tag if its slug already exists
282
+ */
283
+ function process_tags() {
284
+ $this->tags = apply_filters( 'wp_import_tags', $this->tags );
285
+
286
+ if ( empty( $this->tags ) )
287
+ return;
288
+
289
+ foreach ( $this->tags as $tag ) {
290
+ // if the tag already exists leave it alone
291
+ $term_id = term_exists( $tag['tag_slug'], 'post_tag' );
292
+ if ( $term_id ) {
293
+ if ( is_array($term_id) ) $term_id = $term_id['term_id'];
294
+ if ( isset($tag['term_id']) )
295
+ $this->processed_terms[intval($tag['term_id'])] = (int) $term_id;
296
+ continue;
297
+ }
298
+
299
+ $tag = wp_slash( $tag );
300
+ $tag_desc = isset( $tag['tag_description'] ) ? $tag['tag_description'] : '';
301
+ $tagarr = array( 'slug' => $tag['tag_slug'], 'description' => $tag_desc );
302
+
303
+ $id = wp_insert_term( $tag['tag_name'], 'post_tag', $tagarr );
304
+ if ( ! is_wp_error( $id ) ) {
305
+ if ( isset($tag['term_id']) )
306
+ $this->processed_terms[intval($tag['term_id'])] = $id['term_id'];
307
+ } else {
308
+ printf( __( 'Failed to import post tag %s', 'wordpress-importer' ), esc_html($tag['tag_name']) );
309
+ if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG )
310
+ echo ': ' . $id->get_error_message();
311
+ echo '<br />';
312
+ continue;
313
+ }
314
+
315
+ $this->process_termmeta( $tag, $id['term_id'] );
316
+ }
317
+
318
+ unset( $this->tags );
319
+ }
320
+
321
+ /**
322
+ * Create new terms based on import information
323
+ *
324
+ * Doesn't create a term its slug already exists
325
+ */
326
+ function process_terms() {
327
+ $this->terms = apply_filters( 'wp_import_terms', $this->terms );
328
+
329
+ if ( empty( $this->terms ) )
330
+ return;
331
+
332
+ foreach ( $this->terms as $term ) {
333
+ // if the term already exists in the correct taxonomy leave it alone
334
+ $term_id = term_exists( $term['slug'], $term['term_taxonomy'] );
335
+ if ( $term_id ) {
336
+ if ( is_array($term_id) ) $term_id = $term_id['term_id'];
337
+ if ( isset($term['term_id']) )
338
+ $this->processed_terms[intval($term['term_id'])] = (int) $term_id;
339
+ continue;
340
+ }
341
+
342
+ if ( empty( $term['term_parent'] ) ) {
343
+ $parent = 0;
344
+ } else {
345
+ $parent = term_exists( $term['term_parent'], $term['term_taxonomy'] );
346
+ if ( is_array( $parent ) ) $parent = $parent['term_id'];
347
+ }
348
+ $term = wp_slash( $term );
349
+ $description = isset( $term['term_description'] ) ? $term['term_description'] : '';
350
+ $termarr = array( 'slug' => $term['slug'], 'description' => $description, 'parent' => intval($parent) );
351
+
352
+ $id = wp_insert_term( $term['term_name'], $term['term_taxonomy'], $termarr );
353
+ if ( ! is_wp_error( $id ) ) {
354
+ if ( isset($term['term_id']) )
355
+ $this->processed_terms[intval($term['term_id'])] = $id['term_id'];
356
+ } else {
357
+ printf( __( 'Failed to import %s %s', 'wordpress-importer' ), esc_html($term['term_taxonomy']), esc_html($term['term_name']) );
358
+ if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG )
359
+ echo ': ' . $id->get_error_message();
360
+ echo '<br />';
361
+ continue;
362
+ }
363
+
364
+ $this->process_termmeta( $term, $id['term_id'] );
365
+ }
366
+
367
+ unset( $this->terms );
368
+ }
369
+
370
+ /**
371
+ * Add metadata to imported term.
372
+ *
373
+ * @since 0.6.2
374
+ *
375
+ * @param array $term Term data from WXR import.
376
+ * @param int $term_id ID of the newly created term.
377
+ */
378
+ protected function process_termmeta( $term, $term_id ) {
379
+ if ( ! isset( $term['termmeta'] ) ) {
380
+ $term['termmeta'] = array();
381
+ }
382
+
383
+ /**
384
+ * Filters the metadata attached to an imported term.
385
+ *
386
+ * @since 0.6.2
387
+ *
388
+ * @param array $termmeta Array of term meta.
389
+ * @param int $term_id ID of the newly created term.
390
+ * @param array $term Term data from the WXR import.
391
+ */
392
+ $term['termmeta'] = apply_filters( 'wp_import_term_meta', $term['termmeta'], $term_id, $term );
393
+
394
+ if ( empty( $term['termmeta'] ) ) {
395
+ return;
396
+ }
397
+
398
+ foreach ( $term['termmeta'] as $meta ) {
399
+ /**
400
+ * Filters the meta key for an imported piece of term meta.
401
+ *
402
+ * @since 0.6.2
403
+ *
404
+ * @param string $meta_key Meta key.
405
+ * @param int $term_id ID of the newly created term.
406
+ * @param array $term Term data from the WXR import.
407
+ */
408
+ $key = apply_filters( 'import_term_meta_key', $meta['key'], $term_id, $term );
409
+ if ( ! $key ) {
410
+ continue;
411
+ }
412
+
413
+ // Export gets meta straight from the DB so could have a serialized string
414
+ $value = maybe_unserialize( $meta['value'] );
415
+
416
+ add_term_meta( $term_id, $key, $value );
417
+
418
+ /**
419
+ * Fires after term meta is imported.
420
+ *
421
+ * @since 0.6.2
422
+ *
423
+ * @param int $term_id ID of the newly created term.
424
+ * @param string $key Meta key.
425
+ * @param mixed $value Meta value.
426
+ */
427
+ do_action( 'import_term_meta', $term_id, $key, $value );
428
+ }
429
+ }
430
+
431
+ /**
432
+ * Create new posts based on import information
433
+ *
434
+ * Posts marked as having a parent which doesn't exist will become top level items.
435
+ * Doesn't create a new post if: the post type doesn't exist, the given post ID
436
+ * is already noted as imported or a post with the same title and date already exists.
437
+ * Note that new/updated terms, comments and meta are imported for the last of the above.
438
+ */
439
+ function process_posts() {
440
+ $this->posts = apply_filters( 'wp_import_posts', $this->posts );
441
+
442
+ foreach ( $this->posts as $post ) {
443
+ $post = apply_filters( 'wp_import_post_data_raw', $post );
444
+
445
+ if ( ! post_type_exists( $post['post_type'] ) ) {
446
+ printf( __( 'Failed to import &#8220;%s&#8221;: Invalid post type %s', 'wordpress-importer' ),
447
+ esc_html($post['post_title']), esc_html($post['post_type']) );
448
+ echo '<br />';
449
+ do_action( 'wp_import_post_exists', $post );
450
+ continue;
451
+ }
452
+
453
+ if ( isset( $this->processed_posts[$post['post_id']] ) && ! empty( $post['post_id'] ) )
454
+ continue;
455
+
456
+ if ( $post['status'] == 'auto-draft' )
457
+ continue;
458
+
459
+ if ( 'nav_menu_item' == $post['post_type'] ) {
460
+ $this->process_menu_item( $post );
461
+ continue;
462
+ }
463
+
464
+ $post_type_object = get_post_type_object( $post['post_type'] );
465
+
466
+ $post_exists = post_exists( $post['post_title'], '', $post['post_date'] );
467
+
468
+ /**
469
+ * Filter ID of the existing post corresponding to post currently importing.
470
+ *
471
+ * Return 0 to force the post to be imported. Filter the ID to be something else
472
+ * to override which existing post is mapped to the imported post.
473
+ *
474
+ * @see post_exists()
475
+ * @since 0.6.2
476
+ *
477
+ * @param int $post_exists Post ID, or 0 if post did not exist.
478
+ * @param array $post The post array to be inserted.
479
+ */
480
+ $post_exists = apply_filters( 'wp_import_existing_post', $post_exists, $post );
481
+
482
+ if ( $post_exists && get_post_type( $post_exists ) == $post['post_type'] ) {
483
+ printf( __('%s &#8220;%s&#8221; already exists.', 'wordpress-importer'), $post_type_object->labels->singular_name, esc_html($post['post_title']) );
484
+ echo '<br />';
485
+ $comment_post_ID = $post_id = $post_exists;
486
+ $this->processed_posts[ intval( $post['post_id'] ) ] = intval( $post_exists );
487
+ } else {
488
+ $post_parent = (int) $post['post_parent'];
489
+ if ( $post_parent ) {
490
+ // if we already know the parent, map it to the new local ID
491
+ if ( isset( $this->processed_posts[$post_parent] ) ) {
492
+ $post_parent = $this->processed_posts[$post_parent];
493
+ // otherwise record the parent for later
494
+ } else {
495
+ $this->post_orphans[intval($post['post_id'])] = $post_parent;
496
+ $post_parent = 0;
497
+ }
498
+ }
499
+
500
+ // map the post author
501
+ $author = sanitize_user( $post['post_author'], true );
502
+ if ( isset( $this->author_mapping[$author] ) )
503
+ $author = $this->author_mapping[$author];
504
+ else
505
+ $author = (int) get_current_user_id();
506
+
507
+ $postdata = array(
508
+ 'import_id' => $post['post_id'], 'post_author' => $author, 'post_date' => $post['post_date'],
509
+ 'post_date_gmt' => $post['post_date_gmt'], 'post_content' => $post['post_content'],
510
+ 'post_excerpt' => $post['post_excerpt'], 'post_title' => $post['post_title'],
511
+ 'post_status' => $post['status'], 'post_name' => $post['post_name'],
512
+ 'comment_status' => $post['comment_status'], 'ping_status' => $post['ping_status'],
513
+ 'guid' => $post['guid'], 'post_parent' => $post_parent, 'menu_order' => $post['menu_order'],
514
+ 'post_type' => $post['post_type'], 'post_password' => $post['post_password']
515
+ );
516
+
517
+ $original_post_ID = $post['post_id'];
518
+ $postdata = apply_filters( 'wp_import_post_data_processed', $postdata, $post );
519
+
520
+ $postdata = wp_slash( $postdata );
521
+
522
+ if ( 'attachment' == $postdata['post_type'] ) {
523
+ $remote_url = ! empty($post['attachment_url']) ? $post['attachment_url'] : $post['guid'];
524
+
525
+ // try to use _wp_attached file for upload folder placement to ensure the same location as the export site
526
+ // e.g. location is 2003/05/image.jpg but the attachment post_date is 2010/09, see media_handle_upload()
527
+ $postdata['upload_date'] = $post['post_date'];
528
+ if ( isset( $post['postmeta'] ) ) {
529
+ foreach( $post['postmeta'] as $meta ) {
530
+ if ( $meta['key'] == '_wp_attached_file' ) {
531
+ if ( preg_match( '%^[0-9]{4}/[0-9]{2}%', $meta['value'], $matches ) )
532
+ $postdata['upload_date'] = $matches[0];
533
+ break;
534
+ }
535
+ }
536
+ }
537
+
538
+ $comment_post_ID = $post_id = $this->process_attachment( $postdata, $remote_url );
539
+ } else {
540
+ $comment_post_ID = $post_id = wp_insert_post( $postdata, true );
541
+ do_action( 'wp_import_insert_post', $post_id, $original_post_ID, $postdata, $post );
542
+ }
543
+
544
+ if ( is_wp_error( $post_id ) ) {
545
+ printf( __( 'Failed to import %s &#8220;%s&#8221;', 'wordpress-importer' ),
546
+ $post_type_object->labels->singular_name, esc_html($post['post_title']) );
547
+ if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG )
548
+ echo ': ' . $post_id->get_error_message();
549
+ echo '<br />';
550
+ continue;
551
+ }
552
+
553
+ if ( $post['is_sticky'] == 1 )
554
+ stick_post( $post_id );
555
+ }
556
+
557
+ // map pre-import ID to local ID
558
+ $this->processed_posts[intval($post['post_id'])] = (int) $post_id;
559
+
560
+ if ( ! isset( $post['terms'] ) )
561
+ $post['terms'] = array();
562
+
563
+ $post['terms'] = apply_filters( 'wp_import_post_terms', $post['terms'], $post_id, $post );
564
+
565
+ // add categories, tags and other terms
566
+ if ( ! empty( $post['terms'] ) ) {
567
+ $terms_to_set = array();
568
+ foreach ( $post['terms'] as $term ) {
569
+ // back compat with WXR 1.0 map 'tag' to 'post_tag'
570
+ $taxonomy = ( 'tag' == $term['domain'] ) ? 'post_tag' : $term['domain'];
571
+ $term_exists = term_exists( $term['slug'], $taxonomy );
572
+ $term_id = is_array( $term_exists ) ? $term_exists['term_id'] : $term_exists;
573
+ if ( ! $term_id ) {
574
+ $t = wp_insert_term( $term['name'], $taxonomy, array( 'slug' => $term['slug'] ) );
575
+ if ( ! is_wp_error( $t ) ) {
576
+ $term_id = $t['term_id'];
577
+ do_action( 'wp_import_insert_term', $t, $term, $post_id, $post );
578
+ } else {
579
+ printf( __( 'Failed to import %s %s', 'wordpress-importer' ), esc_html($taxonomy), esc_html($term['name']) );
580
+ if ( defined('IMPORT_DEBUG') && IMPORT_DEBUG )
581
+ echo ': ' . $t->get_error_message();
582
+ echo '<br />';
583
+ do_action( 'wp_import_insert_term_failed', $t, $term, $post_id, $post );
584
+ continue;
585
+ }
586
+ }
587
+ $terms_to_set[$taxonomy][] = intval( $term_id );
588
+ }
589
+
590
+ foreach ( $terms_to_set as $tax => $ids ) {
591
+ $tt_ids = wp_set_post_terms( $post_id, $ids, $tax );
592
+ do_action( 'wp_import_set_post_terms', $tt_ids, $ids, $tax, $post_id, $post );
593
+ }
594
+ unset( $post['terms'], $terms_to_set );
595
+ }
596
+
597
+ if ( ! isset( $post['comments'] ) )
598
+ $post['comments'] = array();
599
+
600
+ $post['comments'] = apply_filters( 'wp_import_post_comments', $post['comments'], $post_id, $post );
601
+
602
+ // add/update comments
603
+ if ( ! empty( $post['comments'] ) ) {
604
+ $num_comments = 0;
605
+ $inserted_comments = array();
606
+ foreach ( $post['comments'] as $comment ) {
607
+ $comment_id = $comment['comment_id'];
608
+ $newcomments[$comment_id]['comment_post_ID'] = $comment_post_ID;
609
+ $newcomments[$comment_id]['comment_author'] = $comment['comment_author'];
610
+ $newcomments[$comment_id]['comment_author_email'] = $comment['comment_author_email'];
611
+ $newcomments[$comment_id]['comment_author_IP'] = $comment['comment_author_IP'];
612
+ $newcomments[$comment_id]['comment_author_url'] = $comment['comment_author_url'];
613
+ $newcomments[$comment_id]['comment_date'] = $comment['comment_date'];
614
+ $newcomments[$comment_id]['comment_date_gmt'] = $comment['comment_date_gmt'];
615
+ $newcomments[$comment_id]['comment_content'] = $comment['comment_content'];
616
+ $newcomments[$comment_id]['comment_approved'] = $comment['comment_approved'];
617
+ $newcomments[$comment_id]['comment_type'] = $comment['comment_type'];
618
+ $newcomments[$comment_id]['comment_parent'] = $comment['comment_parent'];
619
+ $newcomments[$comment_id]['commentmeta'] = isset( $comment['commentmeta'] ) ? $comment['commentmeta'] : array();
620
+ if ( isset( $this->processed_authors[$comment['comment_user_id']] ) )
621
+ $newcomments[$comment_id]['user_id'] = $this->processed_authors[$comment['comment_user_id']];
622
+ }
623
+ ksort( $newcomments );
624
+
625
+ foreach ( $newcomments as $key => $comment ) {
626
+ // if this is a new post we can skip the comment_exists() check
627
+ if ( ! $post_exists || ! comment_exists( $comment['comment_author'], $comment['comment_date'] ) ) {
628
+ if ( isset( $inserted_comments[$comment['comment_parent']] ) )
629
+ $comment['comment_parent'] = $inserted_comments[$comment['comment_parent']];
630
+ $comment = wp_filter_comment( $comment );
631
+ $inserted_comments[$key] = wp_insert_comment( $comment );
632
+ do_action( 'wp_import_insert_comment', $inserted_comments[$key], $comment, $comment_post_ID, $post );
633
+
634
+ foreach( $comment['commentmeta'] as $meta ) {
635
+ $value = maybe_unserialize( $meta['value'] );
636
+ add_comment_meta( $inserted_comments[$key], $meta['key'], $value );
637
+ }
638
+
639
+ $num_comments++;
640
+ }
641
+ }
642
+ unset( $newcomments, $inserted_comments, $post['comments'] );
643
+ }
644
+
645
+ if ( ! isset( $post['postmeta'] ) )
646
+ $post['postmeta'] = array();
647
+
648
+ $post['postmeta'] = apply_filters( 'wp_import_post_meta', $post['postmeta'], $post_id, $post );
649
+
650
+ // add/update post meta
651
+ if ( ! empty( $post['postmeta'] ) ) {
652
+ foreach ( $post['postmeta'] as $meta ) {
653
+ $key = apply_filters( 'import_post_meta_key', $meta['key'], $post_id, $post );
654
+ $value = false;
655
+
656
+ if ( '_edit_last' == $key ) {
657
+ if ( isset( $this->processed_authors[intval($meta['value'])] ) )
658
+ $value = $this->processed_authors[intval($meta['value'])];
659
+ else
660
+ $key = false;
661
+ }
662
+
663
+ if ( $key ) {
664
+ // export gets meta straight from the DB so could have a serialized string
665
+ if ( ! $value )
666
+ $value = maybe_unserialize( $meta['value'] );
667
+
668
+ add_post_meta( $post_id, $key, $value );
669
+ do_action( 'import_post_meta', $post_id, $key, $value );
670
+
671
+ // if the post has a featured image, take note of this in case of remap
672
+ if ( '_thumbnail_id' == $key )
673
+ $this->featured_images[$post_id] = (int) $value;
674
+ }
675
+ }
676
+ }
677
+ }
678
+
679
+ unset( $this->posts );
680
+ }
681
+
682
+ /**
683
+ * Attempt to create a new menu item from import data
684
+ *
685
+ * Fails for draft, orphaned menu items and those without an associated nav_menu
686
+ * or an invalid nav_menu term. If the post type or term object which the menu item
687
+ * represents doesn't exist then the menu item will not be imported (waits until the
688
+ * end of the import to retry again before discarding).
689
+ *
690
+ * @param array $item Menu item details from WXR file
691
+ */
692
+ function process_menu_item( $item ) {
693
+ // skip draft, orphaned menu items
694
+ if ( 'draft' == $item['status'] )
695
+ return;
696
+
697
+ $menu_slug = false;
698
+ if ( isset($item['terms']) ) {
699
+ // loop through terms, assume first nav_menu term is correct menu
700
+ foreach ( $item['terms'] as $term ) {
701
+ if ( 'nav_menu' == $term['domain'] ) {
702
+ $menu_slug = $term['slug'];
703
+ break;
704
+ }
705
+ }
706
+ }
707
+
708
+ // no nav_menu term associated with this menu item
709
+ if ( ! $menu_slug ) {
710
+ _e( 'Menu item skipped due to missing menu slug', 'wordpress-importer' );
711
+ echo '<br />';
712
+ return;
713
+ }
714
+
715
+ $menu_id = term_exists( $menu_slug, 'nav_menu' );
716
+ if ( ! $menu_id ) {
717
+ printf( __( 'Menu item skipped due to invalid menu slug: %s', 'wordpress-importer' ), esc_html( $menu_slug ) );
718
+ echo '<br />';
719
+ return;
720
+ } else {
721
+ $menu_id = is_array( $menu_id ) ? $menu_id['term_id'] : $menu_id;
722
+ }
723
+
724
+ foreach ( $item['postmeta'] as $meta )
725
+ ${$meta['key']} = $meta['value'];
726
+
727
+ if ( 'taxonomy' == $_menu_item_type && isset( $this->processed_terms[intval($_menu_item_object_id)] ) ) {
728
+ $_menu_item_object_id = $this->processed_terms[intval($_menu_item_object_id)];
729
+ } else if ( 'post_type' == $_menu_item_type && isset( $this->processed_posts[intval($_menu_item_object_id)] ) ) {
730
+ $_menu_item_object_id = $this->processed_posts[intval($_menu_item_object_id)];
731
+ } else if ( 'custom' != $_menu_item_type ) {
732
+ // associated object is missing or not imported yet, we'll retry later
733
+ $this->missing_menu_items[] = $item;
734
+ return;
735
+ }
736
+
737
+ if ( isset( $this->processed_menu_items[intval($_menu_item_menu_item_parent)] ) ) {
738
+ $_menu_item_menu_item_parent = $this->processed_menu_items[intval($_menu_item_menu_item_parent)];
739
+ } else if ( $_menu_item_menu_item_parent ) {
740
+ $this->menu_item_orphans[intval($item['post_id'])] = (int) $_menu_item_menu_item_parent;
741
+ $_menu_item_menu_item_parent = 0;
742
+ }
743
+
744
+ // wp_update_nav_menu_item expects CSS classes as a space separated string
745
+ $_menu_item_classes = maybe_unserialize( $_menu_item_classes );
746
+ if ( is_array( $_menu_item_classes ) )
747
+ $_menu_item_classes = implode( ' ', $_menu_item_classes );
748
+
749
+ $args = array(
750
+ 'menu-item-object-id' => $_menu_item_object_id,
751
+ 'menu-item-object' => $_menu_item_object,
752
+ 'menu-item-parent-id' => $_menu_item_menu_item_parent,
753
+ 'menu-item-position' => intval( $item['menu_order'] ),
754
+ 'menu-item-type' => $_menu_item_type,
755
+ 'menu-item-title' => $item['post_title'],
756
+ 'menu-item-url' => $_menu_item_url,
757
+ 'menu-item-description' => $item['post_content'],
758
+ 'menu-item-attr-title' => $item['post_excerpt'],
759
+ 'menu-item-target' => $_menu_item_target,
760
+ 'menu-item-classes' => $_menu_item_classes,
761
+ 'menu-item-xfn' => $_menu_item_xfn,
762
+ 'menu-item-status' => $item['status']
763
+ );
764
+
765
+ $id = wp_update_nav_menu_item( $menu_id, 0, $args );
766
+ if ( $id && ! is_wp_error( $id ) )
767
+ $this->processed_menu_items[intval($item['post_id'])] = (int) $id;
768
+ }
769
+
770
+ /**
771
+ * If fetching attachments is enabled then attempt to create a new attachment
772
+ *
773
+ * @param array $post Attachment post details from WXR
774
+ * @param string $url URL to fetch attachment from
775
+ * @return int|WP_Error Post ID on success, WP_Error otherwise
776
+ */
777
+ function process_attachment( $post, $url ) {
778
+ if ( ! $this->fetch_attachments )
779
+ return new WP_Error( 'attachment_processing_error',
780
+ __( 'Fetching attachments is not enabled', 'wordpress-importer' ) );
781
+
782
+ // if the URL is absolute, but does not contain address, then upload it assuming base_site_url
783
+ if ( preg_match( '|^/[\w\W]+$|', $url ) )
784
+ $url = rtrim( $this->base_url, '/' ) . $url;
785
+
786
+ $upload = $this->fetch_remote_file( $url, $post );
787
+ if ( is_wp_error( $upload ) )
788
+ return $upload;
789
+
790
+ if ( $info = wp_check_filetype( $upload['file'] ) )
791
+ $post['post_mime_type'] = $info['type'];
792
+ else
793
+ return new WP_Error( 'attachment_processing_error', __('Invalid file type', 'wordpress-importer') );
794
+
795
+ $post['guid'] = $upload['url'];
796
+
797
+ // as per wp-admin/includes/upload.php
798
+ $post_id = wp_insert_attachment( $post, $upload['file'] );
799
+ wp_update_attachment_metadata( $post_id, wp_generate_attachment_metadata( $post_id, $upload['file'] ) );
800
+
801
+ // remap resized image URLs, works by stripping the extension and remapping the URL stub.
802
+ if ( preg_match( '!^image/!', $info['type'] ) ) {
803
+ $parts = pathinfo( $url );
804
+ $name = basename( $parts['basename'], ".{$parts['extension']}" ); // PATHINFO_FILENAME in PHP 5.2
805
+
806
+ $parts_new = pathinfo( $upload['url'] );
807
+ $name_new = basename( $parts_new['basename'], ".{$parts_new['extension']}" );
808
+
809
+ $this->url_remap[$parts['dirname'] . '/' . $name] = $parts_new['dirname'] . '/' . $name_new;
810
+ }
811
+
812
+ return $post_id;
813
+ }
814
+
815
+ /**
816
+ * Attempt to download a remote file attachment
817
+ *
818
+ * @param string $url URL of item to fetch
819
+ * @param array $post Attachment details
820
+ * @return array|WP_Error Local file location details on success, WP_Error otherwise
821
+ */
822
+ function fetch_remote_file( $url, $post ) {
823
+ // extract the file name and extension from the url
824
+ $file_name = basename( $url );
825
+
826
+ // get placeholder file in the upload dir with a unique, sanitized filename
827
+ $upload = wp_upload_bits( $file_name, 0, '', $post['upload_date'] );
828
+ if ( $upload['error'] )
829
+ return new WP_Error( 'upload_dir_error', $upload['error'] );
830
+
831
+ // fetch the remote url and write it to the placeholder file
832
+ /*EDITED CODE START*/
833
+ // fetch the remote url and write it to the placeholder file
834
+ $response = wp_remote_get( $url, array(
835
+ 'stream' => true,
836
+ 'filename' => $upload['file'],
837
+ ) );
838
+
839
+ // request failed
840
+ if ( is_wp_error( $response ) ) {
841
+ unlink( $upload['file'] );
842
+ return $response;
843
+ }
844
+
845
+ $code = (int) wp_remote_retrieve_response_code( $response );
846
+
847
+ // make sure the fetch was successful
848
+ if ( $code !== 200 ) {
849
+ unlink( $upload['file'] );
850
+ return new WP_Error(
851
+ 'import_file_error',
852
+ sprintf(
853
+ __( 'Remote server returned %1$d %2$s for %3$s', 'wordpress-importer' ),
854
+ $code,
855
+ get_status_header_desc( $code ),
856
+ $url
857
+ )
858
+ );
859
+ }
860
+
861
+ $filesize = filesize( $upload['file'] );
862
+ $headers = wp_remote_retrieve_headers( $response );
863
+ /*EDITED CODE END*/
864
+
865
+ if ( isset( $headers['content-length'] ) && $filesize != $headers['content-length'] ) {
866
+ @unlink( $upload['file'] );
867
+ return new WP_Error( 'import_file_error', __('Remote file is incorrect size', 'wordpress-importer') );
868
+ }
869
+
870
+ if ( 0 == $filesize ) {
871
+ @unlink( $upload['file'] );
872
+ return new WP_Error( 'import_file_error', __('Zero size file downloaded', 'wordpress-importer') );
873
+ }
874
+
875
+ $max_size = (int) $this->max_attachment_size();
876
+ if ( ! empty( $max_size ) && $filesize > $max_size ) {
877
+ @unlink( $upload['file'] );
878
+ return new WP_Error( 'import_file_error', sprintf(__('Remote file is too large, limit is %s', 'wordpress-importer'), size_format($max_size) ) );
879
+ }
880
+
881
+ // keep track of the old and new urls so we can substitute them later
882
+ $this->url_remap[$url] = $upload['url'];
883
+ $this->url_remap[$post['guid']] = $upload['url']; // r13735, really needed?
884
+ // keep track of the destination if the remote url is redirected somewhere else
885
+ if ( isset($headers['x-final-location']) && $headers['x-final-location'] != $url )
886
+ $this->url_remap[$headers['x-final-location']] = $upload['url'];
887
+
888
+ return $upload;
889
+ }
890
+
891
+ /**
892
+ * Attempt to associate posts and menu items with previously missing parents
893
+ *
894
+ * An imported post's parent may not have been imported when it was first created
895
+ * so try again. Similarly for child menu items and menu items which were missing
896
+ * the object (e.g. post) they represent in the menu
897
+ */
898
+ function backfill_parents() {
899
+ global $wpdb;
900
+
901
+ // find parents for post orphans
902
+ foreach ( $this->post_orphans as $child_id => $parent_id ) {
903
+ $local_child_id = $local_parent_id = false;
904
+ if ( isset( $this->processed_posts[$child_id] ) )
905
+ $local_child_id = $this->processed_posts[$child_id];
906
+ if ( isset( $this->processed_posts[$parent_id] ) )
907
+ $local_parent_id = $this->processed_posts[$parent_id];
908
+
909
+ if ( $local_child_id && $local_parent_id )
910
+ $wpdb->update( $wpdb->posts, array( 'post_parent' => $local_parent_id ), array( 'ID' => $local_child_id ), '%d', '%d' );
911
+ }
912
+
913
+ // all other posts/terms are imported, retry menu items with missing associated object
914
+ $missing_menu_items = $this->missing_menu_items;
915
+ foreach ( $missing_menu_items as $item )
916
+ $this->process_menu_item( $item );
917
+
918
+ // find parents for menu item orphans
919
+ foreach ( $this->menu_item_orphans as $child_id => $parent_id ) {
920
+ $local_child_id = $local_parent_id = 0;
921
+ if ( isset( $this->processed_menu_items[$child_id] ) )
922
+ $local_child_id = $this->processed_menu_items[$child_id];
923
+ if ( isset( $this->processed_menu_items[$parent_id] ) )
924
+ $local_parent_id = $this->processed_menu_items[$parent_id];
925
+
926
+ if ( $local_child_id && $local_parent_id )
927
+ update_post_meta( $local_child_id, '_menu_item_menu_item_parent', (int) $local_parent_id );
928
+ }
929
+ }
930
+
931
+ /**
932
+ * Use stored mapping information to update old attachment URLs
933
+ */
934
+ function backfill_attachment_urls() {
935
+ global $wpdb;
936
+ // make sure we do the longest urls first, in case one is a substring of another
937
+ uksort( $this->url_remap, array(&$this, 'cmpr_strlen') );
938
+
939
+ foreach ( $this->url_remap as $from_url => $to_url ) {
940
+ // remap urls in post_content
941
+ $wpdb->query( $wpdb->prepare("UPDATE {$wpdb->posts} SET post_content = REPLACE(post_content, %s, %s)", $from_url, $to_url) );
942
+ // remap enclosure urls
943
+ $result = $wpdb->query( $wpdb->prepare("UPDATE {$wpdb->postmeta} SET meta_value = REPLACE(meta_value, %s, %s) WHERE meta_key='enclosure'", $from_url, $to_url) );
944
+ }
945
+ }
946
+
947
+ /**
948
+ * Update _thumbnail_id meta to new, imported attachment IDs
949
+ */
950
+ function remap_featured_images() {
951
+ // cycle through posts that have a featured image
952
+ foreach ( $this->featured_images as $post_id => $value ) {
953
+ if ( isset( $this->processed_posts[$value] ) ) {
954
+ $new_id = $this->processed_posts[$value];
955
+ // only update if there's a difference
956
+ if ( $new_id != $value )
957
+ update_post_meta( $post_id, '_thumbnail_id', $new_id );
958
+ }
959
+ }
960
+ }
961
+
962
+ /**
963
+ * Parse a WXR file
964
+ *
965
+ * @param string $file Path to WXR file for parsing
966
+ * @return array Information gathered from the WXR file
967
+ */
968
+ function parse( $file ) {
969
+ $parser = new Acme_Demo_Setup_WXR_Parser();
970
+ return $parser->parse( $file );
971
+ }
972
+
973
+
974
+ /**
975
+ * Decide if the given meta key maps to information we will want to import
976
+ *
977
+ * @param string $key The meta key to check
978
+ * @return string|bool The key if we do want to import, false if not
979
+ */
980
+ function is_valid_meta_key( $key ) {
981
+ // skip attachment metadata since we'll regenerate it from scratch
982
+ // skip _edit_lock as not relevant for import
983
+ if ( in_array( $key, array( '_wp_attached_file', '_wp_attachment_metadata', '_edit_lock' ) ) )
984
+ return false;
985
+ return $key;
986
+ }
987
+
988
+ /**
989
+ * Decide whether or not the importer is allowed to create users.
990
+ * Default is true, can be filtered via import_allow_create_users
991
+ *
992
+ * @return bool True if creating users is allowed
993
+ */
994
+ function allow_create_users() {
995
+ return apply_filters( 'import_allow_create_users', true );
996
+ }
997
+
998
+
999
+ /**
1000
+ * Decide what the maximum file size for downloaded attachments is.
1001
+ * Default is 0 (unlimited), can be filtered via import_attachment_size_limit
1002
+ *
1003
+ * @return int Maximum attachment file size to import
1004
+ */
1005
+ function max_attachment_size() {
1006
+ return apply_filters( 'import_attachment_size_limit', 0 );
1007
+ }
1008
+
1009
+ /**
1010
+ * Added to http_request_timeout filter to force timeout at 60 seconds during import
1011
+ * @return int 300
1012
+ */
1013
+ function bump_request_timeout( $val ) {
1014
+ return 300;
1015
+ }
1016
+
1017
+ // return the difference in length between two strings
1018
+ function cmpr_strlen( $a, $b ) {
1019
+ return strlen($b) - strlen($a);
1020
+ }
1021
+ }
1022
+
1023
+ } // class_exists( 'Acme_Demo_Setup_Wp_Import' )
inc/hooks/after-demo-setup.php ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if( !class_exists( 'Acme_Demo_Setup_After_Import') ):
3
+
4
+ class Acme_Demo_Setup_After_Import {
5
+
6
+ /*update nav menu*/
7
+ function update_nav_menu( $acme_demo_setup_nav_data ){
8
+ $new_theme_navs = array();
9
+ $nav_menus = wp_get_nav_menus();
10
+ if ( ! empty( $nav_menus ) ) {
11
+ foreach ( $nav_menus as $nav_menu ) {
12
+ if ( is_object( $nav_menu ) ) {
13
+ foreach ( $acme_demo_setup_nav_data as $location => $location_name ) {
14
+ if ( $nav_menu->name == $location_name ) {
15
+ $new_theme_navs[ $location ] = $nav_menu->term_id;
16
+ }
17
+ }
18
+ }
19
+ }
20
+ }
21
+ set_theme_mod( 'nav_menu_locations', $new_theme_navs );
22
+ }
23
+
24
+ /*update WordPRess options for theme*/
25
+ function update_wp_options( $wp_options ) {
26
+
27
+ if ( ! empty( $wp_options ) ) {
28
+
29
+ foreach ( $wp_options as $option_key => $option_value ) {
30
+ if ( ! in_array( $option_key, array( 'blogname', 'blogdescription', 'show_on_front', 'page_on_front', 'page_for_posts' ) ) ) {
31
+ continue;
32
+ }
33
+
34
+ // Format the value based on option key.
35
+ switch ( $option_key ) {
36
+ case 'show_on_front':
37
+ if ( in_array( $option_value, array( 'posts', 'page' ) ) ) {
38
+ update_option( 'show_on_front', $option_value );
39
+ }
40
+ break;
41
+
42
+ case 'page_on_front':
43
+ case 'page_for_posts':
44
+ $page = get_page_by_title( $option_value );
45
+ if ( is_object( $page ) && $page->ID ) {
46
+ update_option( $option_key, $page->ID );
47
+ update_option( 'show_on_front', 'page' );
48
+ }
49
+ break;
50
+
51
+ default:
52
+ update_option( $option_key, sanitize_text_field( $option_value ) );
53
+ break;
54
+ }
55
+ }
56
+ }
57
+
58
+ return true;
59
+ }
60
+
61
+ function after_demo_import(){
62
+
63
+ /*update theme options*/
64
+ $acme_demo_setup_wp_options_data = apply_filters('acme_demo_setup_wp_options_data',array() );
65
+
66
+ if( !empty( $acme_demo_setup_wp_options_data ) ){
67
+ $this->update_wp_options( $acme_demo_setup_wp_options_data );
68
+ }
69
+
70
+ /*update theme menu*/
71
+ $acme_demo_setup_nav_data = apply_filters('acme_demo_setup_nav_data',array() );
72
+ if( !empty( $acme_demo_setup_nav_data ) ){
73
+ $this->update_nav_menu( $acme_demo_setup_nav_data );
74
+ }
75
+ }
76
+
77
+ }
78
+ endif;
79
+ $Acme_Demo_Setup_After_Import = new Acme_Demo_Setup_After_Import();
80
+ add_action( 'acme_demo_setup_after_import', array( $Acme_Demo_Setup_After_Import, 'after_demo_import' ) );
inc/hooks/before-demo-setup.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if( !class_exists( 'Acme_Demo_Setup_Before_Import') ):
3
+
4
+ class Acme_Demo_Setup_Before_Import {
5
+ /**
6
+ * Reset existing active widgets.
7
+ */
8
+ function reset_widgets() {
9
+ $sidebars_widgets = wp_get_sidebars_widgets();
10
+
11
+ // Reset active widgets.
12
+ foreach ( $sidebars_widgets as $key => $widgets ) {
13
+ $sidebars_widgets[ $key ] = array();
14
+ }
15
+
16
+ wp_set_sidebars_widgets( $sidebars_widgets );
17
+ }
18
+
19
+ /**
20
+ * Delete existing navigation menus.
21
+ */
22
+ function delete_nav_menus() {
23
+ $nav_menus = wp_get_nav_menus();
24
+
25
+ // Delete navigation menus.
26
+ if ( ! empty( $nav_menus ) ) {
27
+ foreach ( $nav_menus as $nav_menu ) {
28
+ wp_delete_nav_menu( $nav_menu->slug );
29
+ }
30
+ }
31
+ }
32
+
33
+ function before_demo_import() {
34
+ $this->reset_widgets();
35
+ $this->delete_nav_menus();
36
+ /**
37
+ * Remove theme modifications option.
38
+ */
39
+ remove_theme_mods();
40
+ }
41
+ }
42
+ endif;
43
+ $Acme_Demo_Setup_Before_Import = new Acme_Demo_Setup_Before_Import();
44
+ add_action( 'acme_demo_setup_before_import', array( $Acme_Demo_Setup_Before_Import, 'before_demo_import' ) );
inc/info.txt ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*What done in this plugin
2
+ 1. Renamed CEI_Core to Acme_Demo_Setup_CEI_Core
3
+ 2. Modify _import method to pass input of file
4
+ 3. Renamed CEI_Option to Acme_Demo_Setup_CEI_Option
5
+ 4. Remaning wie_available_widgets to acme_demo_setup_wie_available_widgets
6
+ 5. Renaming wie_process_import_file to acme_demo_setup_wie_process_import_file
7
+ 6. Renaming wie_import_data to acme_demo_setup_wie_import_data
8
+ 7. Renaming WP_Import to Acme_Demo_Setup_Wp_Import
9
+ 8. Renaming WXR_Parser to Acme_Demo_Setup_WXR_Parser
10
+ 9. Renaming WXR_Parser_SimpleXML to Acme_Demo_Setup_WXR_Parser_SimpleXML
11
+ 10. Renaming WXR_Parser_XML to Acme_Demo_Setup_WXR_Parser_XML
12
+ 11. Renaming WXR_Parser_Regex to Acme_Demo_Setup_WXR_Parser_Regex
13
+ 11. Remove unnecessary methods and functions
14
+ */
inc/init.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Load frameworks.
4
+ */
5
+ /*customizer export import*/
6
+ require_once( ACME_DEMO_SETUP_PATH . 'inc/frameworks/customizer-export-import/class-cei-option.php' );
7
+ require_once( ACME_DEMO_SETUP_PATH . 'inc/frameworks/customizer-export-import/class-cei-core.php' );
8
+
9
+ /*widget importer exporter*/
10
+ require_once( ACME_DEMO_SETUP_PATH . 'inc/frameworks/widget-importer-exporter/widgets.php' );
11
+ require_once( ACME_DEMO_SETUP_PATH . 'inc/frameworks/widget-importer-exporter/import.php' );
12
+
13
+ /*WordPress Importer*/
14
+ require_once( ACME_DEMO_SETUP_PATH . 'inc/frameworks/wordpress-importer/wordpress-importer.php' );
15
+
16
+ /*plugin hooks*/
17
+ require_once( ACME_DEMO_SETUP_PATH . 'inc/hooks/before-demo-setup.php' );
18
+ require_once( ACME_DEMO_SETUP_PATH . 'inc/hooks/after-demo-setup.php' );
19
+
20
+ /*upload screen*/
21
+ require_once( ACME_DEMO_SETUP_PATH . 'inc/admin/upload.php' );
readme.txt ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === Acme Demo Setup ===
2
+
3
+ Contributors: acmethemes, codersantosh
4
+ Tags: demo, dummydata, import, acmethemes, themes, oneclick, customizer, widget
5
+ Requires at least: 4.5
6
+ Tested up to: 4.7.4
7
+ Stable tag: 1.0.3
8
+ License: GPLv2 or later
9
+ License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
+
11
+ Setup you site with dummy data easily. Import settings, widgets and content with one click. Your dummy data must have ZIP file of xml, dat and wie file. Put all this three files on one ZIP folder and import the ZIP file and
12
+ your site will be ready within few seconds.
13
+
14
+ == Description ==
15
+
16
+ Setup you site with dummy data easily. Import settings, widgets and content with one click. Your dummy data must have ZIP file of xml, dat and wie file. Put all this three files on one ZIP folder and import the ZIP file and your site will be ready within few seconds.
17
+
18
+ == Installation ==
19
+
20
+ = From your WordPress dashboard =
21
+
22
+ 1. Visit 'Plugins > Add New'
23
+ 2. Search for 'acme-demo-setup'
24
+ 3. Activate Acme Demo Setup from Appearance > Plugins
25
+ 4. Go to the Appearance -> Acme Demo Setup and upload the ZIP file of dummy data.
26
+
27
+ = From WordPress.org =
28
+
29
+ 1. Download acme-demo-setup.
30
+ 2. Upload the 'acme-demo-setup' directory to your '/wp-content/plugins/' directory, using your favorite method (ftp, sftp, scp, etc...)
31
+ 3. Activate acme-demo-setup from your Appearance > Plugins page.
32
+ 4. Go to the Appearance -> Acme Demo Setup and upload the ZIP file of dummy data.
33
+
34
+ == Frequently Asked Questions ==
35
+
36
+ = I have activated the plugin. Where to find the plugin page to import data? =
37
+
38
+ You will find the import page in *wp-admin -> Appearance -> Acme Demo Setup*.
39
+
40
+ = How to automatically assign Menu Locations after the importer is done? =
41
+
42
+ You can do that, with the `acme_demo_setup_nav_data` action hook. The code would look something like this:
43
+
44
+ `if( !function_exists( 'prefix_demo_nav_data') ){
45
+ function prefix_demo_nav_data(){
46
+ $demo_navs = array(
47
+ 'one-page' => 'Front Page',
48
+ 'primary' => 'Inner Page'
49
+ );
50
+ return $demo_navs;
51
+ }
52
+ }
53
+ add_filter('acme_demo_setup_nav_data','prefix_demo_nav_data');`
54
+
55
+ = How to automatically assign "Front page" & "Posts page" after the importer is done? =
56
+ You can do that, with the `acme_demo_setup_wp_options_data` action hook. The code would look something like this:
57
+
58
+
59
+ `if( !function_exists( 'prefix_demo_wp_options_data') ){
60
+ function prefix_demo_wp_options_data(){
61
+ $wp_options = array(
62
+ 'blogname' => 'Theme Name',
63
+ 'page_on_front' => 'Home Page',
64
+ 'page_for_posts' => 'Blog',
65
+ );
66
+ return $wp_options;
67
+ }
68
+ }
69
+ add_filter('acme_demo_setup_wp_options_data','prefix_demo_wp_options_data');`
70
+
71
+ = What files we need to put on the demo zipped file ? =
72
+
73
+ You need a zip file of three files,
74
+ a. XML file for Data
75
+ B. DAT file for Customizer
76
+ C. WIE file for Widgets
77
+ and make the zip file of this theme files.
78
+
79
+ = Are you a theme author and want to integrate one click demo import on your own themes? =
80
+ One click demo import is very helpful for your theme users, recommend this Acme Demo Setup plugin for better user experience for your theme users.
81
+
82
+ = You are a theme user and facing the problem with the demo import? =
83
+ Contact to your theme author and provide the link of this plugin and request the author to integrate this plugin for your theme. It will be very easy to make the entire site.
84
+
85
+
86
+ = Got the issues on the plugin? =
87
+
88
+ If you have the issues on the plugin [Visit Support Page](https://wordpress.org/support/plugin/acme-demo-setup), so that we can solve the issues.
89
+
90
+
91
+ == Screenshots ==
92
+
93
+ 1. Acme Demo Setup
94
+
95
+ == Changelog ==
96
+
97
+ = 1.0.3
98
+ * Update : Read Me
99
+
100
+ = 1.0.2
101
+ * Fixed issue with Menu import in PHP 7
102
+
103
+ = 1.0.1
104
+ * Implement ajax to import
105
+
106
+ = 1.0.0
107
+ * Initial Release