Rara One Click Demo Import - Version 1.0.0

Version Description

Download this release

Release Info

Developer raratheme
Plugin Icon 128x128 Rara One Click Demo Import
Version 1.0.0
Comparing to
See all releases

Version 1.0.0

assets/css/style.css ADDED
@@ -0,0 +1,109 @@
1
+ /* Overriding WordPress native styles */
2
+
3
+ .rrdi h2 {
4
+ text-align: inherit;
5
+ }
6
+
7
+ .rrdi h2:first-child,
8
+ .rrdi h3:first-child {
9
+ margin-top: 0;
10
+ }
11
+
12
+ .rrdi hr {
13
+ margin: 2.62em 0;
14
+ }
15
+
16
+ .feature-section + hr {
17
+ margin-top: 0;
18
+ }
19
+
20
+ #wpbody select {
21
+ height: auto;
22
+ padding: .62em;
23
+ line-height: inherit;
24
+ }
25
+
26
+ .rrdi .notice {
27
+ display: block !important;
28
+ margin-top: 1.4em;
29
+ margin-bottom: 0;
30
+ }
31
+
32
+ /* Plugin elements */
33
+
34
+ .RRDI__demo-import-files {
35
+ width: 100%;
36
+ }
37
+
38
+ .RRDI__demo-import-preview-image-message {
39
+ font-style: italic;
40
+ }
41
+
42
+ /* Plugin title */
43
+
44
+ .RRDI__title:before {
45
+ width: auto;
46
+ height: auto;
47
+ font-size: inherit;
48
+ }
49
+
50
+ /* Plugin intro text */
51
+
52
+ .RRDI__intro-text ul {
53
+ padding: 0 4%;
54
+ list-style-type: square;
55
+ }
56
+
57
+ /* Plugin multi select import and Plugin file upload containers */
58
+
59
+ .RRDI__file-upload,
60
+ .RRDI__multi-select-import,
61
+ .RRDI__demo-import-notice:not(:empty) {
62
+ padding: 4%;
63
+ margin: 1.62em 0;
64
+ background-color: #ffffff;
65
+ border: 1px solid #e5e5e5;
66
+ }
67
+
68
+ .RRDI__file-upload {
69
+ margin: 0;
70
+ margin-bottom: -1px;
71
+ }
72
+
73
+ .RRDI__file-upload span {
74
+ font-size: .81em;
75
+ font-weight: normal;
76
+ opacity: .66;
77
+ }
78
+
79
+ .RRDI__demo-import-notice:not(:empty) {
80
+ border: 0;
81
+ border-left: 4px solid #00a0d2;
82
+ -webkit-box-shadow: 0 1px 1px 0 rgba(0,0,0,.1);
83
+ box-shadow: 0 1px 1px 0 rgba(0,0,0,.1);
84
+ }
85
+
86
+ [dir="rtl"] .RRDI__demo-import-notice:not(:empty) {
87
+ border: 0;
88
+ border-right: 4px solid #00a0d2;
89
+ }
90
+
91
+ /* Plugin button */
92
+
93
+ .RRDI__button-container {
94
+ margin-top: 1.62em;
95
+ }
96
+
97
+ /* AJAX loader */
98
+
99
+ .RRDI__ajax-loader {
100
+ font-size: 1.5em;
101
+ display: none;
102
+ }
103
+
104
+ .RRDI__ajax-loader .spinner {
105
+ display: inline-block;
106
+ float: none;
107
+ visibility: visible;
108
+ margin-bottom: 6px;
109
+ }
assets/js/script.js ADDED
@@ -0,0 +1,78 @@
1
+ jQuery( function ( $ ) {
2
+
3
+ $( '.js-rrdi-import-data' ).on( 'click', function () {
4
+ // Reset response div content.
5
+ $( '.js-rrdi-ajax-response' ).empty();
6
+
7
+ // Prepare data for the AJAX call
8
+ var data = new FormData();
9
+ data.append( 'action', 'rrdi_import_demo_data' );
10
+ data.append( 'security', rrdi.ajax_nonce );
11
+ data.append( 'selected', $( '#RRDI__demo-import-files' ).val() );
12
+ if ( $('#RRDI__content-file-upload').length ) {
13
+ data.append( 'content_file', $('#RRDI__content-file-upload')[0].files[0] );
14
+ }
15
+ if ( $('#RRDI__widget-file-upload').length ) {
16
+ data.append( 'widget_file', $('#RRDI__widget-file-upload')[0].files[0] );
17
+ }
18
+ if ( $('#RRDI__customizer-file-upload').length ) {
19
+ data.append( 'customizer_file', $('#RRDI__customizer-file-upload')[0].files[0] );
20
+ }
21
+
22
+ // AJAX call to import everything (content, widgets, before/after setup)
23
+ ajaxCall( data );
24
+
25
+ });
26
+
27
+ function ajaxCall( data ) {
28
+ $.ajax({
29
+ method: 'POST',
30
+ url: rrdi.ajax_url,
31
+ data: data,
32
+ contentType: false,
33
+ processData: false,
34
+ beforeSend: function() {
35
+ $( '.js-rrdi-ajax-loader' ).show();
36
+ }
37
+ })
38
+ .done( function( response ) {
39
+
40
+ if ( 'undefined' !== typeof response.status && 'newAJAX' === response.status ) {
41
+ ajaxCall( data );
42
+ }
43
+ else if ( 'undefined' !== typeof response.message ) {
44
+ $( '.js-rrdi-ajax-response' ).append( '<p>' + response.message + '</p>' );
45
+ $( '.js-rrdi-ajax-loader' ).hide();
46
+ }
47
+ else {
48
+ $( '.js-rrdi-ajax-response' ).append( '<div class="notice notice-error is-dismissible"><p>' + response + '</p></div>' );
49
+ $( '.js-rrdi-ajax-loader' ).hide();
50
+ }
51
+ })
52
+ .fail( function( error ) {
53
+ $( '.js-rrdi-ajax-response' ).append( '<div class="notice notice-error is-dismissible"><p>Error: ' + error.statusText + ' (' + error.status + ')' + '</p></div>' );
54
+ $( '.js-rrdi-ajax-loader' ).hide();
55
+ });
56
+ }
57
+
58
+ // Switch preview images on select change event, but only if the img element .js-rrdi-preview-image exists.
59
+ // Also switch the import notice (if it exists).
60
+ $( '#RRDI__demo-import-files' ).on( 'change', function(){
61
+ if ( $( '.js-rrdi-preview-image' ).length ) {
62
+
63
+ // Attempt to change the image, else display message for missing image.
64
+ var currentFilePreviewImage = rrdi.import_files[ this.value ]['import_preview_image_url'] || '';
65
+ $( '.js-rrdi-preview-image' ).prop( 'src', currentFilePreviewImage );
66
+ $( '.js-rrdi-preview-image-message' ).html( '' );
67
+
68
+ if ( '' === currentFilePreviewImage ) {
69
+ $( '.js-rrdi-preview-image-message' ).html( rrdi.texts.missing_preview_image );
70
+ }
71
+ }
72
+
73
+ // Update import notice.
74
+ var currentImportNotice = rrdi.import_files[ this.value ]['import_notice'] || '';
75
+ $( '.js-rrdi-demo-import-notice' ).html( currentImportNotice );
76
+ });
77
+
78
+ });
includes/class-rrdi-customizer-option.php ADDED
@@ -0,0 +1,24 @@
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
+ * Used in the Customizer importer.
7
+ *
8
+ * @since 1.1.1
9
+ * @package rara-demo-import
10
+ */
11
+
12
+ final class RRDI_Customizer_Option extends WP_Customize_Setting {
13
+
14
+ /**
15
+ * Import an option value for this setting.
16
+ *
17
+ * @since 1.1.1
18
+ * @param mixed $value The option value.
19
+ * @return void
20
+ */
21
+ public function import( $value ) {
22
+ $this->update( $value );
23
+ }
24
+ }
includes/class-rrdi-helpers.php ADDED
@@ -0,0 +1,610 @@
1
+ <?php
2
+ /**
3
+ * Static functions used in the rrdi plugin.
4
+ *
5
+ * @package rara-demo-import
6
+ */
7
+
8
+ /**
9
+ * Class with static helper functions.
10
+ */
11
+ class RRDI_Helpers {
12
+
13
+ /**
14
+ * Filter through the array of import files and get rid of those who do not comply.
15
+ *
16
+ * @param array $import_files list of arrays with import file details.
17
+ * @return array list of filtered arrays.
18
+ */
19
+ public static function validate_import_file_info( $import_files ) {
20
+ $filtered_import_file_info = array();
21
+
22
+ foreach ( $import_files as $import_file ) {
23
+ if ( self::is_import_file_info_format_correct( $import_file ) ) {
24
+ $filtered_import_file_info[] = $import_file;
25
+ }
26
+ }
27
+
28
+ return $filtered_import_file_info;
29
+ }
30
+
31
+
32
+ /**
33
+ * Helper function: a simple check for valid import file format.
34
+ *
35
+ * @param array $import_file_info array with import file details.
36
+ * @return boolean
37
+ */
38
+ private static function is_import_file_info_format_correct( $import_file_info ) {
39
+ if ( ( empty( $import_file_info['import_file_url'] ) && empty( $import_file_info['local_import_file'] ) ) || empty( $import_file_info['import_file_name'] ) ) {
40
+ return false;
41
+ }
42
+
43
+ return true;
44
+ }
45
+
46
+
47
+ /**
48
+ * Download import files. Content .xml and widgets .wie|.json files.
49
+ *
50
+ * @param array $import_file_info array with import file details.
51
+ * @param string $start_date string of date and time.
52
+ * @return array|WP_Error array of paths to the downloaded files or WP_Error object with error message.
53
+ */
54
+ public static function download_import_files( $import_file_info, $start_date = '' ) {
55
+
56
+ $downloaded_files = array();
57
+ $upload_dir = wp_upload_dir();
58
+ $upload_path = apply_filters( 'rrdi/upload_file_path', trailingslashit( $upload_dir['path'] ) );
59
+
60
+ // ----- Set content file path -----
61
+ // Check if 'import_file_url' is not defined. That would mean a local file.
62
+ if ( empty( $import_file_info['import_file_url'] ) ) {
63
+ if ( file_exists( $import_file_info['local_import_file'] ) ) {
64
+ $downloaded_files['content'] = $import_file_info['local_import_file'];
65
+ }
66
+ else {
67
+ return new WP_Error(
68
+ 'url_or_local_file_not_defined',
69
+ sprintf(
70
+ __( '"import_file_url" or "local_import_file" for %s%s%s are not defined!', 'rara-demo-import' ),
71
+ '<strong>',
72
+ $import_file_info['import_file_name'],
73
+ '</strong>'
74
+ )
75
+ );
76
+ }
77
+ }
78
+ else {
79
+
80
+ // Retrieve demo data content from the URL.
81
+ $demo_import_content = self::get_content_from_url( $import_file_info['import_file_url'], $import_file_info['import_file_name'] );
82
+
83
+ // Return from this function if there was an error.
84
+ if ( is_wp_error( $demo_import_content ) ) {
85
+ return $demo_import_content;
86
+ }
87
+
88
+ // Setup filename path to save the data content.
89
+ $demo_import_file_path = $upload_path . apply_filters( 'rrdi/downloaded_content_file_prefix', 'demo-content-import-file_' ) . $start_date . apply_filters( 'rrdi/downloaded_content_file_suffix_and_file_extension', '.xml' );
90
+
91
+ // Write data content to the file and return the file path on successful write.
92
+ $downloaded_files['content'] = self::write_to_file( $demo_import_content, $demo_import_file_path );
93
+
94
+ // Return from this function if there was an error.
95
+ if ( is_wp_error( $downloaded_files['content'] ) ) {
96
+ return $downloaded_files['content'];
97
+ }
98
+ }
99
+
100
+ // ----- Set widget file path -----
101
+ // Get widgets file as well. If defined!
102
+ if ( ! empty( $import_file_info['import_widget_file_url'] ) ) {
103
+
104
+ // Retrieve widget content from the URL.
105
+ $demo_import_widgets_content = self::get_content_from_url( $import_file_info['import_widget_file_url'], $import_file_info['import_file_name'] );
106
+
107
+ // Return from this function if there was an error.
108
+ if ( is_wp_error( $demo_import_widgets_content ) ) {
109
+ return $demo_import_widgets_content;
110
+ }
111
+
112
+ // Setup filename path to save the widget content.
113
+ $import_widgets_file_path = $upload_path . apply_filters( 'rrdi/downloaded_widgets_file_prefix', 'demo-widgets-import-file_' ) . $start_date . apply_filters( 'rrdi/downloaded_widgets_file_suffix_and_file_extension', '.json' );
114
+
115
+ // Write widget content to the file and return the file path on successful write.
116
+ $downloaded_files['widgets'] = self::write_to_file( $demo_import_widgets_content, $import_widgets_file_path );
117
+
118
+ // Return from this function if there was an error.
119
+ if ( is_wp_error( $downloaded_files['widgets'] ) ) {
120
+ return $downloaded_files['widgets'];
121
+ }
122
+ }
123
+ else if ( ! empty( $import_file_info['local_import_widget_file'] ) ) {
124
+ if ( file_exists( $import_file_info['local_import_widget_file'] ) ) {
125
+ $downloaded_files['widgets'] = $import_file_info['local_import_widget_file'];
126
+ }
127
+ }
128
+
129
+ // ----- Set customizer file path -----
130
+ // Get customizer import file as well. If defined!
131
+ if ( ! empty( $import_file_info['import_customizer_file_url'] ) ) {
132
+
133
+ // Retrieve customizer content from the URL.
134
+ $demo_import_customizer_content = self::get_content_from_url( $import_file_info['import_customizer_file_url'], $import_file_info['import_file_name'] );
135
+
136
+ // Return from this function if there was an error.
137
+ if ( is_wp_error( $demo_import_customizer_content ) ) {
138
+ return $demo_import_customizer_content;
139
+ }
140
+
141
+ // Setup filename path to save the customizer content.
142
+ $import_customizer_file_path = $upload_path . apply_filters( 'rrdi/downloaded_customizer_file_prefix', 'demo-customizer-import-file_' ) . $start_date . apply_filters( 'rrdi/downloaded_customizer_file_suffix_and_file_extension', '.dat' );
143
+
144
+ // Write customizer content to the file and return the file path on successful write.
145
+ $downloaded_files['customizer'] = self::write_to_file( $demo_import_customizer_content, $import_customizer_file_path );
146
+
147
+ // Return from this function if there was an error.
148
+ if ( is_wp_error( $downloaded_files['customizer'] ) ) {
149
+ return $downloaded_files['customizer'];
150
+ }
151
+ }
152
+ else if ( ! empty( $import_file_info['local_import_customizer_file'] ) ) {
153
+ if ( file_exists( $import_file_info['local_import_customizer_file'] ) ) {
154
+ $downloaded_files['customizer'] = $import_file_info['local_import_customizer_file'];
155
+ }
156
+ }
157
+
158
+ return $downloaded_files;
159
+ }
160
+
161
+
162
+ /**
163
+ * Helper function: get content from an url.
164
+ *
165
+ * @param string $url URL to the content file.
166
+ * @param string $file_name optional, name of the file (used in the error reports).
167
+ * @return string|WP_Error, content from the URL or WP_Error object with error message
168
+ */
169
+ private static function get_content_from_url( $url, $file_name = 'Import file' ) {
170
+
171
+ // Test if the URL to the file is defined.
172
+ if ( empty( $url ) ) {
173
+ return new WP_Error(
174
+ 'url_not_defined',
175
+ sprintf(
176
+ __( 'URL for %s%s%s file is not defined!', 'rara-demo-import' ),
177
+ '<strong>',
178
+ $file_name,
179
+ '</strong>'
180
+ )
181
+ );
182
+ }
183
+
184
+ // Get file content from the server.
185
+ $response = wp_remote_get(
186
+ $url,
187
+ array( 'timeout' => apply_filters( 'rrdi/timeout_for_downloading_import_file', 20 ) )
188
+ );
189
+
190
+ if ( is_wp_error( $response ) || 200 !== $response['response']['code'] ) {
191
+
192
+ // Collect the right format of error data (array or WP_Error).
193
+ $response_error = self::get_error_from_response( $response );
194
+
195
+ return new WP_Error(
196
+ 'file_fetching_error',
197
+ sprintf(
198
+ __( 'An error occurred while fetching %s%s%s file from the server!%sReason: %s - %s.', 'rara-demo-import' ),
199
+ '<strong>',
200
+ $file_name,
201
+ '</strong>',
202
+ '<br>',
203
+ $response_error['error_code'],
204
+ $response_error['error_message']
205
+ ) . '<br>' .
206
+ apply_filters( 'rrdi/message_after_file_fetching_error', '' )
207
+ );
208
+ }
209
+
210
+ // Return content retrieved from the URL.
211
+ return wp_remote_retrieve_body( $response );
212
+ }
213
+
214
+
215
+ /**
216
+ * Write content to a file.
217
+ *
218
+ * @param string $content content to be saved to the file.
219
+ * @param string $file_path file path where the content should be saved.
220
+ * @return string|WP_Error path to the saved file or WP_Error object with error message.
221
+ */
222
+ public static function write_to_file( $content, $file_path ) {
223
+
224
+ // Verify WP file-system credentials.
225
+ $verified_credentials = self::check_wp_filesystem_credentials();
226
+
227
+ if ( is_wp_error( $verified_credentials ) ) {
228
+ return $verified_credentials;
229
+ }
230
+
231
+ // By this point, the $wp_filesystem global should be working, so let's use it to create a file.
232
+ global $wp_filesystem;
233
+
234
+ if ( ! $wp_filesystem->put_contents( $file_path, $content ) ) {
235
+ return new WP_Error(
236
+ 'failed_writing_file_to_server',
237
+ sprintf(
238
+ __( 'An error occurred while writing file to your server! Tried to write a file to: %s%s.', 'rara-demo-import' ),
239
+ '<br>',
240
+ $file_path
241
+ )
242
+ );
243
+ }
244
+
245
+ // Return the file path on successful file write.
246
+ return $file_path;
247
+ }
248
+
249
+
250
+ /**
251
+ * Append content to the file.
252
+ *
253
+ * @param string $content content to be saved to the file.
254
+ * @param string $file_path file path where the content should be saved.
255
+ * @param string $separator_text separates the existing content of the file with the new content.
256
+ * @return boolean|WP_Error, path to the saved file or WP_Error object with error message.
257
+ */
258
+ public static function append_to_file( $content, $file_path, $separator_text = '' ) {
259
+
260
+ // Verify WP file-system credentials.
261
+ $verified_credentials = self::check_wp_filesystem_credentials();
262
+
263
+ if ( is_wp_error( $verified_credentials ) ) {
264
+ return $verified_credentials;
265
+ }
266
+
267
+ // By this point, the $wp_filesystem global should be working, so let's use it to create a file.
268
+ global $wp_filesystem;
269
+
270
+ $existing_data = '';
271
+ if ( file_exists( $file_path ) ) {
272
+ $existing_data = $wp_filesystem->get_contents( $file_path );
273
+ }
274
+
275
+ // Style separator.
276
+ $separator = PHP_EOL . '---' . $separator_text . '---' . PHP_EOL;
277
+
278
+ if ( ! $wp_filesystem->put_contents( $file_path, $existing_data . $separator . $content . PHP_EOL ) ) {
279
+ return new WP_Error(
280
+ 'failed_writing_file_to_server',
281
+ sprintf(
282
+ __( 'An error occurred while writing file to your server! Tried to write a file to: %s%s.', 'rara-demo-import' ),
283
+ '<br>',
284
+ $file_path
285
+ )
286
+ );
287
+ }
288
+
289
+ return true;
290
+ }
291
+
292
+
293
+ /**
294
+ * Get data from a file
295
+ *
296
+ * @param string $file_path file path where the content should be saved.
297
+ * @return string $data, content of the file or WP_Error object with error message.
298
+ */
299
+ public static function data_from_file( $file_path ) {
300
+
301
+ // Verify WP file-system credentials.
302
+ $verified_credentials = self::check_wp_filesystem_credentials();
303
+
304
+ if ( is_wp_error( $verified_credentials ) ) {
305
+ return $verified_credentials;
306
+ }
307
+
308
+ // By this point, the $wp_filesystem global should be working, so let's use it to read a file.
309
+ global $wp_filesystem;
310
+
311
+ $data = $wp_filesystem->get_contents( $file_path );
312
+
313
+ if ( ! $data ) {
314
+ return new WP_Error(
315
+ 'failed_reading_file_from_server',
316
+ sprintf(
317
+ __( 'An error occurred while reading a file from your server! Tried reading file from path: %s%s.', 'rara-demo-import' ),
318
+ '<br>',
319
+ $file_path
320
+ )
321
+ );
322
+ }
323
+
324
+ // Return the file data.
325
+ return $data;
326
+ }
327
+
328
+
329
+ /**
330
+ * Helper function: check for WP file-system credentials needed for reading and writing to a file.
331
+ *
332
+ * @return boolean|WP_Error
333
+ */
334
+ private static function check_wp_filesystem_credentials() {
335
+
336
+ // Check if the file-system method is 'direct', if not display an error.
337
+ if ( ! ( 'direct' === get_filesystem_method() ) ) {
338
+ return new WP_Error(
339
+ 'no_direct_file_access',
340
+ sprintf(
341
+ __( 'This WordPress page does not have %sdirect%s write file access. This plugin needs it in order to save the demo import xml file to the upload directory of your site. You can change this setting with these instructions: %s.', 'rara-demo-import' ),
342
+ '<strong>',
343
+ '</strong>',
344
+ '<a href="http://gregorcapuder.com/wordpress-how-to-set-direct-filesystem-method/" target="_blank">How to set <strong>direct</strong> filesystem method</a>'
345
+ )
346
+ );
347
+ }
348
+
349
+ // Get plugin page settings.
350
+ $plugin_page_setup = apply_filters( 'rrdi/plugin_page_setup', array(
351
+ 'parent_slug' => 'themes.php',
352
+ 'page_title' => esc_html__( 'Rara One Click Demo Import' , 'rara-demo-import' ),
353
+ 'menu_title' => esc_html__( 'Import Demo Data' , 'rara-demo-import' ),
354
+ 'capability' => 'import',
355
+ 'menu_slug' => 'rara-demo-import',
356
+ )
357
+ );
358
+
359
+ // Get user credentials for WP file-system API.
360
+ $demo_import_page_url = wp_nonce_url( $plugin_page_setup['parent_slug'] . '?page=' . $plugin_page_setup['menu_slug'], $plugin_page_setup['menu_slug'] );
361
+
362
+ if ( false === ( $creds = request_filesystem_credentials( $demo_import_page_url, '', false, false, null ) ) ) {
363
+ return new WP_error(
364
+ 'filesystem_credentials_could_not_be_retrieved',
365
+ __( 'An error occurred while retrieving reading/writing permissions to your server (could not retrieve WP filesystem credentials)!', 'rara-demo-import' )
366
+ );
367
+ }
368
+
369
+ // Now we have credentials, try to get the wp_filesystem running.
370
+ if ( ! WP_Filesystem( $creds ) ) {
371
+ return new WP_Error(
372
+ 'wrong_login_credentials',
373
+ __( 'Your WordPress login credentials don\'t allow to use WP_Filesystem!', 'rara-demo-import' )
374
+ );
375
+ }
376
+
377
+ return true;
378
+ }
379
+
380
+
381
+ /**
382
+ * Helper function: get the right format of response errors
383
+ *
384
+ * @param array|WP_Error $response array or WP_Error.
385
+ * @return array, with error code and error message.
386
+ */
387
+ private static function get_error_from_response( $response ) {
388
+ $response_error = array();
389
+
390
+ if ( is_array( $response ) ) {
391
+ $response_error['error_code'] = $response['response']['code'];
392
+ $response_error['error_message'] = $response['response']['message'];
393
+ }
394
+ else {
395
+ $response_error['error_code'] = $response->get_error_code();
396
+ $response_error['error_message'] = $response->get_error_message();
397
+ }
398
+
399
+ return $response_error;
400
+ }
401
+
402
+
403
+ /**
404
+ * Get log file path
405
+ *
406
+ * @param string $start_date date|time|timestamp to use in the log filename.
407
+ * @return string, path to the log file
408
+ */
409
+ public static function get_log_path( $start_date = '' ) {
410
+
411
+ $upload_dir = wp_upload_dir();
412
+ $upload_path = apply_filters( 'rrdi/upload_file_path', trailingslashit( $upload_dir['path'] ) );
413
+
414
+ $log_path = $upload_path . apply_filters( 'rrdi/log_file_prefix', 'log_file_' ) . $start_date . apply_filters( 'rrdi/log_file_suffix_and_file_extension', '.txt' );
415
+
416
+ self::register_file_as_media_attachment( $log_path );
417
+
418
+ return $log_path;
419
+ }
420
+
421
+
422
+ /**
423
+ * Register file as attachment to the Media page.
424
+ *
425
+ * @param string $log_path log file path.
426
+ * @return void
427
+ */
428
+ public static function register_file_as_media_attachment( $log_path ) {
429
+
430
+ // Check the type of file.
431
+ $log_mimes = array( 'txt' => 'text/plain' );
432
+ $filetype = wp_check_filetype( basename( $log_path ), apply_filters( 'rrdi/file_mimes', $log_mimes ) );
433
+
434
+ // Prepare an array of post data for the attachment.
435
+ $attachment = array(
436
+ 'guid' => self::get_log_url( $log_path ),
437
+ 'post_mime_type' => $filetype['type'],
438
+ 'post_title' => apply_filters( 'rrdi/attachment_prefix', esc_html__( 'Rara One Click Demo Import - ', 'rara-demo-import' ) ) . preg_replace( '/\.[^.]+#x2F;', '', basename( $log_path ) ),
439
+ 'post_content' => '',
440
+ 'post_status' => 'inherit',
441
+ );
442
+
443
+ // Insert the file as attachment in Media page.
444
+ $attach_id = wp_insert_attachment( $attachment, $log_path );
445
+ }
446
+
447
+
448
+ /**
449
+ * Get log file url
450
+ *
451
+ * @param string $log_path log path to use for the log filename.
452
+ * @return string, url to the log file.
453
+ */
454
+ public static function get_log_url( $log_path ) {
455
+
456
+ $upload_dir = wp_upload_dir();
457
+ $upload_url = apply_filters( 'rrdi/upload_file_url', trailingslashit( $upload_dir['url'] ) );
458
+
459
+ return $upload_url . basename( $log_path );
460
+ }
461
+
462
+
463
+ /**
464
+ * Check if the AJAX call is valid.
465
+ */
466
+ public static function verify_ajax_call() {
467
+
468
+ check_ajax_referer( 'rrdi-ajax-verification', 'security' );
469
+
470
+ // Check if user has the WP capability to import data.
471
+ if ( ! current_user_can( 'import' ) ) {
472
+ wp_die(
473
+ sprintf(
474
+ __( '%sYour user role isn\'t high enough. You don\'t have permission to import demo data.%s', 'rara-demo-import' ),
475
+ '<div class="notice notice-error"><p>',
476
+ '</p></div>'
477
+ )
478
+ );
479
+ }
480
+ }
481
+
482
+
483
+ /**
484
+ * Process uploaded files and return the paths to these files.
485
+ *
486
+ * @param array $uploaded_files $_FILES array form an AJAX request.
487
+ * @param string $log_file_path path to the log file.
488
+ * @return array of paths to the content import and widget import files.
489
+ */
490
+ public static function process_uploaded_files( $uploaded_files, $log_file_path ) {
491
+
492
+ // Variable holding the paths to the uploaded files.
493
+ $selected_import_files = array();
494
+
495
+ // Upload settings to disable form and type testing for AJAX uploads.
496
+ $upload_overrides = array(
497
+ 'test_form' => false,
498
+ 'test_type' => false,
499
+ );
500
+
501
+ // Handle demo content and widgets file upload.
502
+ $content_file_info = wp_handle_upload( $_FILES['content_file'], $upload_overrides );
503
+ $widget_file_info = wp_handle_upload( $_FILES['widget_file'], $upload_overrides );
504
+ $customizer_file_info = wp_handle_upload( $_FILES['customizer_file'], $upload_overrides );
505
+
506
+ if ( empty( $content_file_info['file'] ) || isset( $content_file_info['error'] ) ) {
507
+
508
+ // Write error to log file and send an AJAX response with the error.
509
+ self::log_error_and_send_ajax_response(
510
+ __( 'Please upload XML file for content import. If you want to import widgets or customizer settings only, please use Widget Importer & Exporter or the Customizer Export/Import plugin.', 'rara-demo-import' ),
511
+ $log_file_path,
512
+ esc_html__( 'Upload files', 'rara-demo-import' )
513
+ );
514
+ }
515
+
516
+ // Set uploaded content file.
517
+ $selected_import_files['content'] = $content_file_info['file'];
518
+
519
+ // Process widget import file.
520
+ if ( $widget_file_info && ! isset( $widget_file_info['error'] ) ) {
521
+
522
+ // Set uploaded widget file.
523
+ $selected_import_files['widgets'] = $widget_file_info['file'];
524
+ }
525
+ else {
526
+
527
+ // Add this error to log file.
528
+ $log_added = self::append_to_file(
529
+ sprintf(
530
+ __( 'Widget file was not uploaded. Error: %s', 'rara-demo-import' ),
531
+ $widget_file_info['error']
532
+ ),
533
+ $log_file_path,
534
+ esc_html__( 'Upload files' , 'rara-demo-import' )
535
+ );
536
+ }
537
+
538
+ // Process Customizer import file.
539
+ if ( $customizer_file_info && ! isset( $customizer_file_info['error'] ) ) {
540
+
541
+ // Set uploaded widget file.
542
+ $selected_import_files['customizer'] = $customizer_file_info['file'];
543
+ }
544
+ else {
545
+
546
+ // Add this error to log file.
547
+ $log_added = self::append_to_file(
548
+ sprintf(
549
+ __( 'Customizer file was not uploaded. Error: %s', 'rara-demo-import' ),
550
+ $customizer_file_info['error']
551
+ ),
552
+ $log_file_path,
553
+ esc_html__( 'Upload files' , 'rara-demo-import' )
554
+ );
555
+ }
556
+
557
+ // Add this message to log file.
558
+ $log_added = self::append_to_file(
559
+ __( 'The import files were successfully uploaded!', 'rara-demo-import' ) . self::import_file_info( $selected_import_files ),
560
+ $log_file_path,
561
+ esc_html__( 'Upload files' , 'rara-demo-import' )
562
+ );
563
+
564
+ // Return array with paths of uploaded files.
565
+ return $selected_import_files;
566
+ }
567
+
568
+
569
+ /**
570
+ * Get import file information and max execution time.
571
+ *
572
+ * @param array $selected_import_files array of selected import files.
573
+ */
574
+ public static function import_file_info( $selected_import_files ) {
575
+ return PHP_EOL .
576
+ sprintf(
577
+ __( 'Initial max execution time = %s', 'rara-demo-import' ),
578
+ ini_get( 'max_execution_time' )
579
+ ) . PHP_EOL .
580
+ sprintf(
581
+ __( 'Files info:%1$sSite URL = %2$s%1$sData file = %3$s%1$sWidget file = %4$s%1$sCustomizer file = %5$s', 'rara-demo-import' ),
582
+ PHP_EOL,
583
+ get_site_url(),
584
+ $selected_import_files['content'],
585
+ empty( $selected_import_files['widgets'] ) ? esc_html__( 'not defined!', 'rara-demo-import' ) : $selected_import_files['widgets'],
586
+ empty( $selected_import_files['customizer'] ) ? esc_html__( 'not defined!', 'rara-demo-import' ) : $selected_import_files['customizer']
587
+ );
588
+ }
589
+
590
+
591
+ /**
592
+ * Write the error to the log file and send the AJAX response.
593
+ *
594
+ * @param string $error_text text to display in the log file and in the AJAX response.
595
+ * @param string $log_file_path path to the log file.
596
+ * @param string $separator title separating the old and new content.
597
+ */
598
+ public static function log_error_and_send_ajax_response( $error_text, $log_file_path, $separator = '' ) {
599
+
600
+ // Add this error to log file.
601
+ $log_added = self::append_to_file(
602
+ $error_text,
603
+ $log_file_path,
604
+ $separator
605
+ );
606
+
607
+ // Send JSON Error response to the AJAX call.
608
+ wp_send_json( $error_text );
609
+ }
610
+ }
includes/class-rrdi-importer.php ADDED
@@ -0,0 +1,69 @@
1
+ <?php
2
+ /**
3
+ * Class for declaring the importer used in the Rara One Click Demo Import plugin
4
+ *
5
+ * @package rara-demo-import
6
+ */
7
+
8
+ class RRDI_Importer {
9
+
10
+ private $importer;
11
+
12
+ public function __construct( $importer_options = array(), $logger = null ) {
13
+
14
+ // Include files that are needed for WordPress Importer v2.
15
+ $this->include_required_files();
16
+
17
+ // Set the WordPress Importer v2 as the importer used in this plugin.
18
+ // More: https://github.com/humanmade/WordPress-Importer.
19
+ $this->importer = new RRDI_WXR_Importer( $importer_options );
20
+
21
+ // Set logger to the importer.
22
+ if ( ! empty( $logger ) ) {
23
+ $this->set_logger( $logger );
24
+ }
25
+ }
26
+
27
+ /**
28
+ * Include required files.
29
+ */
30
+ private function include_required_files() {
31
+ defined( 'WP_LOAD_IMPORTERS' ) || define( 'WP_LOAD_IMPORTERS', true );
32
+ require ABSPATH . '/wp-admin/includes/class-wp-importer.php';
33
+ require RRDI_PATH . 'includes/class-rrdi-wxr-importer.php';
34
+ }
35
+
36
+ /**
37
+ * Imports content from a WordPress export file.
38
+ *
39
+ * @param string $data_file path to xml file, file with WordPress export data.
40
+ */
41
+ public function import( $data_file ) {
42
+ $this->importer->import( $data_file );
43
+ }
44
+
45
+ /**
46
+ * Set the logger used in the import
47
+ *
48
+ * @param object $logger logger instance.
49
+ */
50
+ public function set_logger( $logger ) {
51
+ $this->importer->set_logger( $logger );
52
+ }
53
+
54
+ /**
55
+ * Get all protected variables from the HM_WXR_Importer needed for continuing the import.
56
+ */
57
+ public function get_importer_data() {
58
+ return $this->importer->get_importer_data();
59
+ }
60
+
61
+ /**
62
+ * Sets all protected variables from the HM_WXR_Importer needed for continuing the import.
63
+ *
64
+ * @param array $data with set variables.
65
+ */
66
+ public function set_importer_data( $data ) {
67
+ $this->importer->set_importer_data( $data );
68
+ }
69
+ }
includes/class-rrdi-include-files.php ADDED
@@ -0,0 +1,23 @@
1
+ <?php
2
+ /**
3
+ * Include files.
4
+ *
5
+ * @package rara-demo-import
6
+ */
7
+
8
+ /**
9
+ * Rara One Click Demo Import class, so we don't have to worry about namespaces.
10
+ */
11
+ class RRDI_Theme_Demo_Include_Files {
12
+
13
+ function __construct()
14
+ {
15
+ // Include files.
16
+ require RRDI_PATH . 'includes/class-rrdi-helpers.php';
17
+ require RRDI_PATH . 'includes/class-rrdi-importer.php';
18
+ require RRDI_PATH . 'includes/vendor/class-rrdi-widget-importer.php';
19
+ require RRDI_PATH . 'includes/vendor/class-rrdi-customizer-importer.php';
20
+ require RRDI_PATH . 'includes/class-rrdi-logger.php';
21
+ }
22
+ }
23
+ new RRDI_Theme_Demo_Include_Files;
includes/class-rrdi-init.php ADDED
@@ -0,0 +1,38 @@
1
+ <?php
2
+ /**
3
+ * Display admin error message if PHP version is older than 5.3.2.
4
+ * Otherwise execute the main plugin class.
5
+ */
6
+ class RDDI_init
7
+ {
8
+ function __construct()
9
+ {
10
+ $this->rddi_init_version_check();
11
+ }
12
+
13
+ function rddi_init_version_check()
14
+ {
15
+ if ( version_compare( phpversion(), '5.3.2', '<' ) ) {
16
+
17
+ /**
18
+ * Display an admin error notice when PHP is older the version 5.3.2.
19
+ * Hook it to the 'admin_notices' action.
20
+ */
21
+ function rrdi_old_php_admin_error_notice() {
22
+ $message = sprintf( esc_html__( 'The %2$sRara One Click Demo Import%3$s plugin requires %2$sPHP 5.3.2+%3$s to run properly. Please contact your hosting company and ask them to update the PHP version of your site to at least PHP 5.3.2.%4$s Your current version of PHP: %2$s%1$s%3$s', 'rara-demo-import' ), phpversion(), '<strong>', '</strong>', '<br>' );
23
+
24
+ printf( '<div class="notice notice-error"><p>%1$s</p></div>', wp_kses_post( $message ) );
25
+ }
26
+ add_action( 'admin_notices', 'rrdi_old_php_admin_error_notice' );
27
+ }
28
+ else {
29
+
30
+ // Require main plugin file.
31
+ require RRDI_PATH . 'includes/class-rrdi-main.php';
32
+
33
+ // Instantiate the main plugin class *Singleton*.
34
+ $Theme_Demo_Import = RRDI_Theme_Demo_Import::getInstance();
35
+ }
36
+ }
37
+ }
38
+ new RDDI_init;
includes/class-rrdi-logger.php ADDED
@@ -0,0 +1,64 @@
1
+ <?php
2
+ /**
3
+ * Logger class used in the Rara One Click Demo Import plugin
4
+ *
5
+ * @package rara-demo-import
6
+ */
7
+
8
+ // Include files.
9
+ require RRDI_PATH . 'includes/extras/class-logger.php';
10
+ require RRDI_PATH . 'includes/extras/class-logger-cli.php';
11
+
12
+ class RRDI_Logger extends HM_WP_Importer_Logger_CLI {
13
+
14
+ /**
15
+ * Variable for front-end error display.
16
+ */
17
+ public $error_output = '';
18
+
19
+ /**
20
+ * Overwritten log function from HM_WP_Importer_Logger_CLI.
21
+ *
22
+ * Logs with an arbitrary level.
23
+ *
24
+ * @param mixed $level level of reporting.
25
+ * @param string $message log message.
26
+ * @param array $context context to the log message.
27
+ */
28
+ public function log( $level, $message, array $context = array() ) {
29
+
30
+ // Save error messages for front-end display.
31
+ $this->error_output( $level, $message, $context = array() );
32
+
33
+ if ( $this->level_to_numeric( $level ) < $this->level_to_numeric( $this->min_level ) ) {
34
+ return;
35
+ }
36
+
37
+ printf(
38
+ '[%s] %s' . PHP_EOL,
39
+ strtoupper( $level ),
40
+ $message
41
+ );
42
+ }
43
+
44
+
45
+ /**
46
+ * Save messages for error output.
47
+ * Only the messages greater then Error.
48
+ *
49
+ * @param mixed $level level of reporting.
50
+ * @param string $message log message.
51
+ * @param array $context context to the log message.
52
+ */
53
+ public function error_output( $level, $message, array $context = array() ) {
54
+ if ( $this->level_to_numeric( $level ) < $this->level_to_numeric( 'error' ) ) {
55
+ return;
56
+ }
57
+
58
+ $this->error_output .= sprintf(
59
+ '[%s] %s<br>',
60
+ strtoupper( $level ),
61
+ $message
62
+ );
63
+ }
64
+ }
includes/class-rrdi-main.php ADDED
@@ -0,0 +1,683 @@
1
+ <?php
2
+ /**
3
+ * Main Rara One Click Demo Import plugin class/file.
4
+ *
5
+ * @package rara-demo-import
6
+ */
7
+ /**
8
+ * Rara One Click Demo Import class, so we don't have to worry about namespaces.
9
+ */
10
+ class RRDI_Theme_Demo_Import {
11
+
12
+ /**
13
+ * @var $instance the reference to *Singleton* instance of this class
14
+ */
15
+ private static $instance;
16
+
17
+ /**
18
+ * Private variables used throughout the plugin.
19
+ */
20
+ private $importer, $plugin_page, $import_files, $logger, $log_file_path, $selected_index, $selected_import_files, $microtime, $frontend_error_messages, $ajax_call_number;
21
+
22
+
23
+ /**
24
+ * Returns the *Singleton* instance of this class.
25
+ *
26
+ * @return Theme_Demo_Import the *Singleton* instance.
27
+ */
28
+ public static function getInstance() {
29
+ if ( null === static::$instance ) {
30
+ static::$instance = new static();
31
+ }
32
+
33
+ return static::$instance;
34
+ }
35
+
36
+
37
+ /**
38
+ * Class construct function, to initiate the plugin.
39
+ * Protected constructor to prevent creating a new instance of the
40
+ * *Singleton* via the `new` operator from outside of this class.
41
+ */
42
+ protected function __construct() {
43
+ require RRDI_PATH . 'includes/class-rrdi-include-files.php';
44
+ // Actions.
45
+ add_action( 'admin_menu', array( $this, 'create_plugin_page' ) );
46
+ add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
47
+ add_action( 'wp_ajax_rrdi_import_demo_data', array( $this, 'import_demo_data_ajax_callback' ) );
48
+ add_action( 'after_setup_theme', array( $this, 'setup_plugin_with_filter_data' ) );
49
+ add_action( 'plugins_loaded', array( $this, 'load_textdomain' ) );
50
+ }
51
+
52
+
53
+ /**
54
+ * Private clone method to prevent cloning of the instance of the *Singleton* instance.
55
+ *
56
+ * @return void
57
+ */
58
+ private function __clone() {}
59
+
60
+
61
+ /**
62
+ * Private unserialize method to prevent unserializing of the *Singleton* instance.
63
+ *
64
+ * @return void
65
+ */
66
+ private function __wakeup() {}
67
+
68
+
69
+ /**
70
+ * Creates the plugin page and a submenu item in WP Appearance menu.
71
+ */
72
+ public function create_plugin_page() {
73
+ $plugin_page_setup = apply_filters( 'rrdi/plugin_page_setup', array(
74
+ 'parent_slug' => 'themes.php',
75
+ 'page_title' => esc_html__( 'Rara One Click Demo Import' , 'rara-demo-import' ),
76
+ 'menu_title' => esc_html__( 'Import Demo Content' , 'rara-demo-import' ),
77
+ 'capability' => 'import',
78
+ 'menu_slug' => 'rara-demo-import',
79
+ )
80
+ );
81
+
82
+ $this->plugin_page = add_submenu_page( $plugin_page_setup['parent_slug'], $plugin_page_setup['page_title'], $plugin_page_setup['menu_title'], $plugin_page_setup['capability'], $plugin_page_setup['menu_slug'], array( $this, 'display_plugin_page' ) );
83
+ }
84
+
85
+
86
+ /**
87
+ * Plugin page display.
88
+ */
89
+ public function display_plugin_page() {
90
+ ?>
91
+
92
+ <div class="RRDI__intro-notice notice notice-warning is-dismissible">
93
+ <p><?php $msg = __( 'Before you begin, make sure all the required plugins are activated.', 'rara-demo-import' ); echo apply_filters( 'rrdi_before_import_msg', $msg); ?>
94
+ </p>
95
+ </div>
96
+
97
+ <div class="rrdi wrap about-wrap">
98
+
99
+ <h1><?php esc_html_e( 'Rara One Click Demo Import', 'rara-demo-import' ); ?></h1>
100
+
101
+ <?php
102
+
103
+ // Display warrning if PHP safe mode is enabled, since we wont be able to change the max_execution_time.
104
+ if ( ini_get( 'safe_mode' ) ) {
105
+ printf(
106
+ esc_html__( '%sWarning: your server is using %sPHP safe mode%s. This means that you might experience server timeout errors.%s', 'rara-demo-import' ),
107
+ '<div class="notice notice-warning is-dismissible"><p>',
108
+ '<strong>',
109
+ '</strong>',
110
+ '</p></div>'
111
+ );
112
+ }
113
+
114
+ // Start output buffer for displaying the plugin intro text.
115
+ ob_start();
116
+ ?>
117
+
118
+ <div class="RRDI__intro-text">
119
+
120
+ <p class="about-description">
121
+ <?php esc_html_e( 'Upload your theme’s live demo content and settings with a click. If your theme comes with the demo content bundled with it, just click “Import Now” button. Otherwise, select files to import and click “Import Now”. As simple as that.', 'rara-demo-import' ); ?>
122
+ </p>
123
+
124
+ <h3><?php esc_html_e( 'The following data will be imported:', 'rara-demo-import' ); ?></h3>
125
+
126
+ <ul>
127
+ <li><?php esc_html_e( 'Posts', 'rara-demo-import' ); ?></li>
128
+ <li><?php esc_html_e( 'Pages', 'rara-demo-import' ); ?></li>
129
+ <li><?php esc_html_e( 'Images', 'rara-demo-import' ); ?></li>
130
+ <li><?php esc_html_e( 'Widgets', 'rara-demo-import' ); ?></li>
131
+ <li><?php esc_html_e( 'Menus', 'rara-demo-import' ); ?></li>
132
+ <li><?php esc_html_e( 'Settings', 'rara-demo-import' ); ?></li>
133
+ </ul>
134
+
135
+ <p><strong><?php esc_html_e( 'NOTE: Your existing content will NOT be deleted or modified.', 'rara-demo-import' ); ?></strong></p>
136
+
137
+ <hr>
138
+
139
+ </div>
140
+
141
+ <?php
142
+ $plugin_intro_text = ob_get_clean();
143
+
144
+ // Display the plugin intro text (can be replaced with custom text through the filter below).
145
+ echo wp_kses_post( apply_filters( 'rrdi/plugin_intro_text', $plugin_intro_text ) );
146
+ ?>
147
+
148
+
149
+ <?php if ( empty( $this->import_files ) ) : ?>
150
+
151
+ <div class="notice notice-info is-dismissible">
152
+ <p><?php esc_html_e( 'No predefined import files are available in this theme. Please upload the import files manually.', 'rara-demo-import' ); ?></p>
153
+ </div>
154
+
155
+ <div class="RRDI__file-upload-container">
156
+
157
+ <h2><?php esc_html_e( 'Please, select the following files.', 'rara-demo-import' ); ?></h2>
158
+
159
+ <div class="RRDI__file-upload">
160
+ <h3><label for="content-file-upload"><?php esc_html_e( 'Choose a XML file for content import:', 'rara-demo-import' ); ?></label></h3>
161
+ <input id="RRDI__content-file-upload" type="file" name="content-file-upload">
162
+ </div>
163
+
164
+ <div class="RRDI__file-upload">
165
+ <h3><label for="widget-file-upload"><?php esc_html_e( 'Choose a WIE or JSON file for widget import:', 'rara-demo-import' ); ?></label> <span><?php esc_html_e( '(*optional)', 'rara-demo-import' ); ?></span></h3>
166
+ <input id="RRDI__widget-file-upload" type="file" name="widget-file-upload">
167
+ </div>
168
+
169
+ <div class="RRDI__file-upload">
170
+ <h3><label for="customizer-file-upload"><?php esc_html_e( 'Choose a DAT file for customizer import:', 'rara-demo-import' ); ?></label> <span><?php esc_html_e( '(*optional)', 'rara-demo-import' ); ?></span></h3>
171
+ <input id="RRDI__customizer-file-upload" type="file" name="customizer-file-upload">
172
+ </div>
173
+
174
+ </div>
175
+
176
+ <?php elseif ( 1 < count( $this->import_files ) ) : ?>
177
+
178
+ <div class="RRDI__multi-select-import">
179
+
180
+ <h2><?php esc_html_e( 'Choose which demo you want to import:', 'rara-demo-import' ); ?></h2>
181
+
182
+ <select id="RRDI__demo-import-files" class="RRDI__demo-import-files">
183
+ <?php foreach ( $this->import_files as $index => $import_file ) : ?>
184
+ <option value="<?php echo esc_attr( $index ); ?>">
185
+ <?php echo esc_html( $import_file['import_file_name'] ); ?>
186
+ </option>
187
+ <?php endforeach; ?>
188
+ </select>
189
+
190
+ <?php
191
+ // Check if at least one preview image is defined, so we can prepare the structure for display.
192
+ $preview_image_is_defined = false;
193
+ foreach ( $this->import_files as $import_file ) {
194
+ if ( isset( $import_file['import_preview_image_url'] ) ) {
195
+ $preview_image_is_defined = true;
196
+ break;
197
+ }
198
+ }
199
+
200
+ if ( $preview_image_is_defined ) :
201
+ ?>
202
+
203
+ <div class="RRDI__demo-import-preview-container">
204
+
205
+ <p><?php esc_html_e( 'Import preview:', 'rara-demo-import' ); ?></p>
206
+
207
+ <p class="RRDI__demo-import-preview-image-message js-rrdi-preview-image-message"><?php
208
+ if ( ! isset( $this->import_files[0]['import_preview_image_url'] ) ) {
209
+ esc_html_e( 'No preview image defined for this import.', 'rara-demo-import' );
210
+ }
211
+ // Leave the img tag below and the p tag above available for later changes via JS.
212
+ ?></p>
213
+
214
+ <img id="RRDI__demo-import-preview-image" class="js-rrdi-preview-image" src="<?php echo ! empty( $this->import_files[0]['import_preview_image_url'] ) ? esc_url( $this->import_files[0]['import_preview_image_url'] ) : ''; ?>">
215
+
216
+ </div>
217
+
218
+ <?php endif; ?>
219
+
220
+ </div>
221
+
222
+ <?php endif; ?>
223
+
224
+ <div class="RRDI__demo-import-notice js-rrdi-demo-import-notice"><?php
225
+ if ( is_array( $this->import_files ) && ! empty( $this->import_files[0]['import_notice'] ) ) {
226
+ echo wp_kses_post( $this->import_files[0]['import_notice'] );
227
+ }
228
+ ?></div>
229
+
230
+ <p class="RRDI__button-container">
231
+ <button class="RRDI__button button button-hero button-primary js-rrdi-import-data"><?php esc_html_e( 'Import Now', 'rara-demo-import' ); ?></button>
232
+ <span><?php esc_html_e( 'Click the button to beign the importing process. Please be patient, the process might take a few minutes.', 'rara-demo-import' ); ?></span>
233
+ </p>
234
+
235
+ <p class="RRDI__ajax-loader js-rrdi-ajax-loader">
236
+ <span class="spinner"></span> <?php esc_html_e( 'Importing now, please wait!', 'rara-demo-import' ); ?>
237
+ </p>
238
+
239
+ <div class="RRDI__response js-rrdi-ajax-response"></div>
240
+
241
+ </div>
242
+
243
+ <?php
244
+ }
245
+
246
+
247
+ /**
248
+ * Enqueue admin scripts (JS and CSS)
249
+ *
250
+ * @param string $hook holds info on which admin page you are currently loading.
251
+ */
252
+ public function admin_enqueue_scripts( $hook ) {
253
+
254
+ // Enqueue the scripts only on the plugin page.
255
+ if ( $this->plugin_page === $hook ) {
256
+ wp_enqueue_script( 'rrdi-main-js', RRDI_URL . 'assets/js/script.js' , array( 'jquery', 'jquery-form' ), RRDI_VERSION );
257
+
258
+ wp_localize_script( 'rrdi-main-js', 'rrdi',
259
+ array(
260
+ 'ajax_url' => admin_url( 'admin-ajax.php' ),
261
+ 'ajax_nonce' => wp_create_nonce( 'rrdi-ajax-verification' ),
262
+ 'import_files' => $this->import_files,
263
+ 'texts' => array(
264
+ 'missing_preview_image' => esc_html__( 'No preview image defined for this import.', 'rara-demo-import' ),
265
+ ),
266
+ )
267
+ );
268
+
269
+ wp_enqueue_style( 'rrdi-main-css', RRDI_URL . 'assets/css/style.css', array() , RRDI_VERSION );
270
+ }
271
+ }
272
+
273
+
274
+ /**
275
+ * Main AJAX callback function for:
276
+ * 1. prepare import files (uploaded or predefined via filters)
277
+ * 2. import content
278
+ * 3. before widgets import setup (optional)
279
+ * 4. import widgets (optional)
280
+ * 5. import customizer options (optional)
281
+ * 6. after import setup (optional)
282
+ */
283
+ public function import_demo_data_ajax_callback() {
284
+
285
+ // Try to update PHP memory limit (so that it does not run out of it).
286
+ ini_set( 'memory_limit', apply_filters( 'rrdi/import_memory_limit', '350M' ) );
287
+
288
+ // Verify if the AJAX call is valid (checks nonce and current_user_can).
289
+ RRDI_Helpers::verify_ajax_call();
290
+
291
+ // Is this a new AJAX call to continue the previous import?
292
+ $use_existing_importer_data = $this->get_importer_data();
293
+
294
+ if ( ! $use_existing_importer_data ) {
295
+
296
+ // Set the AJAX call number.
297
+ $this->ajax_call_number = empty( $this->ajax_call_number ) ? 0 : $this->ajax_call_number;
298
+
299
+ // Error messages displayed on front page.
300
+ $this->frontend_error_messages = '';
301
+
302
+ // Create a date and time string to use for demo and log file names.
303
+ $demo_import_start_time = date( apply_filters( 'rrdi/date_format_for_file_names', 'Y-m-d__H-i-s' ) );
304
+
305
+ // Define log file path.
306
+ $this->log_file_path = RRDI_Helpers::get_log_path( $demo_import_start_time );
307
+
308
+ // Get selected file index or set it to 0.
309
+ $this->selected_index = empty( $_POST['selected'] ) ? 0 : absint( $_POST['selected'] );
310
+
311
+ /**
312
+ * 1. Prepare import files.
313
+ * Manually uploaded import files or predefined import files via filter: rrdi/import_files
314
+ */
315
+ if ( ! empty( $_FILES ) ) { // Using manual file uploads?
316
+
317
+ // Get paths for the uploaded files.
318
+ $this->selected_import_files = RRDI_Helpers::process_uploaded_files( $_FILES, $this->log_file_path );
319
+
320
+ // Set the name of the import files, because we used the uploaded files.
321
+ $this->import_files[ $this->selected_index ]['import_file_name'] = esc_html__( 'Manually uploaded files', 'rara-demo-import' );
322
+ }
323
+ elseif ( ! empty( $this->import_files[ $this->selected_index ] ) ) { // Use predefined import files from wp filter: rrdi/import_files.
324
+
325
+ // Download the import files (content and widgets files) and save it to variable for later use.
326
+ $this->selected_import_files = RRDI_Helpers::download_import_files(
327
+ $this->import_files[ $this->selected_index ],
328
+ $demo_import_start_time
329
+ );
330
+
331
+ // Check Errors.
332
+ if ( is_wp_error( $this->selected_import_files ) ) {
333
+
334
+ // Write error to log file and send an AJAX response with the error.
335
+ RRDI_Helpers::log_error_and_send_ajax_response(
336
+ $this->selected_import_files->get_error_message(),
337
+ $this->log_file_path,
338
+ esc_html__( 'Downloaded files', 'rara-demo-import' )
339
+ );
340
+ }
341
+
342
+ // Add this message to log file.
343
+ $log_added = RRDI_Helpers::append_to_file(
344
+ sprintf(
345
+ __( 'The import files for: %s were successfully downloaded!', 'rara-demo-import' ),
346
+ $this->import_files[ $this->selected_index ]['import_file_name']
347
+ ) . RRDI_Helpers::import_file_info( $this->selected_import_files ),
348
+ $this->log_file_path,
349
+ esc_html__( 'Downloaded files' , 'rara-demo-import' )
350
+ );
351
+ }
352
+ else {
353
+
354
+ // Send JSON Error response to the AJAX call.
355
+ wp_send_json( esc_html__( 'No import files specified!', 'rara-demo-import' ) );
356
+ }
357
+ }
358
+
359
+ /**
360
+ * 2. Import content.
361
+ * Returns any errors greater then the "error" logger level, that will be displayed on front page.
362
+ */
363
+ $this->frontend_error_messages .= $this->import_content( $this->selected_import_files['content'] );
364
+
365
+ /**
366
+ * 3. Before widgets import setup.
367
+ */
368
+ $action = 'rrdi/before_widgets_import';
369
+ if ( ( false !== has_action( $action ) ) && empty( $this->frontend_error_messages ) ) {
370
+
371
+ // Run the before_widgets_import action to setup other settings.
372
+ $this->do_import_action( $action, $this->import_files[ $this->selected_index ] );
373
+ }
374
+
375
+ /**
376
+ * 4. Import widgets.
377
+ */
378
+ if ( ! empty( $this->selected_import_files['widgets'] ) && empty( $this->frontend_error_messages ) ) {
379
+ $this->import_widgets( $this->selected_import_files['widgets'] );
380
+ }
381
+
382
+ /**
383
+ * 5. Import customize options.
384
+ */
385
+ if ( ! empty( $this->selected_import_files['customizer'] ) && empty( $this->frontend_error_messages ) ) {
386
+ $this->import_customizer( $this->selected_import_files['customizer'] );
387
+ }
388
+
389
+ /**
390
+ * 6. After import setup.
391
+ */
392
+ $action = 'rrdi/after_import';
393
+ if ( ( false !== has_action( $action ) ) && empty( $this->frontend_error_messages ) ) {
394
+
395
+ // Run the after_import action to setup other settings.
396
+ $this->do_import_action( $action, $this->import_files[ $this->selected_index ] );
397
+ }
398
+
399
+ // Display final messages (success or error messages).
400
+ if ( empty( $this->frontend_error_messages ) ) {
401
+ $response['message'] = sprintf(
402
+ __( '%1$s%3$sCompleted Successfully!%4$s%2$sThe process has finished. Please check your page and make sure that everything has been imported correctly. If you want, you can now deactivate the %3$sRara One Click Demo Import%4$s plugin.%5$s', 'rara-demo-import' ),
403
+ '<div class="notice notice-success"><p>',
404
+ '<br>',
405
+ '<strong>',
406
+ '</strong>',
407
+ '</p></div>'
408
+ );
409
+ }
410
+ else {
411
+ $response['message'] = $this->frontend_error_messages . '<br>';
412
+ $response['message'] .= sprintf(
413
+ __( '%1$sUnfortunately, demo import has finished with some errors.%2$sMore details about the errors can be found in this %3$s%5$slog file%6$s%4$s%7$s', 'rara-demo-import' ),
414
+ '<div class="notice notice-error"><p>',
415
+ '<br>',
416
+ '<strong>',
417
+ '</strong>',
418
+ '<a href="' . RRDI_Helpers::get_log_url( $this->log_file_path ) .'" target="_blank">',
419
+ '</a>',
420
+ '</p></div>'
421
+ );
422
+ }
423
+
424
+ wp_send_json( $response );
425
+ }
426
+
427
+
428
+ /**
429
+ * Import content from an WP XML file.
430
+ *
431
+ * @param string $import_file_path path to the import file.
432
+ */
433
+ private function import_content( $import_file_path ) {
434
+
435
+ $this->microtime = microtime( true );
436
+
437
+ // This should be replaced with multiple AJAX calls (import in smaller chunks)
438
+ // so that it would not come to the Internal Error, because of the PHP script timeout.
439
+ // Also this function has no effect when PHP is running in safe mode
440
+ // http://php.net/manual/en/function.set-time-limit.php.
441
+ // Increase PHP max execution time.
442
+ set_time_limit( apply_filters( 'rrdi/set_time_limit_for_demo_data_import', 300 ) );
443
+
444
+ // Disable import of authors.
445
+ add_filter( 'wxr_importer.pre_process.user', '__return_false' );
446
+
447
+ // Check, if we need to send another AJAX request and set the importing author to the current user.
448
+ add_filter( 'wxr_importer.pre_process.post', array( $this, 'new_ajax_request_maybe' ) );
449
+
450
+ // Disables generation of multiple image sizes (thumbnails) in the content import step.
451
+ if ( ! apply_filters( 'rrdi/regenerate_thumbnails_in_content_import', true ) ) {
452
+ add_filter( 'intermediate_image_sizes_advanced',
453
+ function() {
454
+ return null;
455
+ }
456
+ );
457
+ }
458
+
459
+ // Import content.
460
+ if ( ! empty( $import_file_path ) ) {
461
+ ob_start();
462
+ $this->importer->import( $import_file_path );
463
+ $message = ob_get_clean();
464
+
465
+ // Add this message to log file.
466
+ $log_added = RRDI_Helpers::append_to_file(
467
+ $message . PHP_EOL . esc_html__( 'Max execution time after content import = ' , 'rara-demo-import' ) . ini_get( 'max_execution_time' ),
468
+ $this->log_file_path,
469
+ esc_html__( 'Importing content' , 'rara-demo-import' )
470
+ );
471
+ }
472
+
473
+ // Delete content importer data for current import from DB.
474
+ delete_transient( 'RRDI_importer_data' );
475
+
476
+ // Return any error messages for the front page output (errors, critical, alert and emergency level messages only).
477
+ return $this->logger->error_output;
478
+ }
479
+
480
+
481
+ /**
482
+ * Import widgets from WIE or JSON file.
483
+ *
484
+ * @param string $widget_import_file_path path to the widget import file.
485
+ */
486
+ private function import_widgets( $widget_import_file_path ) {
487
+
488
+ // Widget import results.
489
+ $results = array();
490
+
491
+ // Create an instance of the Widget Importer.
492
+ $widget_importer = new RRDI_Widget_Importer();
493
+
494
+ // Import widgets.
495
+ if ( ! empty( $widget_import_file_path ) ) {
496
+
497
+ // Import widgets and return result.
498
+ $results = $widget_importer->import_widgets( $widget_import_file_path );
499
+ }
500
+
501
+ // Check for errors.
502
+ if ( is_wp_error( $results ) ) {
503
+
504
+ // Write error to log file and send an AJAX response with the error.
505
+ RRDI_Helpers::log_error_and_send_ajax_response(
506
+ $results->get_error_message(),
507
+ $this->log_file_path,
508
+ esc_html__( 'Importing widgets', 'rara-demo-import' )
509
+ );
510
+ }
511
+
512
+ ob_start();
513
+ $widget_importer->format_results_for_log( $results );
514
+ $message = ob_get_clean();
515
+
516
+ // Add this message to log file.
517
+ $log_added = RRDI_Helpers::append_to_file(
518
+ $message,
519
+ $this->log_file_path,
520
+ esc_html__( 'Importing widgets' , 'rara-demo-import' )
521
+ );
522
+ }
523
+
524
+
525
+ /**
526
+ * Import customizer from a DAT file, generated by the Customizer Export/Import plugin.
527
+ *
528
+ * @param string $customizer_import_file_path path to the customizer import file.
529
+ */
530
+ private function import_customizer( $customizer_import_file_path ) {
531
+
532
+ // Try to import the customizer settings.
533
+ $results = RRDI_Customizer_Importer::import_customizer_options( $customizer_import_file_path );
534
+
535
+ // Check for errors.
536
+ if ( is_wp_error( $results ) ) {
537
+
538
+ // Write error to log file and send an AJAX response with the error.
539
+ RRDI_Helpers::log_error_and_send_ajax_response(
540
+ $results->get_error_message(),
541
+ $this->log_file_path,
542
+ esc_html__( 'Importing customizer settings', 'rara-demo-import' )
543
+ );
544
+ }
545
+
546
+ // Add this message to log file.
547
+ $log_added = RRDI_Helpers::append_to_file(
548
+ esc_html__( 'Customizer settings import finished!', 'rara-demo-import' ),
549
+ $this->log_file_path,
550
+ esc_html__( 'Importing customizer settings' , 'rara-demo-import' )
551
+ );
552
+ }
553
+
554
+
555
+ /**
556
+ * Setup other things in the passed wp action.
557
+ *
558
+ * @param string $action the action name to be executed.
559
+ * @param array $selected_import with information about the selected import.
560
+ */
561
+ private function do_import_action( $action, $selected_import ) {
562
+
563
+ ob_start();
564
+ do_action( $action, $selected_import );
565
+ $message = ob_get_clean();
566
+
567
+ // Add this message to log file.
568
+ $log_added = RRDI_Helpers::append_to_file(
569
+ $message,
570
+ $this->log_file_path,
571
+ $action
572
+ );
573
+ }
574
+
575
+
576
+ /**
577
+ * Check if we need to create a new AJAX request, so that server does not timeout.
578
+ *
579
+ * @param array $data current post data.
580
+ * @return array
581
+ */
582
+ public function new_ajax_request_maybe( $data ) {
583
+ $time = microtime( true ) - $this->microtime;
584
+
585
+ // We should make a new ajax call, if the time is right.
586
+ if ( $time > apply_filters( 'rrdi/time_for_one_ajax_call', 25 ) ) {
587
+ $this->ajax_call_number++;
588
+ $this->set_importer_data();
589
+
590
+ $response = array(
591
+ 'status' => 'newAJAX',
592
+ 'message' => 'New AJAX request!: ' . $time,
593
+ );
594
+
595
+ // Add any output to the log file and clear the buffers.
596
+ $message = ob_get_clean();
597
+
598
+ // Add message to log file.
599
+ $log_added = RRDI_Helpers::append_to_file(
600
+ __( 'Completed AJAX call number: ' , 'rara-demo-import' ) . $this->ajax_call_number . PHP_EOL . $message,
601
+ $this->log_file_path,
602
+ ''
603
+ );
604
+
605
+ wp_send_json( $response );
606
+ }
607
+
608
+ // Set importing author to the current user.
609
+ // Fixes the [WARNING] Could not find the author for ... log warning messages.
610
+ $current_user_obj = wp_get_current_user();
611
+ $data['post_author'] = $current_user_obj->user_login;
612
+
613
+ return $data;
614
+ }
615
+
616
+ /**
617
+ * Set current state of the content importer, so we can continue the import with new AJAX request.
618
+ */
619
+ private function set_importer_data() {
620
+ $data = array(
621
+ 'frontend_error_messages' => $this->frontend_error_messages,
622
+ 'ajax_call_number' => $this->ajax_call_number,
623
+ 'log_file_path' => $this->log_file_path,
624
+ 'selected_index' => $this->selected_index,
625
+ 'selected_import_files' => $this->selected_import_files,
626
+ );
627
+
628
+ $data = array_merge( $data, $this->importer->get_importer_data() );
629
+
630
+ set_transient( 'RRDI_importer_data', $data, 0.5 * HOUR_IN_SECONDS );
631
+ }
632
+
633
+ /**
634
+ * Get content importer data, so we can continue the import with this new AJAX request.
635
+ */
636
+ private function get_importer_data() {
637
+ if ( $data = get_transient( 'RRDI_importer_data' ) ) {
638
+ $this->frontend_error_messages = empty( $data['frontend_error_messages'] ) ? '' : $data['frontend_error_messages'];
639
+ $this->ajax_call_number = empty( $data['ajax_call_number'] ) ? 1 : $data['ajax_call_number'];
640
+ $this->log_file_path = empty( $data['log_file_path'] ) ? '' : $data['log_file_path'];
641
+ $this->selected_index = empty( $data['selected_index'] ) ? 0 : $data['selected_index'];
642
+ $this->selected_import_files = empty( $data['selected_import_files'] ) ? array() : $data['selected_import_files'];
643
+ $this->importer->set_importer_data( $data );
644
+
645
+ return true;
646
+ }
647
+ return false;
648
+ }
649
+
650
+ /**
651
+ * Load the plugin textdomain, so that translations can be made.
652
+ */
653
+ public function load_textdomain() {
654
+ load_plugin_textdomain( 'rara-demo-import', false, plugin_basename( dirname( __FILE__ ) ) . '/languages' );
655
+ }
656
+
657
+
658
+ /**
659
+ * Get data from filters, after the theme has loaded and instantiate the importer.
660
+ */
661
+ public function setup_plugin_with_filter_data() {
662
+
663
+ // Get info of import data files and filter it.
664
+ $this->import_files = RRDI_Helpers::validate_import_file_info( apply_filters( 'rrdi/import_files', array() ) );
665
+
666
+ // Importer options array.
667
+ $importer_options = apply_filters( 'rrdi/importer_options', array(
668
+ 'fetch_attachments' => true,
669
+ ) );
670
+
671
+ // Logger options for the logger used in the importer.
672
+ $logger_options = apply_filters( 'rrdi/logger_options', array(
673
+ 'logger_min_level' => 'warning',
674
+ ) );
675
+
676
+ // Configure logger instance and set it to the importer.
677
+ $this->logger = new RRDI_Logger();
678
+ $this->logger->min_level = $logger_options['logger_min_level'];
679
+
680
+ // Create importer instance with proper parameters.
681
+ $this->importer = new RRDI_Importer( $importer_options, $this->logger );
682
+ }
683
+ }
includes/class-rrdi-wxr-importer.php ADDED
@@ -0,0 +1,51 @@
1
+ <?php
2
+ /**
3
+ * WXR importer class used in the Rara One Click Demo Import plugin.
4
+ * Needed to extend the HM_WXR_Importer class to get/set the importer protected variables,
5
+ * for use in the multiple AJAX calls.
6
+ *
7
+ * @package rara-demo-import
8
+ */
9
+
10
+ // Include files.
11
+ require RRDI_PATH . 'includes/extras/class-wxr-importer.php';
12
+
13
+ class RRDI_WXR_Importer extends HM_WXR_Importer {
14
+
15
+ public function __construct( $options = array() ) {
16
+ parent::__construct( $options );
17
+
18
+ // Set current user to $mapping variable.
19
+ // Fixes the [WARNING] Could not find the author for ... log warning messages.
20
+ $current_user_obj = wp_get_current_user();
21
+ $this->mapping['user_slug'][ $current_user_obj->user_login ] = $current_user_obj->ID;
22
+ }
23
+
24
+ /**
25
+ * Get all protected variables from the HM_WXR_Importer needed for continuing the import.
26
+ */
27
+ public function get_importer_data() {
28
+ return array(
29
+ 'mapping' => $this->mapping,
30
+ 'requires_remapping' => $this->requires_remapping,
31
+ 'exists' => $this->exists,
32
+ 'user_slug_override' => $this->user_slug_override,
33
+ 'url_remap' => $this->url_remap,
34
+ 'featured_images' => $this->featured_images,
35
+ );
36
+ }
37
+
38
+ /**
39
+ * Sets all protected variables from the HM_WXR_Importer needed for continuing the import.
40
+ *
41
+ * @param array $data with set variables.
42
+ */
43
+ public function set_importer_data( $data ) {
44
+ $this->mapping = empty( $data['mapping'] ) ? array() : $data['mapping'];
45
+ $this->requires_remapping = empty( $data['requires_remapping'] ) ? array() : $data['requires_remapping'];
46
+ $this->exists = empty( $data['exists'] ) ? array() : $data['exists'];
47
+ $this->user_slug_override = empty( $data['user_slug_override'] ) ? array() : $data['user_slug_override'];
48
+ $this->url_remap = empty( $data['url_remap'] ) ? array() : $data['url_remap'];
49
+ $this->featured_images = empty( $data['featured_images'] ) ? array() : $data['featured_images'];
50
+ }
51
+ }
includes/extras/class-logger-cli.php ADDED
@@ -0,0 +1,43 @@
1
+ <?php
2
+
3
+ class HM_WP_Importer_Logger_CLI extends HM_WP_Importer_Logger {
4
+ public $min_level = 'notice';
5
+
6
+ /**
7
+ * Logs with an arbitrary level.
8
+ *
9
+ * @param mixed $level
10
+ * @param string $message
11
+ * @param array $context
12
+ * @return null
13
+ */
14
+ public function log( $level, $message, array $context = array() ) {
15
+ if ( $this->level_to_numeric( $level ) < $this->level_to_numeric( $this->min_level ) ) {
16
+ return;
17
+ }
18
+
19
+ printf(
20
+ '[%s] %s' . PHP_EOL,
21
+ strtoupper( $level ),
22
+ $message
23
+ );
24
+ }
25
+
26
+ public static function level_to_numeric( $level ) {
27
+ $levels = array(
28
+ 'emergency' => 8,
29
+ 'alert' => 7,
30
+ 'critical' => 6,
31
+ 'error' => 5,
32
+ 'warning' => 4,
33
+ 'notice' => 3,
34
+ 'info' => 2,
35
+ 'debug' => 1,
36
+ );
37
+ if ( ! isset( $levels[ $level ] ) ) {
38
+ return 0;
39
+ }
40
+
41
+ return $levels[ $level ];
42
+ }
43
+ }
includes/extras/class-logger.php ADDED
@@ -0,0 +1,136 @@
1
+ <?php
2
+
3
+ /**
4
+ * Describes a logger instance
5
+ *
6
+ * Based on PSR-3: http://www.php-fig.org/psr/psr-3/
7
+ *
8
+ * The message MUST be a string or object implementing __toString().
9
+ *
10
+ * The message MAY contain placeholders in the form: {foo} where foo
11
+ * will be replaced by the context data in key "foo".
12
+ *
13
+ * The context array can contain arbitrary data, the only assumption that
14
+ * can be made by implementors is that if an Exception instance is given
15
+ * to produce a stack trace, it MUST be in a key named "exception".
16
+ *
17
+ * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
18
+ * for the full interface specification.
19
+ */
20
+ class HM_WP_Importer_Logger {
21
+ /**
22
+ * System is unusable.
23
+ *
24
+ * @param string $message
25
+ * @param array $context
26
+ * @return null
27
+ */
28
+ public function emergency( $message, array $context = array() ) {
29
+ return $this->log( 'emergency', $message, $context );
30
+ }
31
+
32
+ /**
33
+ * Action must be taken immediately.
34
+ *
35
+ * Example: Entire website down, database unavailable, etc. This should
36
+ * trigger the SMS alerts and wake you up.
37
+ *
38
+ * @param string $message
39
+ * @param array $context
40
+ * @return null
41
+ */
42
+ public function alert( $message, array $context = array() ) {
43
+ return $this->log( 'alert', $message, $context );
44
+ }
45
+
46
+ /**
47
+ * Critical conditions.
48
+ *
49
+ * Example: Application component unavailable, unexpected exception.
50
+ *
51
+ * @param string $message
52
+ * @param array $context
53
+ * @return null
54
+ */
55
+ public function critical( $message, array $context = array() ) {
56
+ return $this->log( 'critical', $message, $context );
57
+ }
58
+
59
+ /**
60
+ * Runtime errors that do not require immediate action but should typically
61
+ * be logged and monitored.
62
+ *
63
+ * @param string $message
64
+ * @param array $context
65
+ * @return null
66
+ */
67
+ public function error( $message, array $context = array()) {
68
+ return $this->log( 'error', $message, $context );
69
+ }
70
+
71
+ /**
72
+ * Exceptional occurrences that are not errors.
73
+ *
74
+ * Example: Use of deprecated APIs, poor use of an API, undesirable things
75
+ * that are not necessarily wrong.
76
+ *
77
+ * @param string $message
78
+ * @param array $context
79
+ * @return null
80
+ */
81
+ public function warning( $message, array $context = array() ) {
82
+ return $this->log( 'warning', $message, $context );
83
+ }
84
+
85
+ /**
86
+ * Normal but significant events.
87
+ *
88
+ * @param string $message
89
+ * @param array $context
90
+ * @return null
91
+ */
92
+ public function notice( $message, array $context = array() ) {
93
+ return $this->log( 'notice', $message, $context );
94
+ }
95
+
96
+ /**
97
+ * Interesting events.
98
+ *
99
+ * Example: User logs in, SQL logs.
100
+ *
101
+ * @param string $message
102
+ * @param array $context
103
+ * @return null
104
+ */
105
+ public function info( $message, array $context = array() ) {
106
+ return $this->log( 'info', $message, $context );
107
+ }
108
+
109
+ /**
110
+ * Detailed debug information.
111
+ *
112
+ * @param string $message
113
+ * @param array $context
114
+ * @return null
115
+ */
116
+ public function debug( $message, array $context = array() ) {
117
+ return $this->log( 'debug', $message, $context );
118
+ }
119
+
120
+ /**
121
+ * Logs with an arbitrary level.
122
+ *
123
+ * @param mixed $level
124
+ * @param string $message
125
+ * @param array $context
126
+ * @return null
127
+ */
128
+ public function log( $level, $message, array $context = array() ) {
129
+ $this->messages[] = array(
130
+ 'timestamp' => time(),
131
+ 'level' => $level,
132
+ 'message' => $message,
133
+ 'context' => $context,
134
+ );
135
+ }
136
+ }
includes/extras/class-wxr-importer.php ADDED
@@ -0,0 +1,2250 @@