One Click Demo Import - Version 2.0.0

Version Description

Release Date - 10 December 2016

  • Add new layout for multiple predefined demo imports (a grid layout instead of the dropdown selector),
  • Add support for Redux framework import,
  • Change the code structure of the plugin (plugin rewrite, namespaces, autoloading),
  • Now the whole import (content, widgets, customizer, redux) goes through even if something goes wrong in the content import (before content import errors blocked further import),
  • Add pt-ocdi/before_content_import action hook, that theme authors can use to hook into before the content import starts,
  • Fix frontend error reporting through multiple AJAX calls,
  • Fix post formats (video/quote/gallery,...) not importing,
  • Fix customizer import does not save some options (because of the missing WP actions - these can be enabled via a filter, more in the FAQ section).
Download this release

Release Info

Developer capuderg
Plugin Icon 128x128 One Click Demo Import
Version 2.0.0
Comparing to
See all releases

Code changes from version 1.4.0 to 2.0.0

assets/css/main.css CHANGED
@@ -1,5 +1,9 @@
1
  /* Overriding WordPress native styles */
2
 
 
 
 
 
3
  .ocdi h2 {
4
  text-align: inherit;
5
  }
@@ -94,7 +98,7 @@
94
 
95
  /* AJAX loader */
96
 
97
- .ocdi__ajax-loader {
98
  font-size: 1.5em;
99
  display: none;
100
  }
@@ -105,3 +109,223 @@
105
  visibility: visible;
106
  margin-bottom: 6px;
107
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  /* Overriding WordPress native styles */
2
 
3
+ .ocdi {
4
+ max-width: none;
5
+ }
6
+
7
  .ocdi h2 {
8
  text-align: inherit;
9
  }
98
 
99
  /* AJAX loader */
100
 
101
+ p.ocdi__ajax-loader {
102
  font-size: 1.5em;
103
  display: none;
104
  }
109
  visibility: visible;
110
  margin-bottom: 6px;
111
  }
112
+
113
+
114
+ /* New grid layout */
115
+
116
+ .ocdi__gl-navigation li a {
117
+ -webkit-box-shadow: none;
118
+ box-shadow: none;
119
+ }
120
+
121
+ .ocdi__gl-item {
122
+ float: left;
123
+ width: 100%;
124
+ margin: 0 0 20px 0;
125
+ position: relative;
126
+ border: 1px solid #ddd;
127
+ -webkit-box-shadow: 0 1px 1px -1px rgba(0,0,0,0.1);
128
+ box-shadow: 0 1px 1px -1px rgba(0,0,0,0.1);
129
+ -webkit-box-sizing: border-box;
130
+ -moz-box-sizing: border-box;
131
+ box-sizing: border-box;
132
+ }
133
+
134
+ .ocdi__gl-item-image-container {
135
+ display: block;
136
+ overflow: hidden;
137
+ position: relative;
138
+ -webkit-backface-visibility: hidden;
139
+ -webkit-transition: opacity 0.2s ease-in-out;
140
+ transition: opacity 0.2s ease-in-out;
141
+ }
142
+
143
+ .ocdi__gl-item-image-container::after {
144
+ content: "";
145
+ display: block;
146
+ padding-top: 66.66666%;
147
+ }
148
+
149
+ .ocdi__gl-item-image {
150
+ height: auto;
151
+ position: absolute;
152
+ left: 0;
153
+ top: 0;
154
+ width: 100%;
155
+ -webkit-transition: opacity 0.2s ease-in-out;
156
+ transition: opacity 0.2s ease-in-out;
157
+ }
158
+
159
+ .ocdi__gl-item-image--no-image {
160
+ display: inline-block;
161
+ width: 50%;
162
+ text-align: center;
163
+ position: absolute;
164
+ top: 45%;
165
+ right: 25%;
166
+ left: 25%;
167
+ }
168
+
169
+ .ocdi__gl-item-footer {
170
+ height: 30px;
171
+ margin: 0;
172
+ padding: 10px;
173
+ -webkit-box-shadow: inset 0 1px 0 rgba(0,0,0,0.1);
174
+ box-shadow: inset 0 1px 0 rgba(0,0,0,0.1);
175
+ background: #ffffff;
176
+ background: rgba(255,255,255,0.65);
177
+ }
178
+
179
+ h4.ocdi__gl-item-title {
180
+ width: 70%;
181
+ overflow: hidden;
182
+ white-space: nowrap;
183
+ text-overflow: ellipsis;
184
+ display: inline-block;
185
+ margin: 6px 0 0 0;
186
+ }
187
+
188
+ .ocdi__gl-item-button {
189
+ float: right;
190
+ }
191
+
192
+ .ocdi__gl-header {
193
+ display: inline-block;
194
+ width: calc(100% - 40px);
195
+ background-color: #ffffff;
196
+ margin-bottom: 20px;
197
+ padding: 0 20px;
198
+ }
199
+
200
+ .ocdi__gl-navigation {
201
+ font-size: 13px;
202
+ width: 100%;
203
+ float: left;
204
+ }
205
+
206
+ .ocdi__gl-navigation ul {
207
+ list-style-type: none;
208
+ margin: 0;
209
+ padding: 0;
210
+ overflow: hidden;
211
+ }
212
+
213
+ .ocdi__gl-navigation li {
214
+ float: left;
215
+ margin: 0 15px;
216
+ }
217
+
218
+ .ocdi__gl-navigation li.active a,
219
+ .ocdi__gl-navigation li.active a:hover {
220
+ border-bottom: 4px solid #666666;
221
+ }
222
+
223
+ .ocdi__gl-navigation li a {
224
+ display: block;
225
+ text-align: center;
226
+ text-decoration: none;
227
+ color: #444444;
228
+ border-bottom: 4px solid #ffffff;
229
+ padding: 15px 0;
230
+ }
231
+
232
+ .ocdi__gl-navigation li a:hover {
233
+ color: #00a0d2;
234
+ border-bottom: 4px solid #ffffff;
235
+ cursor:pointer;
236
+ }
237
+
238
+ .ocdi__gl-search-input {
239
+ width: 100%;
240
+ margin: 10px 0;
241
+ }
242
+
243
+ @media (min-width: 640px) {
244
+ .ocdi__gl-navigation {
245
+ width: calc(100% - 180px);
246
+ }
247
+
248
+ .ocdi__gl-navigation li {
249
+ margin: 0;
250
+ }
251
+
252
+ .ocdi__gl-navigation li a {
253
+ padding: 15px;
254
+ }
255
+
256
+ .ocdi__gl-search-input {
257
+ display: inline-block;
258
+ width: 180px;
259
+ height: 30px;
260
+ margin: 0;
261
+ margin-top: 11px;
262
+ }
263
+
264
+ .ocdi__gl-item-container {
265
+ margin-right: -20px;
266
+ }
267
+
268
+ .ocdi__gl-item {
269
+ width: calc(50% - 20px);
270
+ margin: 0 20px 20px 0;
271
+ }
272
+ }
273
+
274
+ @media (min-width: 1120px) {
275
+ .ocdi__gl-item-container {
276
+ margin-right: -30px;
277
+ }
278
+
279
+ .ocdi__gl-item {
280
+ width: calc(33.333% - 30px);
281
+ margin: 0 30px 30px 0;
282
+ }
283
+ }
284
+
285
+ /* Grid animations */
286
+ @keyframes ocdi-fade {
287
+ from {
288
+ opacity: 1;
289
+ }
290
+
291
+ to {
292
+ opacity: 0;
293
+ }
294
+ }
295
+
296
+ .ocdi-is-fadeout {
297
+ animation: ocdi-fade linear 200ms 1 forwards;
298
+ }
299
+
300
+ .ocdi-is-fadein {
301
+ animation: ocdi-fade linear 200ms 1 reverse forwards;
302
+ }
303
+
304
+ /* Grid layout modal window */
305
+
306
+ .ocdi__modal-image-container {
307
+ width: 100%;
308
+ height: 180px;
309
+ margin: 0;
310
+ overflow: hidden;
311
+ }
312
+
313
+ .ocdi__modal-item-title {
314
+ margin-top: 0.5em;
315
+ font-weight: bold;
316
+ }
317
+
318
+ .ocdi__modal-image-container img {
319
+ width: 100%;
320
+ }
321
+
322
+ .ocdi__modal-notice.ocdi__demo-import-notice:not(:empty) {
323
+ border: 1px solid #e5e5e5;
324
+ border-left: 4px solid #00a0d2;
325
+ margin: 1em 0 0;
326
+ }
327
+
328
+ /* Redux */
329
+ .ocdi__redux-option-name-label {
330
+ margin-right: 5px;
331
+ }
assets/js/main.js CHANGED
@@ -1,6 +1,15 @@
1
  jQuery( function ( $ ) {
2
  'use strict';
3
 
 
 
 
 
 
 
 
 
 
4
  $( '.js-ocdi-import-data' ).on( 'click', function () {
5
 
6
  // Reset response div content.
@@ -20,28 +29,267 @@ jQuery( function ( $ ) {
20
  if ( $('#ocdi__customizer-file-upload').length ) {
21
  data.append( 'customizer_file', $('#ocdi__customizer-file-upload')[0].files[0] );
22
  }
 
 
 
 
23
 
24
  // AJAX call to import everything (content, widgets, before/after setup)
25
  ajaxCall( data );
26
 
27
  });
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  function ajaxCall( data ) {
30
  $.ajax({
31
- method: 'POST',
32
- url: ocdi.ajax_url,
33
- data: data,
34
  contentType: false,
35
  processData: false,
36
- beforeSend: function() {
37
  $( '.js-ocdi-ajax-loader' ).show();
38
  }
39
  })
40
  .done( function( response ) {
41
-
42
  if ( 'undefined' !== typeof response.status && 'newAJAX' === response.status ) {
43
  ajaxCall( data );
44
  }
 
 
 
 
 
 
 
 
 
 
45
  else if ( 'undefined' !== typeof response.message ) {
46
  $( '.js-ocdi-ajax-response' ).append( '<p>' + response.message + '</p>' );
47
  $( '.js-ocdi-ajax-loader' ).hide();
@@ -56,25 +304,4 @@ jQuery( function ( $ ) {
56
  $( '.js-ocdi-ajax-loader' ).hide();
57
  });
58
  }
59
-
60
- // Switch preview images on select change event, but only if the img element .js-ocdi-preview-image exists.
61
- // Also switch the import notice (if it exists).
62
- $( '#ocdi__demo-import-files' ).on( 'change', function(){
63
- if ( $( '.js-ocdi-preview-image' ).length ) {
64
-
65
- // Attempt to change the image, else display message for missing image.
66
- var currentFilePreviewImage = ocdi.import_files[ this.value ]['import_preview_image_url'] || '';
67
- $( '.js-ocdi-preview-image' ).prop( 'src', currentFilePreviewImage );
68
- $( '.js-ocdi-preview-image-message' ).html( '' );
69
-
70
- if ( '' === currentFilePreviewImage ) {
71
- $( '.js-ocdi-preview-image-message' ).html( ocdi.texts.missing_preview_image );
72
- }
73
- }
74
-
75
- // Update import notice.
76
- var currentImportNotice = ocdi.import_files[ this.value ]['import_notice'] || '';
77
- $( '.js-ocdi-demo-import-notice' ).html( currentImportNotice );
78
- });
79
-
80
- });
1
  jQuery( function ( $ ) {
2
  'use strict';
3
 
4
+ /**
5
+ * ---------------------------------------
6
+ * ------------- Events ------------------
7
+ * ---------------------------------------
8
+ */
9
+
10
+ /**
11
+ * No or Single predefined demo import button click.
12
+ */
13
  $( '.js-ocdi-import-data' ).on( 'click', function () {
14
 
15
  // Reset response div content.
29
  if ( $('#ocdi__customizer-file-upload').length ) {
30
  data.append( 'customizer_file', $('#ocdi__customizer-file-upload')[0].files[0] );
31
  }
32
+ if ( $('#ocdi__redux-file-upload').length ) {
33
+ data.append( 'redux_file', $('#ocdi__redux-file-upload')[0].files[0] );
34
+ data.append( 'redux_option_name', $('#ocdi__redux-option-name').val() );
35
+ }
36
 
37
  // AJAX call to import everything (content, widgets, before/after setup)
38
  ajaxCall( data );
39
 
40
  });
41
 
42
+
43
+ /**
44
+ * Grid Layout import button click.
45
+ */
46
+ $( '.js-ocdi-gl-import-data' ).on( 'click', function () {
47
+ var selectedImportID = $( this ).val();
48
+ var $itemContainer = $( this ).closest( '.js-ocdi-gl-item' );
49
+
50
+ // If the import confirmation is enabled, then do that, else import straight away.
51
+ if ( ocdi.import_popup ) {
52
+ displayConfirmationPopup( selectedImportID, $itemContainer );
53
+ }
54
+ else {
55
+ gridLayoutImport( selectedImportID, $itemContainer );
56
+ }
57
+ });
58
+
59
+
60
+ /**
61
+ * Grid Layout categories navigation.
62
+ */
63
+ (function () {
64
+ // Cache selector to all items
65
+ var $items = $( '.js-ocdi-gl-item-container' ).find( '.js-ocdi-gl-item' ),
66
+ fadeoutClass = 'ocdi-is-fadeout',
67
+ fadeinClass = 'ocdi-is-fadein',
68
+ animationDuration = 200;
69
+
70
+ // Hide all items.
71
+ var fadeOut = function () {
72
+ var dfd = jQuery.Deferred();
73
+
74
+ $items
75
+ .addClass( fadeoutClass );
76
+
77
+ setTimeout( function() {
78
+ $items
79
+ .removeClass( fadeoutClass )
80
+ .hide();
81
+
82
+ dfd.resolve();
83
+ }, animationDuration );
84
+
85
+ return dfd.promise();
86
+ };
87
+
88
+ var fadeIn = function ( category, dfd ) {
89
+ var filter = category ? '[data-categories*="' + category + '"]' : 'div';
90
+
91
+ if ( 'all' === category ) {
92
+ filter = 'div';
93
+ }
94
+
95
+ $items
96
+ .filter( filter )
97
+ .show()
98
+ .addClass( 'ocdi-is-fadein' );
99
+
100
+ setTimeout( function() {
101
+ $items
102
+ .removeClass( fadeinClass );
103
+
104
+ dfd.resolve();
105
+ }, animationDuration );
106
+ };
107
+
108
+ var animate = function ( category ) {
109
+ var dfd = jQuery.Deferred();
110
+
111
+ var promise = fadeOut();
112
+
113
+ promise.done( function () {
114
+ fadeIn( category, dfd );
115
+ } );
116
+
117
+ return dfd;
118
+ };
119
+
120
+ $( '.js-ocdi-nav-link' ).on( 'click', function( event ) {
121
+ event.preventDefault();
122
+
123
+ // Remove 'active' class from the previous nav list items.
124
+ $( this ).parent().siblings().removeClass( 'active' );
125
+
126
+ // Add the 'active' class to this nav list item.
127
+ $( this ).parent().addClass( 'active' );
128
+
129
+ var category = this.hash.slice(1);
130
+
131
+ // show/hide the right items, based on category selected
132
+ var $container = $( '.js-ocdi-gl-item-container' );
133
+ $container.css( 'min-width', $container.outerHeight() );
134
+
135
+ var promise = animate( category );
136
+
137
+ promise.done( function () {
138
+ $container.removeAttr( 'style' );
139
+ } );
140
+ } );
141
+ }());
142
+
143
+
144
+ /**
145
+ * Grid Layout search functionality.
146
+ */
147
+ $( '.js-ocdi-gl-search' ).on( 'keyup', function( event ) {
148
+ if ( 0 < $(this).val().length ) {
149
+ // Hide all items.
150
+ $( '.js-ocdi-gl-item-container' ).find( '.js-ocdi-gl-item' ).hide();
151
+
152
+ // Show just the ones that have a match on the import name.
153
+ $( '.js-ocdi-gl-item-container' ).find( '.js-ocdi-gl-item[data-name*="' + $(this).val().toLowerCase() + '"]' ).show();
154
+ }
155
+ else {
156
+ $( '.js-ocdi-gl-item-container' ).find( '.js-ocdi-gl-item' ).show();
157
+ }
158
+ } );
159
+
160
+ /**
161
+ * ---------------------------------------
162
+ * --------Helper functions --------------
163
+ * ---------------------------------------
164
+ */
165
+
166
+ /**
167
+ * Prepare grid layout import data and execute the AJAX call.
168
+ *
169
+ * @param int selectedImportID The selected import ID.
170
+ * @param obj $itemContainer The jQuery selected item container object.
171
+ */
172
+ function gridLayoutImport( selectedImportID, $itemContainer ) {
173
+ // Reset response div content.
174
+ $( '.js-ocdi-ajax-response' ).empty();
175
+
176
+ // Hide all other import items.
177
+ $itemContainer.siblings( '.js-ocdi-gl-item' ).fadeOut( 500 );
178
+
179
+ $itemContainer.animate({
180
+ opacity: 0
181
+ }, 500, 'swing', function () {
182
+ $itemContainer.animate({
183
+ opacity: 1
184
+ }, 500 )
185
+ });
186
+
187
+ // Hide the header with category navigation and search box.
188
+ $itemContainer.closest( '.js-ocdi-gl' ).find( '.js-ocdi-gl-header' ).fadeOut( 500 );
189
+
190
+ // Append a title for the selected demo import.
191
+ $itemContainer.parent().prepend( '<h3>' + ocdi.texts.selected_import_title + '</h3>' );
192
+
193
+ // Remove the import button of the selected item.
194
+ $itemContainer.find( '.js-ocdi-gl-import-data' ).remove();
195
+
196
+ // Prepare data for the AJAX call
197
+ var data = new FormData();
198
+ data.append( 'action', 'ocdi_import_demo_data' );
199
+ data.append( 'security', ocdi.ajax_nonce );
200
+ data.append( 'selected', selectedImportID );
201
+
202
+ // AJAX call to import everything (content, widgets, before/after setup)
203
+ ajaxCall( data );
204
+ }
205
+
206
+ /**
207
+ * Display the confirmation popup.
208
+ *
209
+ * @param int selectedImportID The selected import ID.
210
+ * @param obj $itemContainer The jQuery selected item container object.
211
+ */
212
+ function displayConfirmationPopup( selectedImportID, $itemContainer ) {
213
+ var $dialogContiner = $( '#js-ocdi-modal-content' );
214
+ var currentFilePreviewImage = ocdi.import_files[ selectedImportID ]['import_preview_image_url'] || ocdi.theme_screenshot;
215
+ var previewImageContent = '';
216
+ var importNotice = ocdi.import_files[ selectedImportID ]['import_notice'] || '';
217
+ var importNoticeContent = '';
218
+
219
+ if ( '' === currentFilePreviewImage ) {
220
+ previewImageContent = '<p>' + ocdi.texts.missing_preview_image + '</p>';
221
+ }
222
+ else {
223
+ previewImageContent = '<div class="ocdi__modal-image-container"><img src="' + currentFilePreviewImage + '" alt="' + ocdi.import_files[ selectedImportID ]['import_file_name'] + '"></div>'
224
+ }
225
+
226
+ // Prepare notice output.
227
+ if( '' !== importNotice ) {
228
+ importNoticeContent = '<div class="ocdi__modal-notice ocdi__demo-import-notice">' + importNotice + '</div>';
229
+ }
230
+
231
+ // Populate the dialog content.
232
+ $dialogContiner.prop( 'title', ocdi.texts.dialog_title );
233
+ $dialogContiner.html(
234
+ '<p class="ocdi__modal-item-title">' + ocdi.import_files[ selectedImportID ]['import_file_name'] + '</p>' +
235
+ previewImageContent +
236
+ importNoticeContent
237
+ );
238
+
239
+ $dialogContiner.dialog( {
240
+ 'dialogClass': 'wp-dialog',
241
+ 'resizable': false,
242
+ 'height': 'auto',
243
+ 'modal': true,
244
+ 'buttons': [
245
+ {
246
+ text: ocdi.texts.dialog_no,
247
+ click: function() {
248
+ $(this).dialog('close');
249
+ }
250
+ },
251
+ {
252
+ text: ocdi.texts.dialog_yes,
253
+ class: 'button button-primary',
254
+ click: function() {
255
+ $(this).dialog('close');
256
+ gridLayoutImport( selectedImportID, $itemContainer );
257
+ }
258
+ }
259
+ ]
260
+ } );
261
+ }
262
+
263
+ /**
264
+ * The main AJAX call, which executes the import process.
265
+ *
266
+ * @param FormData data The data to be passed to the AJAX call.
267
+ */
268
  function ajaxCall( data ) {
269
  $.ajax({
270
+ method: 'POST',
271
+ url: ocdi.ajax_url,
272
+ data: data,
273
  contentType: false,
274
  processData: false,
275
+ beforeSend: function() {
276
  $( '.js-ocdi-ajax-loader' ).show();
277
  }
278
  })
279
  .done( function( response ) {
 
280
  if ( 'undefined' !== typeof response.status && 'newAJAX' === response.status ) {
281
  ajaxCall( data );
282
  }
283
+ else if ( 'undefined' !== typeof response.status && 'customizerAJAX' === response.status ) {
284
+ data.set( 'action', 'ocdi_import_customizer_data' );
285
+ data.set( 'wp_customize', 'on' );
286
+ ajaxCall( data );
287
+ }
288
+ else if ( 'undefined' !== typeof response.status && 'afterAllImportAJAX' === response.status ) {
289
+ data.set( 'action', 'ocdi_after_import_data' );
290
+ data.delete( 'wp_customize' );
291
+ ajaxCall( data );
292
+ }
293
  else if ( 'undefined' !== typeof response.message ) {
294
  $( '.js-ocdi-ajax-response' ).append( '<p>' + response.message + '</p>' );
295
  $( '.js-ocdi-ajax-loader' ).hide();
304
  $( '.js-ocdi-ajax-loader' ).hide();
305
  });
306
  }
307
+ } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/{class-ocdi-customizer-importer.php → CustomizerImporter.php} RENAMED
@@ -8,7 +8,45 @@
8
  * @package ocdi
9
  */
10
 
11
- class OCDI_Customizer_Importer {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
  /**
14
  * Imports uploaded mods and calls WordPress core customize_save actions so
@@ -21,7 +59,6 @@ class OCDI_Customizer_Importer {
21
  * @return void|WP_Error
22
  */
23
  public static function import_customizer_options( $import_file_path ) {
24
-
25
  // Setup global vars.
26
  global $wp_customize;
27
 
@@ -30,17 +67,17 @@ class OCDI_Customizer_Importer {
30
 
31
  // Make sure we have an import file.
32
  if ( ! file_exists( $import_file_path ) ) {
33
- return new WP_Error(
34
  'missing_cutomizer_import_file',
35
  sprintf(
36
- esc_html__( 'The customizer import file is missing! File path: %s', 'pt-ocdi' ),
37
  $import_file_path
38
  )
39
  );
40
  }
41
 
42
  // Get the upload data.
43
- $raw = OCDI_Helpers::data_from_file( $import_file_path );
44
 
45
  // Make sure we got the data.
46
  if ( is_wp_error( $raw ) ) {
@@ -51,15 +88,15 @@ class OCDI_Customizer_Importer {
51
 
52
  // Data checks.
53
  if ( ! is_array( $data ) && ( ! isset( $data['template'] ) || ! isset( $data['mods'] ) ) ) {
54
- return new WP_Error(
55
  'customizer_import_data_error',
56
- esc_html__( 'The customizer import file is not in a correct format. Please make sure to use the correct customizer import file.', 'pt-ocdi' )
57
  );
58
  }
59
  if ( $data['template'] !== $template ) {
60
- return new WP_Error(
61
  'customizer_import_wrong_theme',
62
- esc_html__( 'The customizer import file is not suitable for current theme. You can only import customizer settings for the same theme or a child theme.', 'pt-ocdi' )
63
  );
64
  }
65
 
@@ -70,15 +107,13 @@ class OCDI_Customizer_Importer {
70
 
71
  // Import custom options.
72
  if ( isset( $data['options'] ) ) {
73
-
74
  // Require modified customizer options class.
75
- if ( ! class_exists( 'WP_Customize_Setting' ) ) {
76
  require_once ABSPATH . 'wp-includes/class-wp-customize-setting.php';
77
  }
78
- require PT_OCDI_PATH . 'inc/class-ocdi-customizer-option.php';
79
 
80
  foreach ( $data['options'] as $option_key => $option_value ) {
81
- $option = new OCDI_Customizer_Option( $wp_customize, $option_key, array(
82
  'default' => '',
83
  'type' => 'option',
84
  'capability' => 'edit_theme_options',
@@ -88,12 +123,25 @@ class OCDI_Customizer_Importer {
88
  }
89
  }
90
 
91
- // Loop through the mods.
 
 
 
 
 
 
 
92
  foreach ( $data['mods'] as $key => $val ) {
 
 
 
93
 
94
- // Save the mod.
95
  set_theme_mod( $key, $val );
96
  }
 
 
 
 
97
  }
98
 
99
  /**
@@ -132,7 +180,7 @@ class OCDI_Customizer_Importer {
132
  * @return array An array of image data.
133
  */
134
  private static function customizer_sideload_image( $file ) {
135
- $data = new stdClass();
136
 
137
  if ( ! function_exists( 'media_handle_sideload' ) ) {
138
  require_once( ABSPATH . 'wp-admin/includes/media.php' );
@@ -140,7 +188,6 @@ class OCDI_Customizer_Importer {
140
  require_once( ABSPATH . 'wp-admin/includes/image.php' );
141
  }
142
  if ( ! empty( $file ) ) {
143
-
144
  // Set variables for storage, fix file filename for query strings.
145
  preg_match( '/[^\?]+\.(jpe?g|jpe|gif|png)\b/i', $file, $matches );
146
  $file_array = array();
8
  * @package ocdi
9
  */
10
 
11
+ namespace OCDI;
12
+
13
+ class CustomizerImporter {
14
+ /**
15
+ * Import customizer from a DAT file, generated by the Customizer Export/Import plugin.
16
+ *
17
+ * @param string $customizer_import_file_path path to the customizer import file.
18
+ */
19
+ public static function import( $customizer_import_file_path ) {
20
+ $ocdi = OneClickDemoImport::get_instance();
21
+ $log_file_path = $ocdi->get_log_file_path();
22
+
23
+ // Try to import the customizer settings.
24
+ $results = self::import_customizer_options( $customizer_import_file_path );
25
+
26
+ // Check for errors, else write the results to the log file.
27
+ if ( is_wp_error( $results ) ) {
28
+ $error_message = $results->get_error_message();
29
+
30
+ // Add any error messages to the frontend_error_messages variable in OCDI main class.
31
+ $ocdi->append_to_frontend_error_messages( $error_message );
32
+
33
+ // Write error to log file.
34
+ Helpers::append_to_file(
35
+ $error_message,
36
+ $log_file_path,
37
+ esc_html__( 'Importing customizer settings', 'pt-ocdi' )
38
+ );
39
+ }
40
+ else {
41
+ // Add this message to log file.
42
+ $log_added = Helpers::append_to_file(
43
+ esc_html__( 'Customizer settings import finished!', 'pt-ocdi' ),
44
+ $log_file_path,
45
+ esc_html__( 'Importing customizer settings' , 'pt-ocdi' )
46
+ );
47
+ }
48
+ }
49
+
50
 
51
  /**
52
  * Imports uploaded mods and calls WordPress core customize_save actions so
59
  * @return void|WP_Error
60
  */
61
  public static function import_customizer_options( $import_file_path ) {
 
62
  // Setup global vars.
63
  global $wp_customize;
64
 
67
 
68
  // Make sure we have an import file.
69
  if ( ! file_exists( $import_file_path ) ) {
70
+ return new \WP_Error(
71
  'missing_cutomizer_import_file',
72
  sprintf(
73
+ esc_html__( 'Error: The customizer import file is missing! File path: %s', 'pt-ocdi' ),
74
  $import_file_path
75
  )
76
  );
77
  }
78
 
79
  // Get the upload data.
80
+ $raw = Helpers::data_from_file( $import_file_path );
81
 
82
  // Make sure we got the data.
83
  if ( is_wp_error( $raw ) ) {
88
 
89
  // Data checks.
90
  if ( ! is_array( $data ) && ( ! isset( $data['template'] ) || ! isset( $data['mods'] ) ) ) {
91
+ return new \WP_Error(
92
  'customizer_import_data_error',
93
+ esc_html__( 'Error: The customizer import file is not in a correct format. Please make sure to use the correct customizer import file.', 'pt-ocdi' )
94
  );
95
  }
96
  if ( $data['template'] !== $template ) {
97
+ return new \WP_Error(
98
  'customizer_import_wrong_theme',
99
+ esc_html__( 'Error: The customizer import file is not suitable for current theme. You can only import customizer settings for the same theme or a child theme.', 'pt-ocdi' )
100
  );
101
  }
102
 
107
 
108
  // Import custom options.
109
  if ( isset( $data['options'] ) ) {
 
110
  // Require modified customizer options class.
111
+ if ( ! class_exists( '\WP_Customize_Setting' ) ) {
112
  require_once ABSPATH . 'wp-includes/class-wp-customize-setting.php';
113
  }
 
114
 
115
  foreach ( $data['options'] as $option_key => $option_value ) {
116
+ $option = new CustomizerOption( $wp_customize, $option_key, array(
117
  'default' => '',
118
  'type' => 'option',
119
  'capability' => 'edit_theme_options',
123
  }
124
  }
125
 
126
+ // Should the customizer import use the WP customize_save* hooks?
127
+ $use_wp_customize_save_hooks = apply_filters( 'pt-ocdi/enable_wp_customize_save_hooks', false );
128
+
129
+ if ( $use_wp_customize_save_hooks ) {
130
+ do_action( 'customize_save', $wp_customize );
131
+ }
132
+
133
+ // Loop through the mods and save the mods.
134
  foreach ( $data['mods'] as $key => $val ) {
135
+ if ( $use_wp_customize_save_hooks ) {
136
+ do_action( 'customize_save_' . $key, $wp_customize );
137
+ }
138
 
 
139
  set_theme_mod( $key, $val );
140
  }
141
+
142
+ if ( $use_wp_customize_save_hooks ) {
143
+ do_action( 'customize_save_after', $wp_customize );
144
+ }
145
  }
146
 
147
  /**
180
  * @return array An array of image data.
181
  */
182
  private static function customizer_sideload_image( $file ) {
183
+ $data = new \stdClass();
184
 
185
  if ( ! function_exists( 'media_handle_sideload' ) ) {
186
  require_once( ABSPATH . 'wp-admin/includes/media.php' );
188
  require_once( ABSPATH . 'wp-admin/includes/image.php' );
189
  }
190
  if ( ! empty( $file ) ) {
 
191
  // Set variables for storage, fix file filename for query strings.
192
  preg_match( '/[^\?]+\.(jpe?g|jpe|gif|png)\b/i', $file, $matches );
193
  $file_array = array();
inc/{class-ocdi-customizer-option.php → CustomizerOption.php} RENAMED
@@ -9,8 +9,9 @@
9
  * @package ocdi
10
  */
11
 
12
- final class OCDI_Customizer_Option extends WP_Customize_Setting {
13
 
 
14
  /**
15
  * Import an option value for this setting.
16
  *
9
  * @package ocdi
10
  */
11
 
12
+ namespace OCDI;
13
 
14
+ final class CustomizerOption extends \WP_Customize_Setting {
15
  /**
16
  * Import an option value for this setting.
17
  *
inc/Downloader.php ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Class for downloading a file from a given URL.
4
+ *
5
+ * @package ocdi
6
+ */
7
+
8
+ namespace OCDI;
9
+
10
+ class Downloader {
11
+ /**
12
+ * Holds full path to where the files will be saved.
13
+ *
14
+ * @var string
15
+ */
16
+ private $download_directory_path = '';
17
+
18
+ /**
19
+ * Constructor method.
20
+ *
21
+ * @param string $download_directory_path Full path to where the files will be saved.
22
+ */
23
+ public function __construct( $download_directory_path = '' ) {
24
+ $this->set_download_directory_path( $download_directory_path );
25
+ }
26
+
27
+
28
+ /**
29
+ * Download file from a given URL.
30
+ *
31
+ * @param string $url URL of file to download.
32
+ * @param string $filename Filename of the file to save.
33
+ * @return string|WP_Error Full path to the downloaded file or WP_Error object with error message.
34
+ */
35
+ public function download_file( $url, $filename ) {
36
+ $content = $this->get_content_from_url( $url );
37
+
38
+ // Check if there was an error and break out.
39
+ if ( is_wp_error( $content ) ) {
40
+ return $content;
41
+ }
42
+
43
+ return Helpers::write_to_file( $content, $this->download_directory_path . $filename );
44
+ }
45
+
46
+
47
+ /**
48
+ * Helper function: get content from an URL.
49
+ *
50
+ * @param string $url URL to the content file.
51
+ * @return string|WP_Error, content from the URL or WP_Error object with error message.
52
+ */
53
+ private function get_content_from_url( $url ) {
54
+ // Test if the URL to the file is defined.
55
+ if ( empty( $url ) ) {
56
+ return new \WP_Error(
57
+ 'missing_url',
58
+ __( 'Missing URL for downloading a file!', 'pt-ocdi' )
59
+ );
60
+ }
61
+
62
+ // Get file content from the server.
63
+ $response = wp_remote_get(
64
+ $url,
65
+ array( 'timeout' => apply_filters( 'pt-ocdi/timeout_for_downloading_import_file', 20 ) )
66
+ );
67
+
68
+ // Test if the get request was not successful.
69
+ if ( is_wp_error( $response ) || 200 !== $response['response']['code'] ) {
70
+ // Collect the right format of error data (array or WP_Error).
71
+ $response_error = $this->get_error_from_response( $response );
72
+
73
+ return new \WP_Error(
74
+ 'download_error',
75
+ sprintf(
76
+ __( 'An error occurred while fetching file from: %1$s%2$s%3$s!%4$sReason: %5$s - %6$s.', 'pt-ocdi' ),
77
+ '<strong>',
78
+ $url,
79
+ '</strong>',
80
+ '<br>',
81
+ $response_error['error_code'],
82
+ $response_error['error_message']
83
+ ) . '<br>' .
84
+ apply_filters( 'pt-ocdi/message_after_file_fetching_error', '' )
85
+ );
86
+ }
87
+
88
+ // Return content retrieved from the URL.
89
+ return wp_remote_retrieve_body( $response );
90
+ }
91
+
92
+
93
+ /**
94
+ * Helper function: get the right format of response errors.
95
+ *
96
+ * @param array|WP_Error $response Array or WP_Error or the response.
97
+ * @return array Error code and error message.
98
+ */
99
+ private function get_error_from_response( $response ) {
100
+ $response_error = array();
101
+
102
+ if ( is_array( $response ) ) {
103
+ $response_error['error_code'] = $response['response']['code'];
104
+ $response_error['error_message'] = $response['response']['message'];
105
+ }
106
+ else {
107
+ $response_error['error_code'] = $response->get_error_code();
108
+ $response_error['error_message'] = $response->get_error_message();
109
+ }
110
+
111
+ return $response_error;
112
+ }
113
+
114
+
115
+ /**
116
+ * Get download_directory_path attribute.
117
+ */
118
+ public function get_download_directory_path() {
119
+ return $this->download_directory_path;
120
+ }
121
+
122
+
123
+ /**
124
+ * Set download_directory_path attribute.
125
+ * If no valid path is specified, the default WP upload directory will be used.
126
+ *
127
+ * @param string $download_directory_path Path, where the files will be saved.
128
+ */
129
+ public function set_download_directory_path( $download_directory_path ) {
130
+ if ( file_exists( $download_directory_path ) ) {
131
+ $this->download_directory_path = $download_directory_path;
132
+ }
133
+ else {
134
+ $upload_dir = wp_upload_dir();
135
+ $this->download_directory_path = apply_filters( 'pt-ocdi/upload_file_path', trailingslashit( $upload_dir['path'] ) );
136
+ }
137
+ }
138
+ }
inc/{class-ocdi-helpers.php → Helpers.php} RENAMED
@@ -5,10 +5,18 @@
5
  * @package ocdi
6
  */
7
 
 
 
8
  /**
9
  * Class with static helper functions.
10
  */
11
- class OCDI_Helpers {
 
 
 
 
 
 
12
 
13
  /**
14
  * Filter through the array of import files and get rid of those who do not comply.
@@ -48,14 +56,11 @@ class OCDI_Helpers {
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( 'pt-ocdi/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.
@@ -64,32 +69,23 @@ class OCDI_Helpers {
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!', 'pt-ocdi' ),
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( 'pt-ocdi/downloaded_content_file_prefix', 'demo-content-import-file_' ) . $start_date . apply_filters( 'pt-ocdi/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'] ) ) {
@@ -100,20 +96,11 @@ class OCDI_Helpers {
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( 'pt-ocdi/downloaded_widgets_file_prefix', 'demo-widgets-import-file_' ) . $start_date . apply_filters( 'pt-ocdi/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'] ) ) {
@@ -129,20 +116,11 @@ class OCDI_Helpers {
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( 'pt-ocdi/downloaded_customizer_file_prefix', 'demo-customizer-import-file_' ) . $start_date . apply_filters( 'pt-ocdi/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'] ) ) {
@@ -155,60 +133,48 @@ class OCDI_Helpers {
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!', 'pt-ocdi' ),
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( 'pt-ocdi/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.', 'pt-ocdi' ),
199
- '<strong>',
200
- $file_name,
201
- '</strong>',
202
- '<br>',
203
- $response_error['error_code'],
204
- $response_error['error_message']
205
- ) . '<br>' .
206
- apply_filters( 'pt-ocdi/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
 
@@ -220,7 +186,6 @@ class OCDI_Helpers {
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
 
@@ -232,7 +197,7 @@ class OCDI_Helpers {
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.', 'pt-ocdi' ),
@@ -256,7 +221,6 @@ class OCDI_Helpers {
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
 
@@ -276,7 +240,7 @@ class OCDI_Helpers {
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.', 'pt-ocdi' ),
@@ -297,7 +261,6 @@ class OCDI_Helpers {
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
 
@@ -311,7 +274,7 @@ class OCDI_Helpers {
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.', 'pt-ocdi' ),
@@ -332,10 +295,9 @@ class OCDI_Helpers {
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.', 'pt-ocdi' ),
@@ -360,7 +322,7 @@ class OCDI_Helpers {
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)!', 'pt-ocdi' )
366
  );
@@ -368,7 +330,7 @@ class OCDI_Helpers {
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!', 'pt-ocdi' )
374
  );
@@ -378,40 +340,16 @@ class OCDI_Helpers {
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( 'pt-ocdi/upload_file_path', trailingslashit( $upload_dir['path'] ) );
413
 
414
- $log_path = $upload_path . apply_filters( 'pt-ocdi/log_file_prefix', 'log_file_' ) . $start_date . apply_filters( 'pt-ocdi/log_file_suffix_and_file_extension', '.txt' );
415
 
416
  self::register_file_as_media_attachment( $log_path );
417
 
@@ -426,7 +364,6 @@ class OCDI_Helpers {
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( 'pt-ocdi/file_mimes', $log_mimes ) );
@@ -452,7 +389,6 @@ class OCDI_Helpers {
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( 'pt-ocdi/upload_file_url', trailingslashit( $upload_dir['url'] ) );
458
 
@@ -464,7 +400,6 @@ class OCDI_Helpers {
464
  * Check if the AJAX call is valid.
465
  */
466
  public static function verify_ajax_call() {
467
-
468
  check_ajax_referer( 'ocdi-ajax-verification', 'security' );
469
 
470
  // Check if user has the WP capability to import data.
@@ -488,7 +423,6 @@ class OCDI_Helpers {
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
 
@@ -502,9 +436,9 @@ class OCDI_Helpers {
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.', 'pt-ocdi' ),
@@ -518,12 +452,10 @@ class OCDI_Helpers {
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(
@@ -537,12 +469,10 @@ class OCDI_Helpers {
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(
@@ -554,6 +484,37 @@ class OCDI_Helpers {
554
  );
555
  }
556
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
557
  // Add this message to log file.
558
  $log_added = self::append_to_file(
559
  __( 'The import files were successfully uploaded!', 'pt-ocdi' ) . self::import_file_info( $selected_import_files ),
@@ -572,18 +533,23 @@ class OCDI_Helpers {
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', 'pt-ocdi' ),
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', 'pt-ocdi' ),
582
  PHP_EOL,
583
  get_site_url(),
584
  $selected_import_files['content'],
585
  empty( $selected_import_files['widgets'] ) ? esc_html__( 'not defined!', 'pt-ocdi' ) : $selected_import_files['widgets'],
586
- empty( $selected_import_files['customizer'] ) ? esc_html__( 'not defined!', 'pt-ocdi' ) : $selected_import_files['customizer']
 
587
  );
588
  }
589
 
@@ -596,7 +562,6 @@ class OCDI_Helpers {
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,
@@ -607,4 +572,71 @@ class OCDI_Helpers {
607
  // Send JSON Error response to the AJAX call.
608
  wp_send_json( $error_text );
609
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
610
  }
5
  * @package ocdi
6
  */
7
 
8
+ namespace OCDI;
9
+
10
  /**
11
  * Class with static helper functions.
12
  */
13
+ class Helpers {
14
+ /**
15
+ * Holds the date and time string for demo import and log file.
16
+ *
17
+ * @var string
18
+ */
19
+ public static $demo_import_start_time = '';
20
 
21
  /**
22
  * Filter through the array of import files and get rid of those who do not comply.
56
  * Download import files. Content .xml and widgets .wie|.json files.
57
  *
58
  * @param array $import_file_info array with import file details.
 
59
  * @return array|WP_Error array of paths to the downloaded files or WP_Error object with error message.
60
  */
61
+ public static function download_import_files( $import_file_info ) {
 
62
  $downloaded_files = array();
63
+ $downloader = new Downloader();
 
64
 
65
  // ----- Set content file path -----
66
  // Check if 'import_file_url' is not defined. That would mean a local file.
69
  $downloaded_files['content'] = $import_file_info['local_import_file'];
70
  }
71
  else {
72
+ return new \WP_Error(
73
  'url_or_local_file_not_defined',
74
  sprintf(
75
  __( '"import_file_url" or "local_import_file" for %s%s%s are not defined!', 'pt-ocdi' ),
76
  '<strong>',
77
+ $import_file_info['import_file_name'],
78
  '</strong>'
79
  )
80
  );
81
  }
82
  }
83
  else {
84
+ // Set the filename string for content import file.
85
+ $content_filename = apply_filters( 'pt-ocdi/downloaded_content_file_prefix', 'demo-content-import-file_' ) . self::$demo_import_start_time . apply_filters( 'pt-ocdi/downloaded_content_file_suffix_and_file_extension', '.xml' );
86
 
87
+ // Download the content import file.
88
+ $downloaded_files['content'] = $downloader->download_file( $import_file_info['import_file_url'], $content_filename );
 
 
 
 
 
 
 
 
 
 
 
89
 
90
  // Return from this function if there was an error.
91
  if ( is_wp_error( $downloaded_files['content'] ) ) {
96
  // ----- Set widget file path -----
97
  // Get widgets file as well. If defined!
98
  if ( ! empty( $import_file_info['import_widget_file_url'] ) ) {
99
+ // Set the filename string for widgets import file.
100
+ $widget_filename = apply_filters( 'pt-ocdi/downloaded_widgets_file_prefix', 'demo-widgets-import-file_' ) . self::$demo_import_start_time . apply_filters( 'pt-ocdi/downloaded_widgets_file_suffix_and_file_extension', '.json' );
101
 
102
+ // Download the widgets import file.
103
+ $downloaded_files['widgets'] = $downloader->download_file( $import_file_info['import_widget_file_url'], $widget_filename );
 
 
 
 
 
 
 
 
 
 
 
104
 
105
  // Return from this function if there was an error.
106
  if ( is_wp_error( $downloaded_files['widgets'] ) ) {
116
  // ----- Set customizer file path -----
117
  // Get customizer import file as well. If defined!
118
  if ( ! empty( $import_file_info['import_customizer_file_url'] ) ) {
 
 
 
 
 
 
 
 
 
119
  // Setup filename path to save the customizer content.
120
+ $customizer_filename = apply_filters( 'pt-ocdi/downloaded_customizer_file_prefix', 'demo-customizer-import-file_' ) . self::$demo_import_start_time . apply_filters( 'pt-ocdi/downloaded_customizer_file_suffix_and_file_extension', '.dat' );
121
 
122
+ // Download the customizer import file.
123
+ $downloaded_files['customizer'] = $downloader->download_file( $import_file_info['import_customizer_file_url'], $customizer_filename );
124
 
125
  // Return from this function if there was an error.
126
  if ( is_wp_error( $downloaded_files['customizer'] ) ) {
133
  }
134
  }
135
 
136
+ // ----- Set Redux file paths -----
137
+ // Get Redux import file as well. If defined!
138
+ if ( ! empty( $import_file_info['import_redux'] ) && is_array( $import_file_info['import_redux'] ) ) {
139
+ $redux_items = array();
140
 
141
+ // Setup filename paths to save the Redux content.
142
+ foreach ( $import_file_info['import_redux'] as $index => $redux_item ) {
143
+ $redux_filename = apply_filters( 'pt-ocdi/downloaded_redux_file_prefix', 'demo-redux-import-file_' ) . $index . '-' . self::$demo_import_start_time . apply_filters( 'pt-ocdi/downloaded_redux_file_suffix_and_file_extension', '.json' );
144
 
145
+ // Download the Redux import file.
146
+ $file_path = $downloader->download_file( $redux_item['file_url'], $redux_filename );
 
 
 
 
 
 
147
 
148
+ // Return from this function if there was an error.
149
+ if ( is_wp_error( $file_path ) ) {
150
+ return $file_path;
151
+ }
 
 
 
 
 
 
 
 
152
 
153
+ $redux_items[] = array(
154
+ 'option_name' => $redux_item['option_name'],
155
+ 'file_path' => $file_path,
156
+ );
157
+ }
158
 
159
+ // Download the Redux import file.
160
+ $downloaded_files['redux'] = $redux_items;
161
+ }
162
+ else if ( ! empty( $import_file_info['local_import_redux'] ) ) {
163
 
164
+ $redux_items = array();
 
165
 
166
+ // Setup filename paths to save the Redux content.
167
+ foreach ( $import_file_info['local_import_redux'] as $redux_item ) {
168
+ if ( file_exists( $redux_item['file_path'] ) ) {
169
+ $redux_items[] = $redux_item;
170
+ }
171
+ }
172
+
173
+ // Download the Redux import file.
174
+ $downloaded_files['redux'] = $redux_items;
 
 
 
 
175
  }
176
 
177
+ return $downloaded_files;
 
178
  }
179
 
180
 
186
  * @return string|WP_Error path to the saved file or WP_Error object with error message.
187
  */
188
  public static function write_to_file( $content, $file_path ) {
 
189
  // Verify WP file-system credentials.
190
  $verified_credentials = self::check_wp_filesystem_credentials();
191
 
197
  global $wp_filesystem;
198
 
199
  if ( ! $wp_filesystem->put_contents( $file_path, $content ) ) {
200
+ return new \WP_Error(
201
  'failed_writing_file_to_server',
202
  sprintf(
203
  __( 'An error occurred while writing file to your server! Tried to write a file to: %s%s.', 'pt-ocdi' ),
221
  * @return boolean|WP_Error, path to the saved file or WP_Error object with error message.
222
  */
223
  public static function append_to_file( $content, $file_path, $separator_text = '' ) {
 
224
  // Verify WP file-system credentials.
225
  $verified_credentials = self::check_wp_filesystem_credentials();
226
 
240
  $separator = PHP_EOL . '---' . $separator_text . '---' . PHP_EOL;
241
 
242
  if ( ! $wp_filesystem->put_contents( $file_path, $existing_data . $separator . $content . PHP_EOL ) ) {
243
+ return new \WP_Error(
244
  'failed_writing_file_to_server',
245
  sprintf(
246
  __( 'An error occurred while writing file to your server! Tried to write a file to: %s%s.', 'pt-ocdi' ),
261
  * @return string $data, content of the file or WP_Error object with error message.
262
  */
263
  public static function data_from_file( $file_path ) {
 
264
  // Verify WP file-system credentials.
265
  $verified_credentials = self::check_wp_filesystem_credentials();
266
 
274
  $data = $wp_filesystem->get_contents( $file_path );
275
 
276
  if ( ! $data ) {
277
+ return new \WP_Error(
278
  'failed_reading_file_from_server',
279
  sprintf(
280
  __( 'An error occurred while reading a file from your server! Tried reading file from path: %s%s.', 'pt-ocdi' ),
295
  * @return boolean|WP_Error
296
  */
297
  private static function check_wp_filesystem_credentials() {
 
298
  // Check if the file-system method is 'direct', if not display an error.
299
  if ( ! ( 'direct' === get_filesystem_method() ) ) {
300
+ return new \WP_Error(
301
  'no_direct_file_access',
302
  sprintf(
303
  __( '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.', 'pt-ocdi' ),
322
  $demo_import_page_url = wp_nonce_url( $plugin_page_setup['parent_slug'] . '?page=' . $plugin_page_setup['menu_slug'], $plugin_page_setup['menu_slug'] );
323
 
324
  if ( false === ( $creds = request_filesystem_credentials( $demo_import_page_url, '', false, false, null ) ) ) {
325
+ return new \WP_error(
326
  'filesystem_credentials_could_not_be_retrieved',
327
  __( 'An error occurred while retrieving reading/writing permissions to your server (could not retrieve WP filesystem credentials)!', 'pt-ocdi' )
328
  );
330
 
331
  // Now we have credentials, try to get the wp_filesystem running.
332
  if ( ! WP_Filesystem( $creds ) ) {
333
+ return new \WP_Error(
334
  'wrong_login_credentials',
335
  __( 'Your WordPress login credentials don\'t allow to use WP_Filesystem!', 'pt-ocdi' )
336
  );
340
  }
341
 
342
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
343
  /**
344
  * Get log file path
345
  *
 
346
  * @return string, path to the log file
347
  */
348
+ public static function get_log_path() {
 
349
  $upload_dir = wp_upload_dir();
350
  $upload_path = apply_filters( 'pt-ocdi/upload_file_path', trailingslashit( $upload_dir['path'] ) );
351
 
352
+ $log_path = $upload_path . apply_filters( 'pt-ocdi/log_file_prefix', 'log_file_' ) . self::$demo_import_start_time . apply_filters( 'pt-ocdi/log_file_suffix_and_file_extension', '.txt' );
353
 
354
  self::register_file_as_media_attachment( $log_path );
355
 
364
  * @return void
365
  */
366
  public static function register_file_as_media_attachment( $log_path ) {
 
367
  // Check the type of file.
368
  $log_mimes = array( 'txt' => 'text/plain' );
369
  $filetype = wp_check_filetype( basename( $log_path ), apply_filters( 'pt-ocdi/file_mimes', $log_mimes ) );
389
  * @return string, url to the log file.
390
  */
391
  public static function get_log_url( $log_path ) {
 
392
  $upload_dir = wp_upload_dir();
393
  $upload_url = apply_filters( 'pt-ocdi/upload_file_url', trailingslashit( $upload_dir['url'] ) );
394
 
400
  * Check if the AJAX call is valid.
401
  */
402
  public static function verify_ajax_call() {
 
403
  check_ajax_referer( 'ocdi-ajax-verification', 'security' );
404
 
405
  // Check if user has the WP capability to import data.
423
  * @return array of paths to the content import and widget import files.
424
  */
425
  public static function process_uploaded_files( $uploaded_files, $log_file_path ) {
 
426
  // Variable holding the paths to the uploaded files.
427
  $selected_import_files = array();
428
 
436
  $content_file_info = wp_handle_upload( $_FILES['content_file'], $upload_overrides );
437
  $widget_file_info = wp_handle_upload( $_FILES['widget_file'], $upload_overrides );
438
  $customizer_file_info = wp_handle_upload( $_FILES['customizer_file'], $upload_overrides );
439
+ $redux_file_info = wp_handle_upload( $_FILES['redux_file'], $upload_overrides );
440
 
441
  if ( empty( $content_file_info['file'] ) || isset( $content_file_info['error'] ) ) {
 
442
  // Write error to log file and send an AJAX response with the error.
443
  self::log_error_and_send_ajax_response(
444
  __( '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.', 'pt-ocdi' ),
452
 
453
  // Process widget import file.
454
  if ( $widget_file_info && ! isset( $widget_file_info['error'] ) ) {
 
455
  // Set uploaded widget file.
456
  $selected_import_files['widgets'] = $widget_file_info['file'];
457
  }
458
  else {
 
459
  // Add this error to log file.
460
  $log_added = self::append_to_file(
461
  sprintf(
469
 
470
  // Process Customizer import file.
471
  if ( $customizer_file_info && ! isset( $customizer_file_info['error'] ) ) {
472
+ // Set uploaded customizer file.
 
473
  $selected_import_files['customizer'] = $customizer_file_info['file'];
474
  }
475
  else {
 
476
  // Add this error to log file.
477
  $log_added = self::append_to_file(
478
  sprintf(
484
  );
485
  }
486
 
487
+ // Process Redux import file.
488
+ if ( $redux_file_info && ! isset( $redux_file_info['error'] ) ) {
489
+ if ( isset( $_POST['redux_option_name'] ) && empty( $_POST['redux_option_name'] ) ) {
490
+ // Write error to log file and send an AJAX response with the error.
491
+ self::log_error_and_send_ajax_response(
492
+ esc_html__( 'Missing Redux option name! Please also enter the Redux option name!', 'pt-ocdi' ),
493
+ $log_file_path,
494
+ esc_html__( 'Upload files', 'pt-ocdi' )
495
+ );
496
+ }
497
+
498
+ // Set uploaded Redux file.
499
+ $selected_import_files['redux'] = array(
500
+ array(
501
+ 'option_name' => $_POST['redux_option_name'],
502
+ 'file_path' => $redux_file_info['file'],
503
+ ),
504
+ );
505
+ }
506
+ else {
507
+ // Add this error to log file.
508
+ $log_added = self::append_to_file(
509
+ sprintf(
510
+ __( 'Redux file was not uploaded. Error: %s', 'pt-ocdi' ),
511
+ $redux_file_info['error']
512
+ ),
513
+ $log_file_path,
514
+ esc_html__( 'Upload files' , 'pt-ocdi' )
515
+ );
516
+ }
517
+
518
  // Add this message to log file.
519
  $log_added = self::append_to_file(
520
  __( 'The import files were successfully uploaded!', 'pt-ocdi' ) . self::import_file_info( $selected_import_files ),
533
  * @param array $selected_import_files array of selected import files.
534
  */
535
  public static function import_file_info( $selected_import_files ) {
536
+ $redux_file_string = array_reduce( $selected_import_files['redux'], function( $string, $item ) {
537
+ return sprintf( '%1$s%2$s -> %3$s %4$s', $string, $item['option_name'], $item['file_path'], PHP_EOL );
538
+ }, '' );
539
+
540
  return PHP_EOL .
541
  sprintf(
542
  __( 'Initial max execution time = %s', 'pt-ocdi' ),
543
  ini_get( 'max_execution_time' )
544
  ) . PHP_EOL .
545
  sprintf(
546
+ __( 'Files info:%1$sSite URL = %2$s%1$sData file = %3$s%1$sWidget file = %4$s%1$sCustomizer file = %5$s%1$sRedux files:%1$s%6$s', 'pt-ocdi' ),
547
  PHP_EOL,
548
  get_site_url(),
549
  $selected_import_files['content'],
550
  empty( $selected_import_files['widgets'] ) ? esc_html__( 'not defined!', 'pt-ocdi' ) : $selected_import_files['widgets'],
551
+ empty( $selected_import_files['customizer'] ) ? esc_html__( 'not defined!', 'pt-ocdi' ) : $selected_import_files['customizer'],
552
+ empty( $selected_import_files['redux'] ) ? esc_html__( 'not defined!', 'pt-ocdi' ) : $redux_file_string
553
  );
554
  }
555
 
562
  * @param string $separator title separating the old and new content.
563
  */
564
  public static function log_error_and_send_ajax_response( $error_text, $log_file_path, $separator = '' ) {
 
565
  // Add this error to log file.
566
  $log_added = self::append_to_file(
567
  $error_text,
572
  // Send JSON Error response to the AJAX call.
573
  wp_send_json( $error_text );
574
  }
575
+
576
+
577
+ /**
578
+ * Set the $demo_import_start_time class variable with the current date and time string.
579
+ */
580
+ public static function set_demo_import_start_time() {
581
+ self::$demo_import_start_time = date( apply_filters( 'pt-ocdi/date_format_for_file_names', 'Y-m-d__H-i-s' ) );
582
+ }
583
+
584
+
585
+ /**
586
+ * Get the category list of all categories used in the predefined demo imports array.
587
+ *
588
+ * @param array $demo_imports Array of demo import items (arrays).
589
+ * @return array|boolean List of all the categories or false if there aren't any.
590
+ */
591
+ public static function get_all_demo_import_categories( $demo_imports ) {
592
+ $categories = array();
593
+
594
+ foreach ( $demo_imports as $item ) {
595
+ if ( ! empty( $item['categories'] ) && is_array( $item['categories'] ) ) {
596
+ foreach ( $item['categories'] as $category ) {
597
+ $categories[ sanitize_key( $category ) ] = $category;
598
+ }
599
+ }
600
+ }
601
+
602
+ if ( empty( $categories ) ) {
603
+ return false;
604
+ }
605
+
606
+ return $categories;
607
+ }
608
+
609
+
610
+ /**
611
+ * Return the concatenated string of demo import item categories.
612
+ * These should be separated by comma and sanitized properly.
613
+ *
614
+ * @param array $item The predefined demo import item data.
615
+ * @return string The concatenated string of categories.
616
+ */
617
+ public static function get_demo_import_item_categories( $item ) {
618
+ $sanitized_categories = array();
619
+
620
+ if ( isset( $item['categories'] ) ) {
621
+ foreach ( $item['categories'] as $category ) {
622
+ $sanitized_categories[] = sanitize_key( $category );
623
+ }
624
+ }
625
+
626
+ if ( ! empty( $sanitized_categories ) ) {
627
+ return implode( ',', $sanitized_categories );
628
+ }
629
+
630
+ return false;
631
+ }
632
+
633
+
634
+ /**
635
+ * Set the OCDI transient with the current importer data.
636
+ *
637
+ * @param array $data Data to be saved to the transient.
638
+ */
639
+ public static function set_ocdi_import_data_transient( $data ) {
640
+ set_transient( 'ocdi_importer_data', $data, 0.1 * HOUR_IN_SECONDS );
641
+ }
642
  }
inc/ImportActions.php ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Class for the import actions used in the One Click Demo Import plugin.
4
+ * Register default WP actions for OCDI plugin.
5
+ *
6
+ * @package ocdi
7
+ */
8
+
9
+ namespace OCDI;
10
+
11
+ class ImportActions {
12
+ /**
13
+ * Register all action hooks for this class.
14
+ */
15
+ public function register_hooks() {
16
+ // Before content import.
17
+ add_action( 'pt-ocdi/before_content_import_execution', array( $this, 'before_content_import_action' ), 10, 3 );
18
+
19
+ // After content import.
20
+ add_action( 'pt-ocdi/after_content_import_execution', array( $this, 'before_widget_import_action' ), 10, 3 );
21
+ add_action( 'pt-ocdi/after_content_import_execution', array( $this, 'widgets_import' ), 20, 3 );
22
+ add_action( 'pt-ocdi/after_content_import_execution', array( $this, 'redux_import' ), 30, 3 );
23
+
24
+ // Customizer import.
25
+ add_action( 'pt-ocdi/customizer_import_execution', array( $this, 'customizer_import' ), 10, 1 );
26
+
27
+ // After full import action.
28
+ add_action( 'pt-ocdi/after_all_import_execution', array( $this, 'after_import_action' ), 10, 3 );
29
+ }
30
+
31
+
32
+ /**
33
+ * Execute the widgets import.
34
+ *
35
+ * @param array $selected_import_files Actual selected import files (content, widgets, customizer, redux).
36
+ * @param array $import_files The filtered import files defined in `pt-ocdi/import_files` filter.
37
+ * @param int $selected_index Selected index of import.
38
+ */
39
+ public function widgets_import( $selected_import_files, $import_files, $selected_index ) {
40
+ if ( ! empty( $selected_import_files['widgets'] ) ) {
41
+ WidgetImporter::import( $selected_import_files['widgets'] );
42
+ }
43
+ }
44
+
45
+
46
+ /**
47
+ * Execute the Redux import.
48
+ *
49
+ * @param array $selected_import_files Actual selected import files (content, widgets, customizer, redux).
50
+ * @param array $import_files The filtered import files defined in `pt-ocdi/import_files` filter.
51
+ * @param int $selected_index Selected index of import.
52
+ */
53
+ public function redux_import( $selected_import_files, $import_files, $selected_index ) {
54
+ if ( ! empty( $selected_import_files['redux'] ) ) {
55
+ ReduxImporter::import( $selected_import_files['redux'] );
56
+ }
57
+ }
58
+
59
+
60
+ /**
61
+ * Execute the customizer import.
62
+ *
63
+ * @param array $selected_import_files Actual selected import files (content, widgets, customizer, redux).
64
+ * @param array $import_files The filtered import files defined in `pt-ocdi/import_files` filter.
65
+ * @param int $selected_index Selected index of import.
66
+ */
67
+ public function customizer_import( $selected_import_files ) {
68
+ if ( ! empty( $selected_import_files['customizer'] ) ) {
69
+ CustomizerImporter::import( $selected_import_files['customizer'] );
70
+ }
71
+ }
72
+
73
+
74
+ /**
75
+ * Execute the action: 'pt-ocdi/before_content_import'.
76
+ *
77
+ * @param array $selected_import_files Actual selected import files (content, widgets, customizer, redux).
78
+ * @param array $import_files The filtered import files defined in `pt-ocdi/import_files` filter.
79
+ * @param int $selected_index Selected index of import.
80
+ */
81
+ public function before_content_import_action( $selected_import_files, $import_files, $selected_index ) {
82
+ $this->do_import_action( 'pt-ocdi/before_content_import', $import_files[ $selected_index ] );
83
+ }
84
+
85
+
86
+ /**
87
+ * Execute the action: 'pt-ocdi/before_widgets_import'.
88
+ *
89
+ * @param array $selected_import_files Actual selected import files (content, widgets, customizer, redux).
90
+ * @param array $import_files The filtered import files defined in `pt-ocdi/import_files` filter.
91
+ * @param int $selected_index Selected index of import.
92
+ */
93
+ public function before_widget_import_action( $selected_import_files, $import_files, $selected_index ) {
94
+ $this->do_import_action( 'pt-ocdi/before_widgets_import', $import_files[ $selected_index ] );
95
+ }
96
+
97
+
98
+ /**
99
+ * Execute the action: 'pt-ocdi/after_import'.
100
+ *
101
+ * @param array $selected_import_files Actual selected import files (content, widgets, customizer, redux).
102
+ * @param array $import_files The filtered import files defined in `pt-ocdi/import_files` filter.
103
+ * @param int $selected_index Selected index of import.
104
+ */
105
+ public function after_import_action( $selected_import_files, $import_files, $selected_index ) {
106
+ $this->do_import_action( 'pt-ocdi/after_import', $import_files[ $selected_index ] );
107
+ }
108
+
109
+
110
+ /**
111
+ * Register the do_action hook, so users can hook to these during import.
112
+ *
113
+ * @param string $action The action name to be executed.
114
+ * @param array $selected_import The data of selected import from `pt-ocdi/import_files` filter.
115
+ */
116
+ private function do_import_action( $action, $selected_import ) {
117
+ if ( false !== has_action( $action ) ) {
118
+ $ocdi = OneClickDemoImport::get_instance();
119
+ $log_file_path = $ocdi->get_log_file_path();
120
+
121
+ ob_start();
122
+ do_action( $action, $selected_import );
123
+ $message = ob_get_clean();
124
+
125
+ // Add this message to log file.
126
+ $log_added = Helpers::append_to_file(
127
+ $message,
128
+ $log_file_path,
129
+ $action
130
+ );
131
+ }
132
+ }
133
+ }
inc/Importer.php ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Class for declaring the content importer used in the One Click Demo Import plugin
4
+ *
5
+ * @package ocdi
6
+ */
7
+
8
+ namespace OCDI;
9
+
10
+ class Importer {
11
+ /**
12
+ * The importer class object used for importing content.
13
+ *
14
+ * @var object
15
+ */
16
+ private $importer;
17
+
18
+ /**
19
+ * Time in milliseconds, marking the beginning of the import.
20
+ *
21
+ * @var float
22
+ */
23
+ private $microtime;
24
+
25
+ /**
26
+ * The instance of the OCDI\Logger class.
27
+ *
28
+ * @var object
29
+ */
30
+ private $logger;
31
+
32
+ /**
33
+ * The instance of the One Click Demo Import class.
34
+ *
35
+ * @var object
36
+ */
37
+ private $ocdi;
38
+
39
+ /**
40
+ * Constructor method.
41
+ *
42
+ * @param array $importer_options Importer options.
43
+ * @param object $logger Logger object used in the importer.
44
+ */
45
+ public function __construct( $importer_options = array(), $logger = null ) {
46
+ // Include files that are needed for WordPress Importer v2.
47
+ $this->include_required_files();
48
+
49
+ // Set the WordPress Importer v2 as the importer used in this plugin.
50
+ // More: https://github.com/humanmade/WordPress-Importer.
51
+ $this->importer = new WXRImporter( $importer_options );
52
+
53
+ // Set logger to the importer.
54
+ $this->logger = $logger;
55
+ if ( ! empty( $this->logger ) ) {
56
+ $this->set_logger( $this->logger );
57
+ }
58
+
59
+ // Get the OCDI (main plugin class) instance.
60
+ $this->ocdi = OneClickDemoImport::get_instance();
61
+ }
62
+
63
+
64
+ /**
65
+ * Include required files.
66
+ */
67
+ private function include_required_files() {
68
+ if ( ! class_exists( '\WP_Importer' ) ) {
69
+ defined( 'WP_LOAD_IMPORTERS' ) || define( 'WP_LOAD_IMPORTERS', true );
70
+ require ABSPATH . '/wp-admin/includes/class-wp-importer.php';
71
+ }
72
+ }
73
+
74
+
75
+ /**
76
+ * Imports content from a WordPress export file.
77
+ *
78
+ * @param string $data_file path to xml file, file with WordPress export data.
79
+ */
80
+ public function import( $data_file ) {
81
+ $this->importer->import( $data_file );
82
+ }
83
+
84
+
85
+ /**
86
+ * Set the logger used in the import
87
+ *
88
+ * @param object $logger logger instance.
89
+ */
90
+ public function set_logger( $logger ) {
91
+ $this->importer->set_logger( $logger );
92
+ }
93
+
94
+
95
+ /**
96
+ * Get all protected variables from the WXR_Importer needed for continuing the import.
97
+ */
98
+ public function get_importer_data() {
99
+ return $this->importer->get_importer_data();
100
+ }
101
+
102
+
103
+ /**
104
+ * Sets all protected variables from the WXR_Importer needed for continuing the import.
105
+ *
106
+ * @param array $data with set variables.
107
+ */
108
+ public function set_importer_data( $data ) {
109
+ $this->importer->set_importer_data( $data );
110
+ }
111
+
112
+
113
+ /**
114
+ * Import content from an WP XML file.
115
+ *
116
+ * @param string $import_file_path Path to the import file.
117
+ */
118
+ public function import_content( $import_file_path ) {
119
+ $this->microtime = microtime( true );
120
+
121
+ // Increase PHP max execution time. Just in case, even though the AJAX calls are only 25 sec long.
122
+ set_time_limit( apply_filters( 'pt-ocdi/set_time_limit_for_demo_data_import', 300 ) );
123
+
124
+ // Disable import of authors.
125
+ add_filter( 'wxr_importer.pre_process.user', '__return_false' );
126
+
127
+ // Check, if we need to send another AJAX request and set the importing author to the current user.
128
+ add_filter( 'wxr_importer.pre_process.post', array( $this, 'new_ajax_request_maybe' ) );
129
+
130
+ // Disables generation of multiple image sizes (thumbnails) in the content import step.
131
+ if ( ! apply_filters( 'pt-ocdi/regenerate_thumbnails_in_content_import', true ) ) {
132
+ add_filter( 'intermediate_image_sizes_advanced', '__return_null' );
133
+ }
134
+
135
+ // Import content.
136
+ if ( ! empty( $import_file_path ) ) {
137
+ ob_start();
138
+ $this->import( $import_file_path );
139
+ $message = ob_get_clean();
140
+ }
141
+
142
+ // Return any error messages for the front page output (errors, critical, alert and emergency level messages only).
143
+ return $this->logger->error_output;
144
+ }
145
+
146
+
147
+ /**
148
+ * Check if we need to create a new AJAX request, so that server does not timeout.
149
+ *
150
+ * @param array $data current post data.
151
+ * @return array
152
+ */
153
+ public function new_ajax_request_maybe( $data ) {
154
+ $time = microtime( true ) - $this->microtime;
155
+
156
+ // We should make a new ajax call, if the time is right.
157
+ if ( $time > apply_filters( 'pt-ocdi/time_for_one_ajax_call', 25 ) ) {
158
+ $response = array(
159
+ 'status' => 'newAJAX',
160
+ 'message' => 'Time for new AJAX request!: ' . $time,
161
+ );
162
+
163
+ // Add any output to the log file and clear the buffers.
164
+ $message = ob_get_clean();
165
+
166
+ // Add any error messages to the frontend_error_messages variable in OCDI main class.
167
+ if ( ! empty( $message ) ) {
168
+ $this->ocdi->append_to_frontend_error_messages( $message );
169
+ }
170
+
171
+ // Add message to log file.
172
+ $log_added = Helpers::append_to_file(
173
+ __( 'New AJAX call!' , 'pt-ocdi' ) . PHP_EOL . $message,
174
+ $this->ocdi->get_log_file_path(),
175
+ ''
176
+ );
177
+
178
+ // Set the current importer stat, so it can be continued on the next AJAX call.
179
+ $this->set_current_importer_data();
180
+
181
+ // Send the request for a new AJAX call.
182
+ wp_send_json( $response );
183
+ }
184
+
185
+ // Set importing author to the current user.
186
+ // Fixes the [WARNING] Could not find the author for ... log warning messages.
187
+ $current_user_obj = wp_get_current_user();
188
+ $data['post_author'] = $current_user_obj->user_login;
189
+
190
+ return $data;
191
+ }
192
+
193
+
194
+ /**
195
+ * Set current state of the content importer, so we can continue the import with new AJAX request.
196
+ */
197
+ private function set_current_importer_data() {
198
+ $data = array_merge( $this->ocdi->get_current_importer_data(), $this->get_importer_data() );
199
+
200
+ Helpers::set_ocdi_import_data_transient( $data );
201
+ }
202
+ }
inc/{class-ocdi-logger.php → Logger.php} RENAMED
@@ -5,10 +5,13 @@
5
  * @package ocdi
6
  */
7
 
8
- class OCDI_Logger extends ProteusThemes\WPContentImporter2\WPImporterLoggerCLI {
9
 
 
10
  /**
11
  * Variable for front-end error display.
 
 
12
  */
13
  public $error_output = '';
14
 
@@ -22,7 +25,6 @@ class OCDI_Logger extends ProteusThemes\WPContentImporter2\WPImporterLoggerCLI {
22
  * @param array $context context to the log message.
23
  */
24
  public function log( $level, $message, array $context = array() ) {
25
-
26
  // Save error messages for front-end display.
27
  $this->error_output( $level, $message, $context = array() );
28
 
5
  * @package ocdi
6
  */
7
 
8
+ namespace OCDI;
9
 
10
+ class Logger extends \ProteusThemes\WPContentImporter2\WPImporterLoggerCLI {
11
  /**
12
  * Variable for front-end error display.
13
+ *
14
+ * @var string
15
  */
16
  public $error_output = '';
17
 
25
  * @param array $context context to the log message.
26
  */
27
  public function log( $level, $message, array $context = array() ) {
 
28
  // Save error messages for front-end display.
29
  $this->error_output( $level, $message, $context = array() );
30
 
inc/OneClickDemoImport.php ADDED
@@ -0,0 +1,520 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Main One Click Demo Import plugin class/file.
4
+ *
5
+ * @package ocdi
6
+ */
7
+
8
+ namespace OCDI;
9
+
10
+ /**
11
+ * One Click Demo Import class, so we don't have to worry about namespaces.
12
+ */
13
+ class OneClickDemoImport {
14
+ /**
15
+ * The instance *Singleton* of this class
16
+ *
17
+ * @var object
18
+ */
19
+ private static $instance;
20
+
21
+ /**
22
+ * The instance of the OCDI\Importer class.
23
+ *
24
+ * @var object
25
+ */
26
+ private $importer;
27
+
28
+ /**
29
+ * The resulting page's hook_suffix, or false if the user does not have the capability required.
30
+ *
31
+ * @var boolean or string
32
+ */
33
+ private $plugin_page;
34
+
35
+ /**
36
+ * Holds the verified import files.
37
+ *
38
+ * @var array
39
+ */
40
+ private $import_files;
41
+
42
+ /**
43
+ * The path of the log file.
44
+ *
45
+ * @var string
46
+ */
47
+ private $log_file_path;
48
+
49
+ /**
50
+ * The index of the `import_files` array (which import files was selected).
51
+ *
52
+ * @var int
53
+ */
54
+ private $selected_index;
55
+
56
+ /**
57
+ * The paths of the actual import files to be used in the import.
58
+ *
59
+ * @var array
60
+ */
61
+ private $selected_import_files;
62
+
63
+ /**
64
+ * Holds any error messages, that should be printed out at the end of the import.
65
+ *
66
+ * @var string
67
+ */
68
+ private $frontend_error_messages = array();
69
+
70
+ /**
71
+ * Was the before content import already triggered?
72
+ *
73
+ * @var boolean
74
+ */
75
+ private $before_import_executed = false;
76
+
77
+
78
+ /**
79
+ * Returns the *Singleton* instance of this class.
80
+ *
81
+ * @return PT_One_Click_Demo_Import the *Singleton* instance.
82
+ */
83
+ public static function get_instance() {
84
+ if ( null === static::$instance ) {
85
+ static::$instance = new static();
86
+ }
87
+
88
+ return static::$instance;
89
+ }
90
+
91
+
92
+ /**
93
+ * Class construct function, to initiate the plugin.
94
+ * Protected constructor to prevent creating a new instance of the
95
+ * *Singleton* via the `new` operator from outside of this class.
96
+ */
97
+ protected function __construct() {
98
+ // Actions.
99
+ add_action( 'admin_menu', array( $this, 'create_plugin_page' ) );
100
+ add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
101
+ add_action( 'wp_ajax_ocdi_import_demo_data', array( $this, 'import_demo_data_ajax_callback' ) );
102
+ add_action( 'wp_ajax_ocdi_import_customizer_data', array( $this, 'import_customizer_data_ajax_callback' ) );
103
+ add_action( 'wp_ajax_ocdi_after_import_data', array( $this, 'after_all_import_data_ajax_callback' ) );
104
+ add_action( 'after_setup_theme', array( $this, 'setup_plugin_with_filter_data' ) );
105
+ add_action( 'plugins_loaded', array( $this, 'load_textdomain' ) );
106
+ }
107
+
108
+
109
+ /**
110
+ * Private clone method to prevent cloning of the instance of the *Singleton* instance.
111
+ *
112
+ * @return void
113
+ */
114
+ private function __clone() {}
115
+
116
+
117
+ /**
118
+ * Private unserialize method to prevent unserializing of the *Singleton* instance.
119
+ *
120
+ * @return void
121
+ */
122
+ private function __wakeup() {}
123
+
124
+
125
+ /**
126
+ * Creates the plugin page and a submenu item in WP Appearance menu.
127
+ */
128
+ public function create_plugin_page() {
129
+ $plugin_page_setup = apply_filters( 'pt-ocdi/plugin_page_setup', array(
130
+ 'parent_slug' => 'themes.php',
131
+ 'page_title' => esc_html__( 'One Click Demo Import' , 'pt-ocdi' ),
132
+ 'menu_title' => esc_html__( 'Import Demo Data' , 'pt-ocdi' ),
133
+ 'capability' => 'import',
134
+ 'menu_slug' => 'pt-one-click-demo-import',
135
+ )
136
+ );
137
+
138
+ $this->plugin_page = add_submenu_page(
139
+ $plugin_page_setup['parent_slug'],
140
+ $plugin_page_setup['page_title'],
141
+ $plugin_page_setup['menu_title'],
142
+ $plugin_page_setup['capability'],
143
+ $plugin_page_setup['menu_slug'],
144
+ apply_filters( 'pt-ocdi/plugin_page_display_callback_function', array( $this, 'display_plugin_page' ) )
145
+ );
146
+ }
147
+
148
+
149
+ /**
150
+ * Plugin page display.
151
+ * Output (HTML) is in another file.
152
+ */
153
+ public function display_plugin_page() {
154
+ require_once PT_OCDI_PATH . 'views/plugin-page.php';
155
+ }
156
+
157
+
158
+ /**
159
+ * Enqueue admin scripts (JS and CSS)
160
+ *
161
+ * @param string $hook holds info on which admin page you are currently loading.
162
+ */
163
+ public function admin_enqueue_scripts( $hook ) {
164
+ // Enqueue the scripts only on the plugin page.
165
+ if ( $this->plugin_page === $hook ) {
166
+ wp_enqueue_script( 'jquery-ui-dialog' );
167
+ wp_enqueue_style( 'wp-jquery-ui-dialog' );
168
+
169
+ wp_enqueue_script( 'ocdi-main-js', PT_OCDI_URL . 'assets/js/main.js' , array( 'jquery', 'jquery-ui-dialog' ), PT_OCDI_VERSION );
170
+
171
+ // Get theme data.
172
+ $theme = wp_get_theme();
173
+
174
+ wp_localize_script( 'ocdi-main-js', 'ocdi',
175
+ array(
176
+ 'ajax_url' => admin_url( 'admin-ajax.php' ),
177
+ 'ajax_nonce' => wp_create_nonce( 'ocdi-ajax-verification' ),
178
+ 'import_files' => $this->import_files,
179
+ 'import_popup' => apply_filters( 'pt-ocdi/enable_grid_layout_import_popup_confirmation', true ),
180
+ 'theme_screenshot' => $theme->get_screenshot(),
181
+ 'texts' => array(
182
+ 'missing_preview_image' => esc_html__( 'No preview image defined for this import.', 'pt-ocdi' ),
183
+ 'dialog_title' => esc_html__( 'Are you sure?', 'pt-ocdi' ),
184
+ 'dialog_no' => esc_html__( 'Cancel', 'pt-ocdi' ),
185
+ 'dialog_yes' => esc_html__( 'Yes, import!', 'pt-ocdi' ),
186
+ 'selected_import_title' => esc_html__( 'Selected demo import:', 'pt-ocdi' ),
187
+ ),
188
+ )
189
+ );
190
+
191
+ wp_enqueue_style( 'ocdi-main-css', PT_OCDI_URL . 'assets/css/main.css', array() , PT_OCDI_VERSION );
192
+ }
193
+ }
194
+
195
+
196
+ /**
197
+ * Main AJAX callback function for:
198
+ * 1). prepare import files (uploaded or predefined via filters)
199
+ * 2). execute 'before content import' actions (before import WP action)
200
+ * 3). import content
201
+ * 4). execute 'after content import' actions (before widget import WP action, widget import, customizer import, after import WP action)
202
+ */
203
+ public function import_demo_data_ajax_callback() {
204
+ // Try to update PHP memory limit (so that it does not run out of it).
205
+ ini_set( 'memory_limit', apply_filters( 'pt-ocdi/import_memory_limit', '350M' ) );
206
+
207
+ // Verify if the AJAX call is valid (checks nonce and current_user_can).
208
+ Helpers::verify_ajax_call();
209
+
210
+ // Is this a new AJAX call to continue the previous import?
211
+ $use_existing_importer_data = $this->use_existing_importer_data();
212
+
213
+ if ( ! $use_existing_importer_data ) {
214
+ // Create a date and time string to use for demo and log file names.
215
+ Helpers::set_demo_import_start_time();
216
+
217
+ // Define log file path.
218
+ $this->log_file_path = Helpers::get_log_path();
219
+
220
+ // Get selected file index or set it to 0.
221
+ $this->selected_index = empty( $_POST['selected'] ) ? 0 : absint( $_POST['selected'] );
222
+
223
+ /**
224
+ * 1). Prepare import files.
225
+ * Manually uploaded import files or predefined import files via filter: pt-ocdi/import_files
226
+ */
227
+ if ( ! empty( $_FILES ) ) { // Using manual file uploads?
228
+ // Get paths for the uploaded files.
229
+ $this->selected_import_files = Helpers::process_uploaded_files( $_FILES, $this->log_file_path );
230
+
231
+ // Set the name of the import files, because we used the uploaded files.
232
+ $this->import_files[ $this->selected_index ]['import_file_name'] = esc_html__( 'Manually uploaded files', 'pt-ocdi' );
233
+ }
234
+ elseif ( ! empty( $this->import_files[ $this->selected_index ] ) ) { // Use predefined import files from wp filter: pt-ocdi/import_files.
235
+
236
+ // Download the import files (content, widgets and customizer files).
237
+ $this->selected_import_files = Helpers::download_import_files( $this->import_files[ $this->selected_index ] );
238
+
239
+ // Check Errors.
240
+ if ( is_wp_error( $this->selected_import_files ) ) {
241
+ // Write error to log file and send an AJAX response with the error.
242
+ Helpers::log_error_and_send_ajax_response(
243
+ $this->selected_import_files->get_error_message(),
244
+ $this->log_file_path,
245
+ esc_html__( 'Downloaded files', 'pt-ocdi' )
246
+ );
247
+ }
248
+
249
+ // Add this message to log file.
250
+ $log_added = Helpers::append_to_file(
251
+ sprintf(
252
+ __( 'The import files for: %s were successfully downloaded!', 'pt-ocdi' ),
253
+ $this->import_files[ $this->selected_index ]['import_file_name']
254
+ ) . Helpers::import_file_info( $this->selected_import_files ),
255
+ $this->log_file_path,
256
+ esc_html__( 'Downloaded files' , 'pt-ocdi' )
257
+ );
258
+ }
259
+ else {
260
+ // Send JSON Error response to the AJAX call.
261
+ wp_send_json( esc_html__( 'No import files specified!', 'pt-ocdi' ) );
262
+ }
263
+ }
264
+
265
+ // Save the initial import data as a transient, so other import parts (in new AJAX calls) can use that data.
266
+ Helpers::set_ocdi_import_data_transient( $this->get_current_importer_data() );
267
+
268
+ if ( ! $this->before_import_executed ) {
269
+ $this->before_import_executed = true;
270
+
271
+ /**
272
+ * 2). Execute the actions hooked to the 'pt-ocdi/before_content_import_execution' action:
273
+ *
274
+ * Default actions:
275
+ * 1 - Before content import WP action (with priority 10).
276
+ */
277
+ do_action( 'pt-ocdi/before_content_import_execution', $this->selected_import_files, $this->import_files, $this->selected_index );
278
+ }
279
+
280
+ /**
281
+ * 3). Import content.
282
+ * Returns any errors greater then the "warning" logger level, that will be displayed on front page.
283
+ */
284
+ $this->append_to_frontend_error_messages( $this->importer->import_content( $this->selected_import_files['content'] ) );
285
+
286
+ /**
287
+ * 4). Execute the actions hooked to the 'pt-ocdi/after_content_import_execution' action:
288
+ *
289
+ * Default actions:
290
+ * 1 - Before widgets import setup (with priority 10).
291
+ * 2 - Import widgets (with priority 20).
292
+ * 3 - Import Redux data (with priority 30).
293
+ */
294
+ do_action( 'pt-ocdi/after_content_import_execution', $this->selected_import_files, $this->import_files, $this->selected_index );
295
+
296
+ // Save the import data as a transient, so other import parts (in new AJAX calls) can use that data.
297
+ Helpers::set_ocdi_import_data_transient( $this->get_current_importer_data() );
298
+
299
+ // Request the customizer import AJAX call.
300
+ if ( ! empty( $this->selected_import_files['customizer'] ) ) {
301
+ wp_send_json( array( 'status' => 'customizerAJAX' ) );
302
+ }
303
+
304
+ // Request the after all import AJAX call.
305
+ if ( false !== has_action( 'pt-ocdi/after_all_import_execution' ) ) {
306
+ wp_send_json( array( 'status' => 'afterAllImportAJAX' ) );
307
+ }
308
+
309
+ // Send a JSON response with final report.
310
+ $this->final_response();
311
+ }
312
+
313
+
314
+ /**
315
+ * AJAX callback for importing the customizer data.
316
+ * This request has the wp_customize set to 'on', so that the customizer hooks can be called
317
+ * (they can only be called with the $wp_customize instance). But if the $wp_customize is defined,
318
+ * then the widgets do not import correctly, that's why the customizer import has its own AJAX call.
319
+ */
320
+ public function import_customizer_data_ajax_callback() {
321
+ // Verify if the AJAX call is valid (checks nonce and current_user_can).
322
+ Helpers::verify_ajax_call();
323
+
324
+ // Get existing import data.
325
+ if ( $this->use_existing_importer_data() ) {
326
+ /**
327
+ * Execute the customizer import actions.
328
+ *
329
+ * Default actions:
330
+ * 1 - Customizer import (with priority 10).
331
+ */
332
+ do_action( 'pt-ocdi/customizer_import_execution', $this->selected_import_files );
333
+ }
334
+
335
+ // Request the after all import AJAX call.
336
+ if ( false !== has_action( 'pt-ocdi/after_all_import_execution' ) ) {
337
+ wp_send_json( array( 'status' => 'afterAllImportAJAX' ) );
338
+ }
339
+
340
+ // Send a JSON response with final report.
341
+ $this->final_response();
342
+ }
343
+
344
+
345
+ /**
346
+ * AJAX callback for the after all import action.
347
+ */
348
+ public function after_all_import_data_ajax_callback() {
349
+ // Verify if the AJAX call is valid (checks nonce and current_user_can).
350
+ Helpers::verify_ajax_call();
351
+
352
+ // Get existing import data.
353
+ if ( $this->use_existing_importer_data() ) {
354
+ /**
355
+ * Execute the after all import actions.
356
+ *
357
+ * Default actions:
358
+ * 1 - after_import action (with priority 10).
359
+ */
360
+ do_action( 'pt-ocdi/after_all_import_execution', $this->selected_import_files, $this->import_files, $this->selected_index );
361
+ }
362
+
363
+ // Send a JSON response with final report.
364
+ $this->final_response();
365
+ }
366
+
367
+
368
+ /**
369
+ * Send a JSON response with final report.
370
+ */
371
+ private function final_response() {
372
+ // Delete importer data transient for current import.
373
+ delete_transient( 'ocdi_importer_data' );
374
+
375
+ // Display final messages (success or error messages).
376
+ if ( empty( $this->frontend_error_messages ) ) {
377
+ $response['message'] = sprintf(
378
+ __( '%1$s%3$sThat\'s it, all done!%4$s%2$sThe demo import has finished. Please check your page and make sure that everything has imported correctly. If it did, you can deactivate the %3$sOne Click Demo Import%4$s plugin, because it has done its job.%5$s', 'pt-ocdi' ),
379
+ '<div class="notice notice-success"><p>',
380
+ '<br>',
381
+ '<strong>',
382
+ '</strong>',
383
+ '</p></div>'
384
+ );
385
+ }
386
+ else {
387
+ $response['message'] = $this->frontend_error_messages_display() . '<br>';
388
+ $response['message'] .= sprintf(
389
+ __( '%1$sThe demo import has finished, but there were some import errors.%2$sMore details about the errors can be found in this %3$s%5$slog file%6$s%4$s%7$s', 'pt-ocdi' ),
390
+ '<div class="notice notice-warning"><p>',
391
+ '<br>',
392
+ '<strong>',
393
+ '</strong>',
394
+ '<a href="' . Helpers::get_log_url( $this->log_file_path ) .'" target="_blank">',
395
+ '</a>',
396
+ '</p></div>'
397
+ );
398
+ }
399
+
400
+ wp_send_json( $response );
401
+ }
402
+
403
+
404
+ /**
405
+ * Get content importer data, so we can continue the import with this new AJAX request.
406
+ *
407
+ * @return boolean
408
+ */
409
+ private function use_existing_importer_data() {
410
+ if ( $data = get_transient( 'ocdi_importer_data' ) ) {
411
+ $this->frontend_error_messages = empty( $data['frontend_error_messages'] ) ? array() : $data['frontend_error_messages'];
412
+ $this->log_file_path = empty( $data['log_file_path'] ) ? '' : $data['log_file_path'];
413
+ $this->selected_index = empty( $data['selected_index'] ) ? 0 : $data['selected_index'];
414
+ $this->selected_import_files = empty( $data['selected_import_files'] ) ? array() : $data['selected_import_files'];
415
+ $this->before_import_executed = empty( $data['before_import_executed'] ) ? false : $data['before_import_executed'];
416
+ $this->importer->set_importer_data( $data );
417
+
418
+ return true;
419
+ }
420
+ return false;
421
+ }
422
+
423
+
424
+ /**
425
+ * Get the current state of selected data.
426
+ *
427
+ * @return array
428
+ */
429
+ public function get_current_importer_data() {
430
+ return array(
431
+ 'frontend_error_messages' => $this->frontend_error_messages,
432
+ 'log_file_path' => $this->log_file_path,
433
+ 'selected_index' => $this->selected_index,
434
+ 'selected_import_files' => $this->selected_import_files,
435
+ 'before_import_executed' => $this->before_import_executed,
436
+ );
437
+ }
438
+
439
+
440
+ /**
441
+ * Getter function to retrieve the private log_file_path value.
442
+ *
443
+ * @return string The log_file_path value.
444
+ */
445
+ public function get_log_file_path() {
446
+ return $this->log_file_path;
447
+ }
448
+
449
+
450
+ /**
451
+ * Setter function to append additional value to the private frontend_error_messages value.
452
+ *
453
+ * @param string $additional_value The additional value that will be appended to the existing frontend_error_messages.
454
+ */
455
+ public function append_to_frontend_error_messages( $text ) {
456
+ if ( ! empty( $text ) && ! in_array( $text , $this->frontend_error_messages ) ) {
457
+ $this->frontend_error_messages[] = $text;
458
+ }
459
+ }
460
+
461
+
462
+ /**
463
+ * Display the frontend error messages.
464
+ *
465
+ * @return string Text with HTML markup.
466
+ */
467
+ public function frontend_error_messages_display() {
468
+ $output = '';
469
+
470
+ if ( ! empty( $this->frontend_error_messages ) ) {
471
+ foreach ( $this->frontend_error_messages as $line ) {
472
+ $output .= nl2br( $line );
473
+ $output .= '<br>';
474
+ }
475
+ }
476
+
477
+ return $output;
478
+ }
479
+
480
+
481
+ /**
482
+ * Load the plugin textdomain, so that translations can be made.
483
+ */
484
+ public function load_textdomain() {
485
+ load_plugin_textdomain( 'pt-ocdi', false, plugin_basename( dirname( __FILE__ ) ) . '/languages' );
486
+ }
487
+
488
+
489
+ /**
490
+ * Get data from filters, after the theme has loaded and instantiate the importer.
491
+ */
492
+ public function setup_plugin_with_filter_data() {
493
+ // Get info of import data files and filter it.
494
+ $this->import_files = Helpers::validate_import_file_info( apply_filters( 'pt-ocdi/import_files', array() ) );
495
+
496
+ /**
497
+ * Register all default actions (before content import, widget, customizer import and other actions)
498
+ * to the 'before_content_import_execution' and the 'pt-ocdi/after_content_import_execution' action hook.
499
+ */
500
+ $import_actions = new ImportActions();
501
+ $import_actions->register_hooks();
502
+
503
+ // Importer options array.
504
+ $importer_options = apply_filters( 'pt-ocdi/importer_options', array(
505
+ 'fetch_attachments' => true,
506
+ ) );
507
+
508
+ // Logger options for the logger used in the importer.
509
+ $logger_options = apply_filters( 'pt-ocdi/logger_options', array(
510
+ 'logger_min_level' => 'warning',
511
+ ) );
512
+
513
+ // Configure logger instance and set it to the importer.
514
+ $logger = new Logger();
515
+ $logger->min_level = $logger_options['logger_min_level'];
516
+
517
+ // Create importer instance with proper parameters.
518
+ $this->importer = new Importer( $importer_options, $logger );
519
+ }
520
+ }
inc/ReduxImporter.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Class for the Redux importer used in the One Click Demo Import plugin.
4
+ *
5
+ * @see https://wordpress.org/plugins/redux-framework/
6
+ * @package ocdi
7
+ */
8
+
9
+ namespace OCDI;
10
+
11
+ class ReduxImporter {
12
+ /**
13
+ * Import Redux data from a JSON file, generated by the Redux plugin.
14
+ *
15
+ * @param array $import_data Array of arrays. Child array contains 'option_name' and 'file_path'.
16
+ */
17
+ public static function import( $import_data ) {
18
+ $ocdi = OneClickDemoImport::get_instance();
19
+ $log_file_path = $ocdi->get_log_file_path();
20
+
21
+ // Redux plugin is not active!
22
+ if ( ! class_exists( 'ReduxFramework' ) ) {
23
+ $error_message = esc_html__( 'The Redux plugin is not activated, so the Redux import was skipped!', 'pt-ocdi' );
24
+
25
+ // Add any error messages to the frontend_error_messages variable in OCDI main class.
26
+ $ocdi->append_to_frontend_error_messages( $error_message );
27
+
28
+ // Write error to log file.
29
+ Helpers::append_to_file(
30
+ $error_message,
31
+ $log_file_path,
32
+ esc_html__( 'Importing Redux settings' , 'pt-ocdi' )
33
+ );
34
+
35
+ return;
36
+ }
37
+
38
+ foreach ( $import_data as $redux_item ) {
39
+ $redux_options_raw_data = Helpers::data_from_file( $redux_item['file_path'] );
40
+
41
+ $redux_options_data = json_decode( $redux_options_raw_data, true );
42
+
43
+ $redux_framework = \ReduxFrameworkInstances::get_instance( $redux_item['option_name'] );
44
+
45
+ if ( isset( $redux_framework->args['opt_name'] ) ) {
46
+ // Import Redux settings.
47
+ $redux_framework->set_options( $redux_options_data );
48
+
49
+ // Add this message to log file.
50
+ $log_added = Helpers::append_to_file(
51
+ sprintf( esc_html__( 'Redux settings import for: %s finished successfully!', 'pt-ocdi' ), $redux_item['option_name'] ),
52
+ $log_file_path,
53
+ esc_html__( 'Importing Redux settings' , 'pt-ocdi' )
54
+ );
55
+ }
56
+ else {
57
+ $error_message = sprintf( esc_html__( 'The Redux option name: %s, was not found in this WP site, so it was not imported!', 'pt-ocdi' ), $redux_item['option_name'] );
58
+
59
+ // Add any error messages to the frontend_error_messages variable in OCDI main class.
60
+ $ocdi->append_to_frontend_error_messages( $error_message );
61
+
62
+ // Write error to log file.
63
+ Helpers::append_to_file(
64
+ $error_message,
65
+ $log_file_path,
66
+ esc_html__( 'Importing Redux settings' , 'pt-ocdi' )
67
+ );
68
+ }
69
+ }
70
+ }
71
+ }
inc/{class-ocdi-wxr-importer.php → WXRImporter.php} RENAMED
@@ -7,8 +7,14 @@
7
  * @package ocdi
8
  */
9
 
10
- class OCDI_WXR_Importer extends ProteusThemes\WPContentImporter2\WXRImporter {
11
 
 
 
 
 
 
 
12
  public function __construct( $options = array() ) {
13
  parent::__construct( $options );
14
 
7
  * @package ocdi
8
  */
9
 
10
+ namespace OCDI;
11
 
12
+ class WXRImporter extends \ProteusThemes\WPContentImporter2\WXRImporter {
13
+ /**
14
+ * Constructor method.
15
+ *
16
+ * @param array $options Importer options.
17
+ */
18
  public function __construct( $options = array() ) {
19
  parent::__construct( $options );
20
 
inc/{class-ocdi-widget-importer.php → WidgetImporter.php} RENAMED
@@ -8,17 +8,62 @@
8
  * @package ocdi
9
  */
10
 
11
- class OCDI_Widget_Importer {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
  /**
14
  * Imports widgets from a json file.
15
  *
16
  * @param string $data_file path to json file with WordPress widget export data.
17
  */
18
- public function import_widgets( $data_file ) {
19
-
20
  // Get widgets data from file.
21
- $data = $this->process_import_file( $data_file );
22
 
23
  // Return from this function if there was an error.
24
  if ( is_wp_error( $data ) ) {
@@ -26,7 +71,7 @@ class OCDI_Widget_Importer {
26
  }
27
 
28
  // Import the widget data and save the results.
29
- return $this->import_data( $data );
30
  }
31
 
32
  /**
@@ -35,18 +80,17 @@ class OCDI_Widget_Importer {
35
  * @param string $file path to json file.
36
  * @return object $data decoded JSON string
37
  */
38
- private function process_import_file( $file ) {
39
-
40
  // File exists?
41
  if ( ! file_exists( $file ) ) {
42
- return new WP_Error(
43
  'widget_import_file_not_found',
44
- __( 'Widget import file could not be found.', 'pt-ocdi' )
45
  );
46
  }
47
 
48
  // Get file contents and decode.
49
- $data = OCDI_Helpers::data_from_file( $file );
50
 
51
  // Return from this function if there was an error.
52
  if ( is_wp_error( $data ) ) {
@@ -57,7 +101,6 @@ class OCDI_Widget_Importer {
57
  }
58
 
59
 
60
-
61
  /**
62
  * Import widget JSON data
63
  *
@@ -65,15 +108,14 @@ class OCDI_Widget_Importer {
65
  * @param object $data JSON widget data.
66
  * @return array $results
67
  */
68
- private function import_data( $data ) {
69
-
70
  global $wp_registered_sidebars;
71
 
72
  // Have valid data? If no data or could not decode.
73
  if ( empty( $data ) || ! is_object( $data ) ) {
74
- return new WP_Error(
75
  'corrupted_widget_import_data',
76
- __( 'Widget import data could not be read. Please try a different file.', 'pt-ocdi' )
77
  );
78
  }
79
 
@@ -82,7 +124,7 @@ class OCDI_Widget_Importer {
82
  $data = apply_filters( 'pt-ocdi/before_widgets_import_data', $data );
83
 
84
  // Get all available widgets site supports.
85
- $available_widgets = $this->available_widgets();
86
 
87
  // Get all existing widget instances.
88
  $widget_instances = array();
@@ -96,7 +138,6 @@ class OCDI_Widget_Importer {
96
 
97
  // Loop import data's sidebars.
98
  foreach ( $data as $sidebar_id => $widgets ) {
99
-
100
  // Skip inactive widgets (should not be in export file).
101
  if ( 'wp_inactive_widgets' == $sidebar_id ) {
102
  continue;
@@ -124,7 +165,6 @@ class OCDI_Widget_Importer {
124
 
125
  // Loop widgets.
126
  foreach ( $widgets as $widget_instance_id => $widget ) {
127
-
128
  $fail = false;
129
 
130
  // Get id_base (remove -# from end) and instance ID number.
@@ -157,7 +197,6 @@ class OCDI_Widget_Importer {
157
 
158
  // Does widget with identical settings already exist in same sidebar?
159
  if ( ! $fail && isset( $widget_instances[ $id_base ] ) ) {
160
-
161
  // Get existing widgets in this sidebar.
162
  $sidebars_widgets = get_option( 'sidebars_widgets' );
163
  $sidebar_widgets = isset( $sidebars_widgets[ $use_sidebar_id ] ) ? $sidebars_widgets[ $use_sidebar_id ] : array(); // Check Inactive if that's where will go.
@@ -165,7 +204,6 @@ class OCDI_Widget_Importer {
165
  // Loop widgets with ID base.
166
  $single_widget_instances = ! empty( $widget_instances[ $id_base ] ) ? $widget_instances[ $id_base ] : array();
167
  foreach ( $single_widget_instances as $check_id => $check_widget ) {
168
-
169
  // Is widget in same sidebar and has identical settings?
170
  if ( in_array( "$id_base-$check_id", $sidebar_widgets ) && (array) $widget == $check_widget ) {
171
  $fail = true;
@@ -179,7 +217,6 @@ class OCDI_Widget_Importer {
179
 
180
  // No failure.
181
  if ( ! $fail ) {
182
-
183
  // Add widget instance.
184
  $single_widget_instances = get_option( 'widget_' . $id_base ); // All instances for that widget ID base, get fresh every time.
185
  $single_widget_instances = ! empty( $single_widget_instances ) ? $single_widget_instances : array( '_multiwidget' => 1 ); // Start fresh if have to.
@@ -262,8 +299,7 @@ class OCDI_Widget_Importer {
262
  * @global array $wp_registered_widget_controls
263
  * @return array $available_widgets, Widget information
264
  */
265
- private function available_widgets() {
266
-
267
  global $wp_registered_widget_controls;
268
 
269
  $widget_controls = $wp_registered_widget_controls;
@@ -285,8 +321,7 @@ class OCDI_Widget_Importer {
285
  *
286
  * @param array $results widget import results.
287
  */
288
- public function format_results_for_log( $results ) {
289
-
290
  if ( empty( $results ) ) {
291
  esc_html_e( 'No results for widget import!', 'pt-ocdi' );
292
  }
8
  * @package ocdi
9
  */
10
 
11
+ namespace OCDI;
12
+
13
+ class WidgetImporter {
14
+ /**
15
+ * Import widgets from WIE or JSON file.
16
+ *
17
+ * @param string $widget_import_file_path path to the widget import file.
18
+ */
19
+ public static function import( $widget_import_file_path ) {
20
+ $results = array();
21
+ $ocdi = OneClickDemoImport::get_instance();
22
+ $log_file_path = $ocdi->get_log_file_path();
23
+
24
+ // Import widgets and return result.
25
+ if ( ! empty( $widget_import_file_path ) ) {
26
+ $results = self::import_widgets( $widget_import_file_path );
27
+ }
28
+
29
+ // Check for errors, else write the results to the log file.
30
+ if ( is_wp_error( $results ) ) {
31
+ $error_message = $results->get_error_message();
32
+
33
+ // Add any error messages to the frontend_error_messages variable in OCDI main class.
34
+ $ocdi->append_to_frontend_error_messages( $error_message );
35
+
36
+ // Write error to log file.
37
+ Helpers::append_to_file(
38
+ $error_message,
39
+ $log_file_path,
40
+ esc_html__( 'Importing widgets', 'pt-ocdi' )
41
+ );
42
+ }
43
+ else {
44
+ ob_start();
45
+ self::format_results_for_log( $results );
46
+ $message = ob_get_clean();
47
+
48
+ // Add this message to log file.
49
+ $log_added = Helpers::append_to_file(
50
+ $message,
51
+ $log_file_path,
52
+ esc_html__( 'Importing widgets' , 'pt-ocdi' )
53
+ );
54
+ }
55
+
56
+ }
57
+
58
 
59
  /**
60
  * Imports widgets from a json file.
61
  *
62
  * @param string $data_file path to json file with WordPress widget export data.
63
  */
64
+ private static function import_widgets( $data_file ) {
 
65
  // Get widgets data from file.
66
+ $data = self::process_import_file( $data_file );
67
 
68
  // Return from this function if there was an error.
69
  if ( is_wp_error( $data ) ) {
71
  }
72
 
73
  // Import the widget data and save the results.
74
+ return self::import_data( $data );
75
  }
76
 
77
  /**
80
  * @param string $file path to json file.
81
  * @return object $data decoded JSON string
82
  */
83
+ private static function process_import_file( $file ) {
 
84
  // File exists?
85
  if ( ! file_exists( $file ) ) {
86
+ return new \WP_Error(
87
  'widget_import_file_not_found',
88
+ __( 'Error: Widget import file could not be found.', 'pt-ocdi' )
89
  );
90
  }
91
 
92
  // Get file contents and decode.
93
+ $data = Helpers::data_from_file( $file );
94
 
95
  // Return from this function if there was an error.
96
  if ( is_wp_error( $data ) ) {
101
  }
102
 
103
 
 
104
  /**
105
  * Import widget JSON data
106
  *
108
  * @param object $data JSON widget data.
109
  * @return array $results
110
  */
111
+ private static function import_data( $data ) {
 
112
  global $wp_registered_sidebars;
113
 
114
  // Have valid data? If no data or could not decode.
115
  if ( empty( $data ) || ! is_object( $data ) ) {
116
+ return new \WP_Error(
117
  'corrupted_widget_import_data',
118
+ __( 'Error: Widget import data could not be read. Please try a different file.', 'pt-ocdi' )
119
  );
120
  }
121
 
124
  $data = apply_filters( 'pt-ocdi/before_widgets_import_data', $data );
125
 
126
  // Get all available widgets site supports.
127
+ $available_widgets = self::available_widgets();
128
 
129
  // Get all existing widget instances.
130
  $widget_instances = array();
138
 
139
  // Loop import data's sidebars.
140
  foreach ( $data as $sidebar_id => $widgets ) {
 
141
  // Skip inactive widgets (should not be in export file).
142
  if ( 'wp_inactive_widgets' == $sidebar_id ) {
143
  continue;
165
 
166
  // Loop widgets.
167
  foreach ( $widgets as $widget_instance_id => $widget ) {
 
168
  $fail = false;
169
 
170
  // Get id_base (remove -# from end) and instance ID number.
197
 
198
  // Does widget with identical settings already exist in same sidebar?
199
  if ( ! $fail && isset( $widget_instances[ $id_base ] ) ) {
 
200
  // Get existing widgets in this sidebar.
201
  $sidebars_widgets = get_option( 'sidebars_widgets' );
202
  $sidebar_widgets = isset( $sidebars_widgets[ $use_sidebar_id ] ) ? $sidebars_widgets[ $use_sidebar_id ] : array(); // Check Inactive if that's where will go.
204
  // Loop widgets with ID base.
205
  $single_widget_instances = ! empty( $widget_instances[ $id_base ] ) ? $widget_instances[ $id_base ] : array();
206
  foreach ( $single_widget_instances as $check_id => $check_widget ) {
 
207
  // Is widget in same sidebar and has identical settings?
208
  if ( in_array( "$id_base-$check_id", $sidebar_widgets ) && (array) $widget == $check_widget ) {
209
  $fail = true;
217
 
218
  // No failure.
219
  if ( ! $fail ) {
 
220
  // Add widget instance.
221
  $single_widget_instances = get_option( 'widget_' . $id_base ); // All instances for that widget ID base, get fresh every time.
222
  $single_widget_instances = ! empty( $single_widget_instances ) ? $single_widget_instances : array( '_multiwidget' => 1 ); // Start fresh if have to.
299
  * @global array $wp_registered_widget_controls
300
  * @return array $available_widgets, Widget information
301
  */
302
+ private static function available_widgets() {
 
303
  global $wp_registered_widget_controls;
304
 
305
  $widget_controls = $wp_registered_widget_controls;
321
  *
322
  * @param array $results widget import results.
323
  */
324
+ private static function format_results_for_log( $results ) {
 
325
  if ( empty( $results ) ) {
326
  esc_html_e( 'No results for widget import!', 'pt-ocdi' );
327
  }
inc/class-ocdi-importer.php DELETED
@@ -1,71 +0,0 @@
1
- <?php
2
- /**
3
- * Class for declaring the importer used in the One Click Demo Import plugin
4
- *
5
- * @package ocdi
6
- */
7
-
8
- class OCDI_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 OCDI_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
- if ( ! class_exists( 'WP_Importer' ) ) {
32
- defined( 'WP_LOAD_IMPORTERS' ) || define( 'WP_LOAD_IMPORTERS', true );
33
- require ABSPATH . '/wp-admin/includes/class-wp-importer.php';
34
- }
35
- require PT_OCDI_PATH . 'inc/class-ocdi-wxr-importer.php';
36
- }
37
-
38
- /**
39
- * Imports content from a WordPress export file.
40
- *
41
- * @param string $data_file path to xml file, file with WordPress export data.
42
- */
43
- public function import( $data_file ) {
44
- $this->importer->import( $data_file );
45
- }
46
-
47
- /**
48
- * Set the logger used in the import
49
- *
50
- * @param object $logger logger instance.
51
- */
52
- public function set_logger( $logger ) {
53
- $this->importer->set_logger( $logger );
54
- }
55
-
56
- /**
57
- * Get all protected variables from the WXR_Importer needed for continuing the import.
58
- */
59
- public function get_importer_data() {
60
- return $this->importer->get_importer_data();
61
- }
62
-
63
- /**
64
- * Sets all protected variables from the WXR_Importer needed for continuing the import.
65
- *
66
- * @param array $data with set variables.
67
- */
68
- public function set_importer_data( $data ) {
69
- $this->importer->set_importer_data( $data );
70
- }
71
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/class-ocdi-main.php DELETED
@@ -1,687 +0,0 @@
1
- <?php
2
- /**
3
- * Main One Click Demo Import plugin class/file.
4
- *
5
- * @package ocdi
6
- */
7
-
8
- // Include files.
9
- require PT_OCDI_PATH . 'inc/class-ocdi-helpers.php';
10
- require PT_OCDI_PATH . 'inc/class-ocdi-importer.php';
11
- require PT_OCDI_PATH . 'inc/class-ocdi-widget-importer.php';
12
- require PT_OCDI_PATH . 'inc/class-ocdi-customizer-importer.php';
13
- require PT_OCDI_PATH . 'inc/class-ocdi-logger.php';
14
-
15
- /**
16
- * One Click Demo Import class, so we don't have to worry about namespaces.
17
- */
18
- class PT_One_Click_Demo_Import {
19
-
20
- /**
21
- * @var $instance the reference to *Singleton* instance of this class
22
- */
23
- private static $instance;
24
-
25
- /**
26
- * Private variables used throughout the plugin.
27
- */
28
- private $importer, $plugin_page, $import_files, $logger, $log_file_path, $selected_index, $selected_import_files, $microtime, $frontend_error_messages, $ajax_call_number;
29
-
30
-
31
- /**
32
- * Returns the *Singleton* instance of this class.
33
- *
34
- * @return PT_One_Click_Demo_Import the *Singleton* instance.
35
- */
36
- public static function getInstance() {
37
- if ( null === static::$instance ) {
38
- static::$instance = new static();
39
- }
40
-
41
- return static::$instance;
42
- }
43
-
44
-
45
- /**
46
- * Class construct function, to initiate the plugin.
47
- * Protected constructor to prevent creating a new instance of the
48
- * *Singleton* via the `new` operator from outside of this class.
49
- */
50
- protected function __construct() {
51
-
52
- // Actions.
53
- add_action( 'admin_menu', array( $this, 'create_plugin_page' ) );
54
- add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
55
- add_action( 'wp_ajax_ocdi_import_demo_data', array( $this, 'import_demo_data_ajax_callback' ) );
56
- add_action( 'after_setup_theme', array( $this, 'setup_plugin_with_filter_data' ) );
57
- add_action( 'plugins_loaded', array( $this, 'load_textdomain' ) );
58
- }
59
-
60
-
61
- /**
62
- * Private clone method to prevent cloning of the instance of the *Singleton* instance.
63
- *
64
- * @return void
65
- */
66
- private function __clone() {}
67
-
68
-
69
- /**
70
- * Private unserialize method to prevent unserializing of the *Singleton* instance.
71
- *
72
- * @return void
73
- */
74
- private function __wakeup() {}
75
-
76
-
77
- /**
78
- * Creates the plugin page and a submenu item in WP Appearance menu.
79
- */
80
- public function create_plugin_page() {
81
- $plugin_page_setup = apply_filters( 'pt-ocdi/plugin_page_setup', array(
82
- 'parent_slug' => 'themes.php',
83
- 'page_title' => esc_html__( 'One Click Demo Import' , 'pt-ocdi' ),
84
- 'menu_title' => esc_html__( 'Import Demo Data' , 'pt-ocdi' ),
85
- 'capability' => 'import',
86
- 'menu_slug' => 'pt-one-click-demo-import',
87
- )
88
- );
89
-
90
- $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' ) );
91
- }
92
-
93
-
94
- /**
95
- * Plugin page display.
96
- */
97
- public function display_plugin_page() {
98
- ?>
99
-
100
- <div class="ocdi wrap about-wrap">
101
-
102
- <h1 class="ocdi__title dashicons-before dashicons-download"><?php esc_html_e( 'One Click Demo Import', 'pt-ocdi' ); ?></h1>
103
-
104
- <?php
105
-
106
- // Display warrning if PHP safe mode is enabled, since we wont be able to change the max_execution_time.
107
- if ( ini_get( 'safe_mode' ) ) {
108
- printf(
109
- esc_html__( '%sWarning: your server is using %sPHP safe mode%s. This means that you might experience server timeout errors.%s', 'pt-ocdi' ),
110
- '<div class="notice notice-warning is-dismissible"><p>',
111
- '<strong>',
112
- '</strong>',
113
- '</p></div>'
114
- );
115
- }
116
-
117
- // Start output buffer for displaying the plugin intro text.
118
- ob_start();
119
- ?>
120
-
121
- <div class="ocdi__intro-notice notice notice-warning is-dismissible">
122
- <p><?php esc_html_e( 'Before you begin, make sure all the required plugins are activated.', 'pt-ocdi' ); ?></p>
123
- </div>
124
-
125
- <div class="ocdi__intro-text">
126
-
127
- <p class="about-description">
128
- <?php esc_html_e( 'Importing demo data (post, pages, images, theme settings, ...) is the easiest way to setup your theme.', 'pt-ocdi' ); ?>
129
- <?php esc_html_e( 'It will allow you to quickly edit everything instead of creating content from scratch.', 'pt-ocdi' ); ?>
130
- </p>
131
-
132
- <hr>
133
-
134
- <p><?php esc_html_e( 'When you import the data, the following things might happen:', 'pt-ocdi' ); ?></p>
135
-
136
- <ul>
137
- <li><?php esc_html_e( 'No existing posts, pages, categories, images, custom post types or any other data will be deleted or modified.', 'pt-ocdi' ); ?></li>
138
- <li><?php esc_html_e( 'Posts, pages, images, widgets and menus will get imported.', 'pt-ocdi' ); ?></li>
139
- <li><?php esc_html_e( 'Please click "Import Demo Data" button only once and wait, it can take a couple of minutes.', 'pt-ocdi' ); ?></li>
140
- </ul>
141
-
142
- <hr>
143
-
144
- </div>
145
-
146
- <?php
147
- $plugin_intro_text = ob_get_clean();
148
-
149
- // Display the plugin intro text (can be replaced with custom text through the filter below).
150
- echo wp_kses_post( apply_filters( 'pt-ocdi/plugin_intro_text', $plugin_intro_text ) );
151
- ?>
152
-
153
-
154
- <?php if ( empty( $this->import_files ) ) : ?>
155
-
156
- <div class="notice notice-info is-dismissible">
157
- <p><?php esc_html_e( 'There are no predefined import files available in this theme. Please upload the import files manually!', 'pt-ocdi' ); ?></p>
158
- </div>
159
-
160
- <div class="ocdi__file-upload-container">
161
-
162
- <h2><?php esc_html_e( 'Manual demo files upload', 'pt-ocdi' ); ?></h2>
163
-
164
- <div class="ocdi__file-upload">
165
- <h3><label for="content-file-upload"><?php esc_html_e( 'Choose a XML file for content import:', 'pt-ocdi' ); ?></label></h3>
166
- <input id="ocdi__content-file-upload" type="file" name="content-file-upload">
167
- </div>
168
-
169
- <div class="ocdi__file-upload">
170
- <h3><label for="widget-file-upload"><?php esc_html_e( 'Choose a WIE or JSON file for widget import:', 'pt-ocdi' ); ?></label> <span><?php esc_html_e( '(*optional)', 'pt-ocdi' ); ?></span></h3>
171
- <input id="ocdi__widget-file-upload" type="file" name="widget-file-upload">
172
- </div>
173
-
174
- <div class="ocdi__file-upload">
175
- <h3><label for="customizer-file-upload"><?php esc_html_e( 'Choose a DAT file for customizer import:', 'pt-ocdi' ); ?></label> <span><?php esc_html_e( '(*optional)', 'pt-ocdi' ); ?></span></h3>
176
- <input id="ocdi__customizer-file-upload" type="file" name="customizer-file-upload">
177
- </div>
178
-
179
- </div>
180
-
181
- <?php elseif ( 1 < count( $this->import_files ) ) : ?>
182
-
183
- <div class="ocdi__multi-select-import">
184
-
185
- <h2><?php esc_html_e( 'Choose which demo you want to import:', 'pt-ocdi' ); ?></h2>
186
-
187
- <select id="ocdi__demo-import-files" class="ocdi__demo-import-files">
188
- <?php foreach ( $this->import_files as $index => $import_file ) : ?>
189
- <option value="<?php echo esc_attr( $index ); ?>">
190
- <?php echo esc_html( $import_file['import_file_name'] ); ?>
191
- </option>
192
- <?php endforeach; ?>
193
- </select>
194
-
195
- <?php
196
- // Check if at least one preview image is defined, so we can prepare the structure for display.
197
- $preview_image_is_defined = false;
198
- foreach ( $this->import_files as $import_file ) {
199
- if ( isset( $import_file['import_preview_image_url'] ) ) {
200
- $preview_image_is_defined = true;
201
- break;
202
- }
203
- }
204
-
205
- if ( $preview_image_is_defined ) :
206
- ?>
207
-
208
- <div class="ocdi__demo-import-preview-container">
209
-
210
- <p><?php esc_html_e( 'Import preview:', 'pt-ocdi' ); ?></p>
211
-
212
- <p class="ocdi__demo-import-preview-image-message js-ocdi-preview-image-message"><?php
213
- if ( ! isset( $this->import_files[0]['import_preview_image_url'] ) ) {
214
- esc_html_e( 'No preview image defined for this import.', 'pt-ocdi' );
215
- }
216
- // Leave the img tag below and the p tag above available for later changes via JS.
217
- ?></p>
218
-
219
- <img id="ocdi__demo-import-preview-image" class="js-ocdi-preview-image" src="<?php echo ! empty( $this->import_files[0]['import_preview_image_url'] ) ? esc_url( $this->import_files[0]['import_preview_image_url'] ) : ''; ?>">
220
-
221
- </div>
222
-
223
- <?php endif; ?>
224
-
225
- </div>
226
-
227
- <?php endif; ?>
228
-
229
- <div class="ocdi__demo-import-notice js-ocdi-demo-import-notice"><?php
230
- if ( is_array( $this->import_files ) && ! empty( $this->import_files[0]['import_notice'] ) ) {
231
- echo wp_kses_post( $this->import_files[0]['import_notice'] );
232
- }
233
- ?></div>
234
-
235
- <p class="ocdi__button-container">
236
- <button class="ocdi__button button button-hero button-primary js-ocdi-import-data"><?php esc_html_e( 'Import Demo Data', 'pt-ocdi' ); ?></button>
237
- </p>
238
-
239
- <p class="ocdi__ajax-loader js-ocdi-ajax-loader">
240
- <span class="spinner"></span> <?php esc_html_e( 'Importing, please wait!', 'pt-ocdi' ); ?>
241
- </p>
242
-
243
- <div class="ocdi__response js-ocdi-ajax-response"></div>
244
-
245
- </div>
246
-
247
- <?php
248
- }
249
-
250
-
251
- /**
252
- * Enqueue admin scripts (JS and CSS)
253
- *
254
- * @param string $hook holds info on which admin page you are currently loading.
255
- */
256
- public function admin_enqueue_scripts( $hook ) {
257
-
258
- // Enqueue the scripts only on the plugin page.
259
- if ( $this->plugin_page === $hook ) {
260
- wp_enqueue_script( 'ocdi-main-js', PT_OCDI_URL . 'assets/js/main.js' , array( 'jquery', 'jquery-form' ), PT_OCDI_VERSION );
261
-
262
- wp_localize_script( 'ocdi-main-js', 'ocdi',
263
- array(
264
- 'ajax_url' => admin_url( 'admin-ajax.php' ),
265
- 'ajax_nonce' => wp_create_nonce( 'ocdi-ajax-verification' ),
266
- 'import_files' => $this->import_files,
267
- 'texts' => array(
268
- 'missing_preview_image' => esc_html__( 'No preview image defined for this import.', 'pt-ocdi' ),
269
- ),
270
- )
271
- );
272
-
273
- wp_enqueue_style( 'ocdi-main-css', PT_OCDI_URL . 'assets/css/main.css', array() , PT_OCDI_VERSION );
274
- }
275
- }
276
-
277
-
278
- /**
279
- * Main AJAX callback function for:
280
- * 1. prepare import files (uploaded or predefined via filters)
281
- * 2. import content
282
- * 3. before widgets import setup (optional)
283
- * 4. import widgets (optional)
284
- * 5. import customizer options (optional)
285
- * 6. after import setup (optional)
286
- */
287
- public function import_demo_data_ajax_callback() {
288
-
289
- // Try to update PHP memory limit (so that it does not run out of it).
290
- ini_set( 'memory_limit', apply_filters( 'pt-ocdi/import_memory_limit', '350M' ) );
291
-
292
- // Verify if the AJAX call is valid (checks nonce and current_user_can).
293
- OCDI_Helpers::verify_ajax_call();
294
-
295
- // Is this a new AJAX call to continue the previous import?
296
- $use_existing_importer_data = $this->get_importer_data();
297
-
298
- if ( ! $use_existing_importer_data ) {
299
-
300
- // Set the AJAX call number.
301
- $this->ajax_call_number = empty( $this->ajax_call_number ) ? 0 : $this->ajax_call_number;
302
-
303
- // Error messages displayed on front page.
304
- $this->frontend_error_messages = '';
305
-
306
- // Create a date and time string to use for demo and log file names.
307
- $demo_import_start_time = date( apply_filters( 'pt-ocdi/date_format_for_file_names', 'Y-m-d__H-i-s' ) );
308
-
309
- // Define log file path.
310
- $this->log_file_path = OCDI_Helpers::get_log_path( $demo_import_start_time );
311
-
312
- // Get selected file index or set it to 0.
313
- $this->selected_index = empty( $_POST['selected'] ) ? 0 : absint( $_POST['selected'] );
314
-
315
- /**
316
- * 1. Prepare import files.
317
- * Manually uploaded import files or predefined import files via filter: pt-ocdi/import_files
318
- */
319
- if ( ! empty( $_FILES ) ) { // Using manual file uploads?
320
-
321
- // Get paths for the uploaded files.
322
- $this->selected_import_files = OCDI_Helpers::process_uploaded_files( $_FILES, $this->log_file_path );
323
-
324
- // Set the name of the import files, because we used the uploaded files.
325
- $this->import_files[ $this->selected_index ]['import_file_name'] = esc_html__( 'Manually uploaded files', 'pt-ocdi' );
326
- }
327
- elseif ( ! empty( $this->import_files[ $this->selected_index ] ) ) { // Use predefined import files from wp filter: pt-ocdi/import_files.
328
-
329
- // Download the import files (content and widgets files) and save it to variable for later use.
330
- $this->selected_import_files = OCDI_Helpers::download_import_files(
331
- $this->import_files[ $this->selected_index ],
332
- $demo_import_start_time
333
- );
334
-
335
- // Check Errors.
336
- if ( is_wp_error( $this->selected_import_files ) ) {
337
-
338
- // Write error to log file and send an AJAX response with the error.
339
- OCDI_Helpers::log_error_and_send_ajax_response(
340
- $this->selected_import_files->get_error_message(),
341
- $this->log_file_path,
342
- esc_html__( 'Downloaded files', 'pt-ocdi' )
343
- );
344
- }
345
-
346
- // Add this message to log file.
347
- $log_added = OCDI_Helpers::append_to_file(
348
- sprintf(
349
- __( 'The import files for: %s were successfully downloaded!', 'pt-ocdi' ),
350
- $this->import_files[ $this->selected_index ]['import_file_name']
351
- ) . OCDI_Helpers::import_file_info( $this->selected_import_files ),
352
- $this->log_file_path,
353
- esc_html__( 'Downloaded files' , 'pt-ocdi' )
354
- );
355
- }
356
- else {
357
-
358
- // Send JSON Error response to the AJAX call.
359
- wp_send_json( esc_html__( 'No import files specified!', 'pt-ocdi' ) );
360
- }
361
- }
362
-
363
- /**
364
- * 2. Import content.
365
- * Returns any errors greater then the "error" logger level, that will be displayed on front page.
366
- */
367
- $this->frontend_error_messages .= $this->import_content( $this->selected_import_files['content'] );
368
-
369
- /**
370
- * 3. Before widgets import setup.
371
- */
372
- $action = 'pt-ocdi/before_widgets_import';
373
- if ( ( false !== has_action( $action ) ) && empty( $this->frontend_error_messages ) ) {
374
-
375
- // Run the before_widgets_import action to setup other settings.
376
- $this->do_import_action( $action, $this->import_files[ $this->selected_index ] );
377
- }
378
-
379
- /**
380
- * 4. Import widgets.
381
- */
382
- if ( ! empty( $this->selected_import_files['widgets'] ) && empty( $this->frontend_error_messages ) ) {
383
- $this->import_widgets( $this->selected_import_files['widgets'] );
384
- }
385
-
386
- /**
387
- * 5. Import customize options.
388
- */
389
- if ( ! empty( $this->selected_import_files['customizer'] ) && empty( $this->frontend_error_messages ) ) {
390
- $this->import_customizer( $this->selected_import_files['customizer'] );
391
- }
392
-
393
- /**
394
- * 6. After import setup.
395
- */
396
- $action = 'pt-ocdi/after_import';
397
- if ( ( false !== has_action( $action ) ) && empty( $this->frontend_error_messages ) ) {
398
-
399
- // Run the after_import action to setup other settings.
400
- $this->do_import_action( $action, $this->import_files[ $this->selected_index ] );
401
- }
402
-
403
- // Display final messages (success or error messages).
404
- if ( empty( $this->frontend_error_messages ) ) {
405
- $response['message'] = sprintf(
406
- __( '%1$s%3$sThat\'s it, all done!%4$s%2$sThe demo import has finished. Please check your page and make sure that everything has imported correctly. If it did, you can deactivate the %3$sOne Click Demo Import%4$s plugin, because it has done its job.%5$s', 'pt-ocdi' ),
407
- '<div class="notice notice-success"><p>',
408
- '<br>',
409
- '<strong>',
410
- '</strong>',
411
- '</p></div>'
412
- );
413
- }
414
- else {
415
- $response['message'] = $this->frontend_error_messages . '<br>';
416
- $response['message'] .= sprintf(
417
- __( '%1$sThe demo import has finished, but there were some import errors.%2$sMore details about the errors can be found in this %3$s%5$slog file%6$s%4$s%7$s', 'pt-ocdi' ),
418
- '<div class="notice notice-error"><p>',
419
- '<br>',
420
- '<strong>',
421
- '</strong>',
422
- '<a href="' . OCDI_Helpers::get_log_url( $this->log_file_path ) .'" target="_blank">',
423
- '</a>',
424
- '</p></div>'
425
- );
426
- }
427
-
428
- wp_send_json( $response );
429
- }
430
-
431
-
432
- /**
433
- * Import content from an WP XML file.
434
- *
435
- * @param string $import_file_path path to the import file.
436
- */
437
- private function import_content( $import_file_path ) {
438
-
439
- $this->microtime = microtime( true );
440
-
441
- // This should be replaced with multiple AJAX calls (import in smaller chunks)
442
- // so that it would not come to the Internal Error, because of the PHP script timeout.
443
- // Also this function has no effect when PHP is running in safe mode
444
- // http://php.net/manual/en/function.set-time-limit.php.
445
- // Increase PHP max execution time.
446
- set_time_limit( apply_filters( 'pt-ocdi/set_time_limit_for_demo_data_import', 300 ) );
447
-
448
- // Disable import of authors.
449
- add_filter( 'wxr_importer.pre_process.user', '__return_false' );
450
-
451
- // Check, if we need to send another AJAX request and set the importing author to the current user.
452
- add_filter( 'wxr_importer.pre_process.post', array( $this, 'new_ajax_request_maybe' ) );
453
-
454
- // Disables generation of multiple image sizes (thumbnails) in the content import step.
455
- if ( ! apply_filters( 'pt-ocdi/regenerate_thumbnails_in_content_import', true ) ) {
456
- add_filter( 'intermediate_image_sizes_advanced',
457
- function() {
458
- return null;
459
- }
460
- );
461
- }
462
-
463
- // Import content.
464
- if ( ! empty( $import_file_path ) ) {
465
- ob_start();
466
- $this->importer->import( $import_file_path );
467
- $message = ob_get_clean();
468
-
469
- // Add this message to log file.
470
- $log_added = OCDI_Helpers::append_to_file(
471
- $message . PHP_EOL . esc_html__( 'Max execution time after content import = ' , 'pt-ocdi' ) . ini_get( 'max_execution_time' ),
472
- $this->log_file_path,
473
- esc_html__( 'Importing content' , 'pt-ocdi' )
474
- );
475
- }
476
-
477
- // Delete content importer data for current import from DB.
478
- delete_transient( 'ocdi_importer_data' );
479
-
480
- // Return any error messages for the front page output (errors, critical, alert and emergency level messages only).
481
- return $this->logger->error_output;
482
- }
483
-
484
-
485
- /**
486
- * Import widgets from WIE or JSON file.
487
- *
488
- * @param string $widget_import_file_path path to the widget import file.
489
- */
490
- private function import_widgets( $widget_import_file_path ) {
491
-
492
- // Widget import results.
493
- $results = array();
494
-
495
- // Create an instance of the Widget Importer.
496
- $widget_importer = new OCDI_Widget_Importer();
497
-
498
- // Import widgets.
499
- if ( ! empty( $widget_import_file_path ) ) {
500
-
501
- // Import widgets and return result.
502
- $results = $widget_importer->import_widgets( $widget_import_file_path );
503
- }
504
-
505
- // Check for errors.
506
- if ( is_wp_error( $results ) ) {
507
-
508
- // Write error to log file and send an AJAX response with the error.
509
- OCDI_Helpers::log_error_and_send_ajax_response(
510
- $results->get_error_message(),
511
- $this->log_file_path,
512
- esc_html__( 'Importing widgets', 'pt-ocdi' )
513
- );
514
- }
515
-
516
- ob_start();
517
- $widget_importer->format_results_for_log( $results );
518
- $message = ob_get_clean();
519
-
520
- // Add this message to log file.
521
- $log_added = OCDI_Helpers::append_to_file(
522
- $message,
523
- $this->log_file_path,
524
- esc_html__( 'Importing widgets' , 'pt-ocdi' )
525
- );
526
- }
527
-
528
-
529
- /**
530
- * Import customizer from a DAT file, generated by the Customizer Export/Import plugin.
531
- *
532
- * @param string $customizer_import_file_path path to the customizer import file.
533
- */
534
- private function import_customizer( $customizer_import_file_path ) {
535
-
536
- // Try to import the customizer settings.
537
- $results = OCDI_Customizer_Importer::import_customizer_options( $customizer_import_file_path );
538
-
539
- // Check for errors.
540
- if ( is_wp_error( $results ) ) {
541
-
542
- // Write error to log file and send an AJAX response with the error.
543
- OCDI_Helpers::log_error_and_send_ajax_response(
544
- $results->get_error_message(),
545
- $this->log_file_path,
546
- esc_html__( 'Importing customizer settings', 'pt-ocdi' )
547
- );
548
- }
549
-
550
- // Add this message to log file.
551
- $log_added = OCDI_Helpers::append_to_file(
552
- esc_html__( 'Customizer settings import finished!', 'pt-ocdi' ),
553
- $this->log_file_path,
554
- esc_html__( 'Importing customizer settings' , 'pt-ocdi' )
555
- );
556
- }
557
-
558
-
559
- /**
560
- * Setup other things in the passed wp action.
561
- *
562
- * @param string $action the action name to be executed.
563
- * @param array $selected_import with information about the selected import.
564
- */
565
- private function do_import_action( $action, $selected_import ) {
566
-
567
- ob_start();
568
- do_action( $action, $selected_import );
569
- $message = ob_get_clean();
570
-
571
- // Add this message to log file.
572
- $log_added = OCDI_Helpers::append_to_file(
573
- $message,
574
- $this->log_file_path,
575
- $action
576
- );
577
- }
578
-
579
-
580
- /**
581
- * Check if we need to create a new AJAX request, so that server does not timeout.
582
- *
583
- * @param array $data current post data.
584
- * @return array
585
- */
586
- public function new_ajax_request_maybe( $data ) {
587
- $time = microtime( true ) - $this->microtime;
588
-
589
- // We should make a new ajax call, if the time is right.
590
- if ( $time > apply_filters( 'pt-ocdi/time_for_one_ajax_call', 25 ) ) {
591
- $this->ajax_call_number++;
592
- $this->set_importer_data();
593
-
594
- $response = array(
595
- 'status' => 'newAJAX',
596
- 'message' => 'Time for new AJAX request!: ' . $time,
597
- );
598
-
599
- // Add any output to the log file and clear the buffers.
600
- $message = ob_get_clean();
601
-
602
- // Add message to log file.
603
- $log_added = OCDI_Helpers::append_to_file(
604
- __( 'Completed AJAX call number: ' , 'pt-ocdi' ) . $this->ajax_call_number . PHP_EOL . $message,
605
- $this->log_file_path,
606
- ''
607
- );
608
-
609
- wp_send_json( $response );
610
- }
611
-
612
- // Set importing author to the current user.
613
- // Fixes the [WARNING] Could not find the author for ... log warning messages.
614
- $current_user_obj = wp_get_current_user();
615
- $data['post_author'] = $current_user_obj->user_login;
616
-
617
- return $data;
618
- }
619
-
620
- /**
621
- * Set current state of the content importer, so we can continue the import with new AJAX request.
622
- */
623
- private function set_importer_data() {
624
- $data = array(
625
- 'frontend_error_messages' => $this->frontend_error_messages,
626
- 'ajax_call_number' => $this->ajax_call_number,
627
- 'log_file_path' => $this->log_file_path,
628
- 'selected_index' => $this->selected_index,
629
- 'selected_import_files' => $this->selected_import_files,
630
- );
631
-
632
- $data = array_merge( $data, $this->importer->get_importer_data() );
633
-
634
- set_transient( 'ocdi_importer_data', $data, 0.5 * HOUR_IN_SECONDS );
635
- }
636
-
637
- /**
638
- * Get content importer data, so we can continue the import with this new AJAX request.
639
- */
640
- private function get_importer_data() {
641
- if ( $data = get_transient( 'ocdi_importer_data' ) ) {
642
- $this->frontend_error_messages = empty( $data['frontend_error_messages'] ) ? '' : $data['frontend_error_messages'];
643
- $this->ajax_call_number = empty( $data['ajax_call_number'] ) ? 1 : $data['ajax_call_number'];
644
- $this->log_file_path = empty( $data['log_file_path'] ) ? '' : $data['log_file_path'];
645
- $this->selected_index = empty( $data['selected_index'] ) ? 0 : $data['selected_index'];
646
- $this->selected_import_files = empty( $data['selected_import_files'] ) ? array() : $data['selected_import_files'];
647
- $this->importer->set_importer_data( $data );
648
-
649
- return true;
650
- }
651
- return false;
652
- }
653
-
654
- /**
655
- * Load the plugin textdomain, so that translations can be made.
656
- */
657
- public function load_textdomain() {
658
- load_plugin_textdomain( 'pt-ocdi', false, plugin_basename( dirname( __FILE__ ) ) . '/languages' );
659
- }
660
-
661
-
662
- /**
663
- * Get data from filters, after the theme has loaded and instantiate the importer.
664
- */
665
- public function setup_plugin_with_filter_data() {
666
-
667
- // Get info of import data files and filter it.
668
- $this->import_files = OCDI_Helpers::validate_import_file_info( apply_filters( 'pt-ocdi/import_files', array() ) );
669
-
670
- // Importer options array.
671
- $importer_options = apply_filters( 'pt-ocdi/importer_options', array(
672
- 'fetch_attachments' => true,
673
- ) );
674
-
675
- // Logger options for the logger used in the importer.
676
- $logger_options = apply_filters( 'pt-ocdi/logger_options', array(
677
- 'logger_min_level' => 'warning',
678
- ) );
679
-
680
- // Configure logger instance and set it to the importer.
681
- $this->logger = new OCDI_Logger();
682
- $this->logger->min_level = $logger_options['logger_min_level'];
683
-
684
- // Create importer instance with proper parameters.
685
- $this->importer = new OCDI_Importer( $importer_options, $this->logger );
686
- }
687
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
languages/pt-ocdi.pot CHANGED
@@ -2,7 +2,7 @@
2
  # This file is distributed under the GPL 2.0.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: One Click Demo Import 1.4.0\n"
6
  "Report-Msgid-Bugs-To: http://support.proteusthemes.com/\n"
7
  "POT-Creation-Date: 2016-05-14 09:53:17+00:00\n"
8
  "MIME-Version: 1.0\n"
@@ -24,49 +24,57 @@ msgstr ""
24
  "X-Poedit-Bookmarks: \n"
25
  "X-Textdomain-Support: yes\n"
26
 
27
- #: inc/class-ocdi-customizer-importer.php:36
28
- msgid "The customizer import file is missing! File path: %s"
29
  msgstr ""
30
 
31
- #: inc/class-ocdi-customizer-importer.php:56
32
- msgid ""
33
- "The customizer import file is not in a correct format. Please make sure to "
34
- "use the correct customizer import file."
35
  msgstr ""
36
 
37
- #: inc/class-ocdi-customizer-importer.php:62
 
 
 
 
38
  msgid ""
39
- "The customizer import file is not suitable for current theme. You can only "
40
- "import customizer settings for the same theme or a child theme."
41
  msgstr ""
42
 
43
- #: inc/class-ocdi-helpers.php:70
44
- msgid "\"import_file_url\" or \"local_import_file\" for %s%s%s are not defined!"
 
 
45
  msgstr ""
46
 
47
- #: inc/class-ocdi-helpers.php:176
48
- msgid "URL for %s%s%s file is not defined!"
49
  msgstr ""
50
 
51
- #: inc/class-ocdi-helpers.php:198
52
  msgid ""
53
- "An error occurred while fetching %s%s%s file from the server!%sReason: %s - "
54
- "%s."
55
  msgstr ""
56
 
57
- #: inc/class-ocdi-helpers.php:238 inc/class-ocdi-helpers.php:282
 
 
 
 
58
  msgid ""
59
  "An error occurred while writing file to your server! Tried to write a file "
60
  "to: %s%s."
61
  msgstr ""
62
 
63
- #: inc/class-ocdi-helpers.php:317
64
  msgid ""
65
  "An error occurred while reading a file from your server! Tried reading file "
66
  "from path: %s%s."
67
  msgstr ""
68
 
69
- #: inc/class-ocdi-helpers.php:341
70
  msgid ""
71
  "This WordPress page does not have %sdirect%s write file access. This plugin "
72
  "needs it in order to save the demo import xml file to the upload directory "
@@ -77,170 +85,117 @@ msgstr ""
77
  msgid "One Click Demo Import"
78
  msgstr ""
79
 
80
- #: inc/class-ocdi-helpers.php:353 inc/class-ocdi-main.php:84
81
- #: inc/class-ocdi-main.php:236
82
  msgid "Import Demo Data"
83
  msgstr ""
84
 
85
- #: inc/class-ocdi-helpers.php:365
86
  msgid ""
87
  "An error occurred while retrieving reading/writing permissions to your "
88
  "server (could not retrieve WP filesystem credentials)!"
89
  msgstr ""
90
 
91
- #: inc/class-ocdi-helpers.php:373
92
  msgid "Your WordPress login credentials don't allow to use WP_Filesystem!"
93
  msgstr ""
94
 
95
- #: inc/class-ocdi-helpers.php:438
96
  msgid "One Click Demo Import - "
97
  msgstr ""
98
 
99
- #: inc/class-ocdi-helpers.php:474
100
  msgid ""
101
  "%sYour user role isn't high enough. You don't have permission to import "
102
  "demo data.%s"
103
  msgstr ""
104
 
105
- #: inc/class-ocdi-helpers.php:510
106
  msgid ""
107
  "Please upload XML file for content import. If you want to import widgets or "
108
  "customizer settings only, please use Widget Importer & Exporter or the "
109
  "Customizer Export/Import plugin."
110
  msgstr ""
111
 
112
- #: inc/class-ocdi-helpers.php:512 inc/class-ocdi-helpers.php:534
113
- #: inc/class-ocdi-helpers.php:553 inc/class-ocdi-helpers.php:561
114
  msgid "Upload files"
115
  msgstr ""
116
 
117
- #: inc/class-ocdi-helpers.php:530
118
  msgid "Widget file was not uploaded. Error: %s"
119
  msgstr ""
120
 
121
- #: inc/class-ocdi-helpers.php:549
122
  msgid "Customizer file was not uploaded. Error: %s"
123
  msgstr ""
124
 
125
- #: inc/class-ocdi-helpers.php:559
126
- msgid "The import files were successfully uploaded!"
127
- msgstr ""
128
-
129
- #: inc/class-ocdi-helpers.php:577
130
- msgid "Initial max execution time = %s"
131
  msgstr ""
132
 
133
- #: inc/class-ocdi-helpers.php:581
134
- msgid ""
135
- "Files info:%1$sSite URL = %2$s%1$sData file = %3$s%1$sWidget file = "
136
- "%4$s%1$sCustomizer file = %5$s"
137
- msgstr ""
138
-
139
- #: inc/class-ocdi-helpers.php:585 inc/class-ocdi-helpers.php:586
140
- msgid "not defined!"
141
- msgstr ""
142
-
143
- #: inc/class-ocdi-main.php:109
144
- msgid ""
145
- "%sWarning: your server is using %sPHP safe mode%s. This means that you "
146
- "might experience server timeout errors.%s"
147
- msgstr ""
148
-
149
- #: inc/class-ocdi-main.php:122
150
- msgid "Before you begin, make sure all the required plugins are activated."
151
- msgstr ""
152
-
153
- #: inc/class-ocdi-main.php:128
154
- msgid ""
155
- "Importing demo data (post, pages, images, theme settings, ...) is the "
156
- "easiest way to setup your theme."
157
  msgstr ""
158
 
159
- #: inc/class-ocdi-main.php:129
160
- msgid ""
161
- "It will allow you to quickly edit everything instead of creating content "
162
- "from scratch."
163
- msgstr ""
164
-
165
- #: inc/class-ocdi-main.php:134
166
- msgid "When you import the data, the following things might happen:"
167
- msgstr ""
168
-
169
- #: inc/class-ocdi-main.php:137
170
- msgid ""
171
- "No existing posts, pages, categories, images, custom post types or any "
172
- "other data will be deleted or modified."
173
- msgstr ""
174
-
175
- #: inc/class-ocdi-main.php:138
176
- msgid "Posts, pages, images, widgets and menus will get imported."
177
  msgstr ""
178
 
179
- #: inc/class-ocdi-main.php:139
180
- msgid ""
181
- "Please click \"Import Demo Data\" button only once and wait, it can take a "
182
- "couple of minutes."
183
  msgstr ""
184
 
185
- #: inc/class-ocdi-main.php:157
186
  msgid ""
187
- "There are no predefined import files available in this theme. Please upload "
188
- "the import files manually!"
189
- msgstr ""
190
-
191
- #: inc/class-ocdi-main.php:162
192
- msgid "Manual demo files upload"
193
- msgstr ""
194
-
195
- #: inc/class-ocdi-main.php:165
196
- msgid "Choose a XML file for content import:"
197
  msgstr ""
198
 
199
- #: inc/class-ocdi-main.php:170
200
- msgid "Choose a WIE or JSON file for widget import:"
201
  msgstr ""
202
 
203
- #: inc/class-ocdi-main.php:170 inc/class-ocdi-main.php:175
204
- msgid "(*optional)"
205
  msgstr ""
206
 
207
- #: inc/class-ocdi-main.php:175
208
- msgid "Choose a DAT file for customizer import:"
209
  msgstr ""
210
 
211
- #: inc/class-ocdi-main.php:185
212
- msgid "Choose which demo you want to import:"
213
  msgstr ""
214
 
215
- #: inc/class-ocdi-main.php:210
216
- msgid "Import preview:"
217
  msgstr ""
218
 
219
- #: inc/class-ocdi-main.php:214 inc/class-ocdi-main.php:268
220
- msgid "No preview image defined for this import."
221
  msgstr ""
222
 
223
- #: inc/class-ocdi-main.php:240
224
- msgid "Importing, please wait!"
225
  msgstr ""
226
 
227
- #: inc/class-ocdi-main.php:325
228
  msgid "Manually uploaded files"
229
  msgstr ""
230
 
231
- #: inc/class-ocdi-main.php:342 inc/class-ocdi-main.php:353
232
  msgid "Downloaded files"
233
  msgstr ""
234
 
235
- #: inc/class-ocdi-main.php:349
236
  msgid "The import files for: %s were successfully downloaded!"
237
  msgstr ""
238
 
239
- #: inc/class-ocdi-main.php:359
240
  msgid "No import files specified!"
241
  msgstr ""
242
 
243
- #: inc/class-ocdi-main.php:406
244
  msgid ""
245
  "%1$s%3$sThat's it, all done!%4$s%2$sThe demo import has finished. Please "
246
  "check your page and make sure that everything has imported correctly. If it "
@@ -248,74 +203,72 @@ msgid ""
248
  "it has done its job.%5$s"
249
  msgstr ""
250
 
251
- #: inc/class-ocdi-main.php:417
252
  msgid ""
253
  "%1$sThe demo import has finished, but there were some import "
254
  "errors.%2$sMore details about the errors can be found in this %3$s%5$slog "
255
  "file%6$s%4$s%7$s"
256
  msgstr ""
257
 
258
- #: inc/class-ocdi-main.php:471
259
- msgid "Max execution time after content import = "
260
  msgstr ""
261
 
262
- #: inc/class-ocdi-main.php:473
263
- msgid "Importing content"
264
  msgstr ""
265
 
266
- #: inc/class-ocdi-main.php:512 inc/class-ocdi-main.php:524
267
- msgid "Importing widgets"
268
  msgstr ""
269
 
270
- #: inc/class-ocdi-main.php:546 inc/class-ocdi-main.php:554
271
- msgid "Importing customizer settings"
272
- msgstr ""
273
-
274
- #: inc/class-ocdi-main.php:552
275
- msgid "Customizer settings import finished!"
276
  msgstr ""
277
 
278
- #: inc/class-ocdi-main.php:604
279
- msgid "Completed AJAX call number: "
280
  msgstr ""
281
 
282
- #: inc/class-ocdi-widget-importer.php:44
283
- msgid "Widget import file could not be found."
284
  msgstr ""
285
 
286
- #: inc/class-ocdi-widget-importer.php:76
287
- msgid "Widget import data could not be read. Please try a different file."
288
  msgstr ""
289
 
290
- #: inc/class-ocdi-widget-importer.php:116
291
  msgid "Sidebar does not exist in theme (moving widget to Inactive)"
292
  msgstr ""
293
 
294
- #: inc/class-ocdi-widget-importer.php:138
295
  msgid "Site does not support widget"
296
  msgstr ""
297
 
298
- #: inc/class-ocdi-widget-importer.php:173
299
  msgid "Widget already exists"
300
  msgstr ""
301
 
302
- #: inc/class-ocdi-widget-importer.php:232
303
  msgid "Imported"
304
  msgstr ""
305
 
306
- #: inc/class-ocdi-widget-importer.php:236
307
  msgid "Imported to Inactive"
308
  msgstr ""
309
 
310
- #: inc/class-ocdi-widget-importer.php:242
311
  msgid "No Title"
312
  msgstr ""
313
 
314
- #: inc/class-ocdi-widget-importer.php:291
315
  msgid "No results for widget import!"
316
  msgstr ""
317
 
318
- #: one-click-demo-import.php:29
319
  msgid ""
320
  "The %2$sOne Click Demo Import%3$s plugin requires %2$sPHP 5.3.2+%3$s to run "
321
  "properly. Please contact your hosting company and ask them to update the "
2
  # This file is distributed under the GPL 2.0.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: One Click Demo Import 2.0.0\n"
6
  "Report-Msgid-Bugs-To: http://support.proteusthemes.com/\n"
7
  "POT-Creation-Date: 2016-05-14 09:53:17+00:00\n"
8
  "MIME-Version: 1.0\n"
24
  "X-Poedit-Bookmarks: \n"
25
  "X-Textdomain-Support: yes\n"
26
 
27
+ #: inc/CustomizerImporter.php:37 inc/CustomizerImporter.php:45
28
+ msgid "Importing customizer settings"
29
  msgstr ""
30
 
31
+ #: inc/CustomizerImporter.php:43
32
+ msgid "Customizer settings import finished!"
 
 
33
  msgstr ""
34
 
35
+ #: inc/CustomizerImporter.php:73
36
+ msgid "Error: The customizer import file is missing! File path: %s"
37
+ msgstr ""
38
+
39
+ #: inc/CustomizerImporter.php:93
40
  msgid ""
41
+ "Error: The customizer import file is not in a correct format. Please make "
42
+ "sure to use the correct customizer import file."
43
  msgstr ""
44
 
45
+ #: inc/CustomizerImporter.php:99
46
+ msgid ""
47
+ "Error: The customizer import file is not suitable for current theme. You "
48
+ "can only import customizer settings for the same theme or a child theme."
49
  msgstr ""
50
 
51
+ #: inc/Downloader.php:58
52
+ msgid "Missing URL for downloading a file!"
53
  msgstr ""
54
 
55
+ #: inc/Downloader.php:76
56
  msgid ""
57
+ "An error occurred while fetching file from: %1$s%2$s%3$s!%4$sReason: %5$s - "
58
+ "%6$s."
59
  msgstr ""
60
 
61
+ #: inc/Helpers.php:75
62
+ msgid "\"import_file_url\" or \"local_import_file\" for %s%s%s are not defined!"
63
+ msgstr ""
64
+
65
+ #: inc/Helpers.php:203 inc/Helpers.php:246
66
  msgid ""
67
  "An error occurred while writing file to your server! Tried to write a file "
68
  "to: %s%s."
69
  msgstr ""
70
 
71
+ #: inc/Helpers.php:280
72
  msgid ""
73
  "An error occurred while reading a file from your server! Tried reading file "
74
  "from path: %s%s."
75
  msgstr ""
76
 
77
+ #: inc/Helpers.php:303
78
  msgid ""
79
  "This WordPress page does not have %sdirect%s write file access. This plugin "
80
  "needs it in order to save the demo import xml file to the upload directory "
85
  msgid "One Click Demo Import"
86
  msgstr ""
87
 
88
+ #: inc/Helpers.php:315 inc/OneClickDemoImport.php:132
 
89
  msgid "Import Demo Data"
90
  msgstr ""
91
 
92
+ #: inc/Helpers.php:327
93
  msgid ""
94
  "An error occurred while retrieving reading/writing permissions to your "
95
  "server (could not retrieve WP filesystem credentials)!"
96
  msgstr ""
97
 
98
+ #: inc/Helpers.php:335
99
  msgid "Your WordPress login credentials don't allow to use WP_Filesystem!"
100
  msgstr ""
101
 
102
+ #: inc/Helpers.php:375
103
  msgid "One Click Demo Import - "
104
  msgstr ""
105
 
106
+ #: inc/Helpers.php:409
107
  msgid ""
108
  "%sYour user role isn't high enough. You don't have permission to import "
109
  "demo data.%s"
110
  msgstr ""
111
 
112
+ #: inc/Helpers.php:444
113
  msgid ""
114
  "Please upload XML file for content import. If you want to import widgets or "
115
  "customizer settings only, please use Widget Importer & Exporter or the "
116
  "Customizer Export/Import plugin."
117
  msgstr ""
118
 
119
+ #: inc/Helpers.php:446 inc/Helpers.php:466 inc/Helpers.php:483
120
+ #: inc/Helpers.php:494 inc/Helpers.php:514 inc/Helpers.php:522
121
  msgid "Upload files"
122
  msgstr ""
123
 
124
+ #: inc/Helpers.php:462
125
  msgid "Widget file was not uploaded. Error: %s"
126
  msgstr ""
127
 
128
+ #: inc/Helpers.php:479
129
  msgid "Customizer file was not uploaded. Error: %s"
130
  msgstr ""
131
 
132
+ #: inc/Helpers.php:492
133
+ msgid "Missing Redux option name! Please also enter the Redux option name!"
 
 
 
 
134
  msgstr ""
135
 
136
+ #: inc/Helpers.php:510
137
+ msgid "Redux file was not uploaded. Error: %s"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
  msgstr ""
139
 
140
+ #: inc/Helpers.php:520
141
+ msgid "The import files were successfully uploaded!"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  msgstr ""
143
 
144
+ #: inc/Helpers.php:542
145
+ msgid "Initial max execution time = %s"
 
 
146
  msgstr ""
147
 
148
+ #: inc/Helpers.php:546
149
  msgid ""
150
+ "Files info:%1$sSite URL = %2$s%1$sData file = %3$s%1$sWidget file = "
151
+ "%4$s%1$sCustomizer file = %5$s%1$sRedux files:%1$s%6$s"
 
 
 
 
 
 
 
 
152
  msgstr ""
153
 
154
+ #: inc/Helpers.php:550 inc/Helpers.php:551 inc/Helpers.php:552
155
+ msgid "not defined!"
156
  msgstr ""
157
 
158
+ #: inc/Importer.php:173
159
+ msgid "New AJAX call!"
160
  msgstr ""
161
 
162
+ #: inc/OneClickDemoImport.php:182
163
+ msgid "No preview image defined for this import."
164
  msgstr ""
165
 
166
+ #: inc/OneClickDemoImport.php:183
167
+ msgid "Are you sure?"
168
  msgstr ""
169
 
170
+ #: inc/OneClickDemoImport.php:184
171
+ msgid "Cancel"
172
  msgstr ""
173
 
174
+ #: inc/OneClickDemoImport.php:185
175
+ msgid "Yes, import!"
176
  msgstr ""
177
 
178
+ #: inc/OneClickDemoImport.php:186
179
+ msgid "Selected demo import:"
180
  msgstr ""
181
 
182
+ #: inc/OneClickDemoImport.php:232
183
  msgid "Manually uploaded files"
184
  msgstr ""
185
 
186
+ #: inc/OneClickDemoImport.php:245 inc/OneClickDemoImport.php:256
187
  msgid "Downloaded files"
188
  msgstr ""
189
 
190
+ #: inc/OneClickDemoImport.php:252
191
  msgid "The import files for: %s were successfully downloaded!"
192
  msgstr ""
193
 
194
+ #: inc/OneClickDemoImport.php:261
195
  msgid "No import files specified!"
196
  msgstr ""
197
 
198
+ #: inc/OneClickDemoImport.php:378
199
  msgid ""
200
  "%1$s%3$sThat's it, all done!%4$s%2$sThe demo import has finished. Please "
201
  "check your page and make sure that everything has imported correctly. If it "
203
  "it has done its job.%5$s"
204
  msgstr ""
205
 
206
+ #: inc/OneClickDemoImport.php:389
207
  msgid ""
208
  "%1$sThe demo import has finished, but there were some import "
209
  "errors.%2$sMore details about the errors can be found in this %3$s%5$slog "
210
  "file%6$s%4$s%7$s"
211
  msgstr ""
212
 
213
+ #: inc/ReduxImporter.php:23
214
+ msgid "The Redux plugin is not activated, so the Redux import was skipped!"
215
  msgstr ""
216
 
217
+ #: inc/ReduxImporter.php:32 inc/ReduxImporter.php:53 inc/ReduxImporter.php:66
218
+ msgid "Importing Redux settings"
219
  msgstr ""
220
 
221
+ #: inc/ReduxImporter.php:51
222
+ msgid "Redux settings import for: %s finished successfully!"
223
  msgstr ""
224
 
225
+ #: inc/ReduxImporter.php:57
226
+ msgid ""
227
+ "The Redux option name: %s, was not found in this WP site, so it was not "
228
+ "imported!"
 
 
229
  msgstr ""
230
 
231
+ #: inc/WidgetImporter.php:40 inc/WidgetImporter.php:52
232
+ msgid "Importing widgets"
233
  msgstr ""
234
 
235
+ #: inc/WidgetImporter.php:88
236
+ msgid "Error: Widget import file could not be found."
237
  msgstr ""
238
 
239
+ #: inc/WidgetImporter.php:118
240
+ msgid "Error: Widget import data could not be read. Please try a different file."
241
  msgstr ""
242
 
243
+ #: inc/WidgetImporter.php:157
244
  msgid "Sidebar does not exist in theme (moving widget to Inactive)"
245
  msgstr ""
246
 
247
+ #: inc/WidgetImporter.php:178
248
  msgid "Site does not support widget"
249
  msgstr ""
250
 
251
+ #: inc/WidgetImporter.php:211
252
  msgid "Widget already exists"
253
  msgstr ""
254
 
255
+ #: inc/WidgetImporter.php:269
256
  msgid "Imported"
257
  msgstr ""
258
 
259
+ #: inc/WidgetImporter.php:273
260
  msgid "Imported to Inactive"
261
  msgstr ""
262
 
263
+ #: inc/WidgetImporter.php:279
264
  msgid "No Title"
265
  msgstr ""
266
 
267
+ #: inc/WidgetImporter.php:326
268
  msgid "No results for widget import!"
269
  msgstr ""
270
 
271
+ #: one-click-demo-import.php:51
272
  msgid ""
273
  "The %2$sOne Click Demo Import%3$s plugin requires %2$sPHP 5.3.2+%3$s to run "
274
  "properly. Please contact your hosting company and ask them to update the "
one-click-demo-import.php CHANGED
@@ -4,7 +4,7 @@
4
  Plugin Name: One Click Demo Import
5
  Plugin URI: https://wordpress.org/plugins/one-click-demo-import/
6
  Description: Import your content, widgets and theme settings with one click. Theme authors! Enable simple demo import for your theme demo data.
7
- Version: 1.4.0
8
  Author: ProteusThemes
9
  Author URI: http://www.proteusthemes.com
10
  License: GPL3
@@ -16,37 +16,73 @@ Text Domain: pt-ocdi
16
  defined( 'ABSPATH' ) or die( 'No script kiddies please!' );
17
 
18
  /**
19
- * Display admin error message if PHP version is older than 5.3.2.
20
- * Otherwise execute the main plugin class.
21
  */
22
- if ( version_compare( phpversion(), '5.3.2', '<' ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
 
24
  /**
25
  * Display an admin error notice when PHP is older the version 5.3.2.
26
  * Hook it to the 'admin_notices' action.
27
  */
28
- function ocdi_old_php_admin_error_notice() {
29
  $message = sprintf( esc_html__( 'The %2$sOne 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', 'pt-ocdi' ), phpversion(), '<strong>', '</strong>', '<br>' );
30
 
31
  printf( '<div class="notice notice-error"><p>%1$s</p></div>', wp_kses_post( $message ) );
32
  }
33
- add_action( 'admin_notices', 'ocdi_old_php_admin_error_notice' );
34
- }
35
- else {
36
 
37
- // Current version of the plugin.
38
- define( 'PT_OCDI_VERSION', '1.4.0' );
39
 
40
- // Path/URL to root of this plugin, with trailing slash.
41
- define( 'PT_OCDI_PATH', plugin_dir_path( __FILE__ ) );
42
- define( 'PT_OCDI_URL', plugin_dir_url( __FILE__ ) );
 
 
 
 
 
 
 
 
 
 
43
 
44
- // Composer autoloader.
45
- require_once PT_OCDI_PATH . 'vendor/autoload.php';
 
46
 
47
- // Require main plugin file.
48
- require PT_OCDI_PATH . 'inc/class-ocdi-main.php';
49
 
50
- // Instantiate the main plugin class *Singleton*.
51
- $pt_one_click_demo_import = PT_One_Click_Demo_Import::getInstance();
 
 
 
 
 
 
 
52
  }
 
 
 
4
  Plugin Name: One Click Demo Import
5
  Plugin URI: https://wordpress.org/plugins/one-click-demo-import/
6
  Description: Import your content, widgets and theme settings with one click. Theme authors! Enable simple demo import for your theme demo data.
7
+ Version: 2.0.0
8
  Author: ProteusThemes
9
  Author URI: http://www.proteusthemes.com
10
  License: GPL3
16
  defined( 'ABSPATH' ) or die( 'No script kiddies please!' );
17
 
18
  /**
19
+ * Main plugin class with initialization tasks.
 
20
  */
21
+ class OCDI_Plugin {
22
+ /**
23
+ * Constructor for this class.
24
+ */
25
+ public function __construct() {
26
+ /**
27
+ * Display admin error message if PHP version is older than 5.3.2.
28
+ * Otherwise execute the main plugin class.
29
+ */
30
+ if ( version_compare( phpversion(), '5.3.2', '<' ) ) {
31
+ add_action( 'admin_notices', array( $this, 'old_php_admin_error_notice' ) );
32
+ }
33
+ else {
34
+ // Set plugin constants.
35
+ $this->set_plugin_constants();
36
+
37
+ // Composer autoloader.
38
+ require_once PT_OCDI_PATH . 'vendor/autoload.php';
39
+
40
+ // Instantiate the main plugin class *Singleton*.
41
+ $pt_one_click_demo_import = OCDI\OneClickDemoImport::get_instance();
42
+ }
43
+ }
44
+
45
 
46
  /**
47
  * Display an admin error notice when PHP is older the version 5.3.2.
48
  * Hook it to the 'admin_notices' action.
49
  */
50
+ public function old_php_admin_error_notice() {
51
  $message = sprintf( esc_html__( 'The %2$sOne 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', 'pt-ocdi' ), phpversion(), '<strong>', '</strong>', '<br>' );
52
 
53
  printf( '<div class="notice notice-error"><p>%1$s</p></div>', wp_kses_post( $message ) );
54
  }
 
 
 
55
 
 
 
56
 
57
+ /**
58
+ * Set plugin constants.
59
+ *
60
+ * Path/URL to root of this plugin, with trailing slash and plugin version.
61
+ */
62
+ private function set_plugin_constants() {
63
+ // Path/URL to root of this plugin, with trailing slash.
64
+ if ( ! defined( 'PT_OCDI_PATH' ) ) {
65
+ define( 'PT_OCDI_PATH', plugin_dir_path( __FILE__ ) );
66
+ }
67
+ if ( ! defined( 'PT_OCDI_URL' ) ) {
68
+ define( 'PT_OCDI_URL', plugin_dir_url( __FILE__ ) );
69
+ }
70
 
71
+ // Action hook to set the plugin version constant.
72
+ add_action( 'admin_init', array( $this, 'set_plugin_version_constant' ) );
73
+ }
74
 
 
 
75
 
76
+ /**
77
+ * Set plugin version constant -> PT_OCDI_VERSION.
78
+ */
79
+ public function set_plugin_version_constant() {
80
+ if ( ! defined( 'PT_OCDI_VERSION' ) ) {
81
+ $plugin_data = get_plugin_data( __FILE__ );
82
+ define( 'PT_OCDI_VERSION', $plugin_data['Version'] );
83
+ }
84
+ }
85
  }
86
+
87
+ // Instantiate the plugin class.
88
+ $ocdi_plugin = new OCDI_Plugin();
readme.txt CHANGED
@@ -1,9 +1,9 @@
1
  === One Click Demo Import ===
2
- Contributors: capuderg, cyman
3
  Tags: import, content, demo, data, widgets, settings
4
  Requires at least: 4.0.0
5
- Tested up to: 4.6
6
- Stable tag: 1.4.0
7
  License: GPLv3 or later
8
 
9
  Import your demo content, widgets and theme settings with one click. Theme authors! Enable simple demo import for your theme demo data.
@@ -21,13 +21,11 @@ The best feature of this plugin is, that theme authors can define import files i
21
 
22
  This plugin will create a submenu page under Appearance with the title **Import demo data**.
23
 
24
- If the theme you are using does not have any predefined import files, then you will be presented with three file upload inputs. First one is required and you will have to upload a demo content XML file, for the actual demo import. The second one is optional and will ask you for a WIE or JSON file for widgets import. You create that file using the [Widget Importer & Exporter](https://wordpress.org/plugins/widget-importer-exporter/) plugin. The third one is also optional and will import the customizer settings, select the DAT file which you can generate from [Customizer Export/Import](https://wordpress.org/plugins/customizer-export-import/) plugin (the customizer settings will be imported only if the export file was created from the same theme).
25
 
26
  This plugin is using the improved WP import 2.0 that is still in development and can be found here: https://github.com/humanmade/WordPress-Importer.
27
 
28
- All progress of this plugin's work is logged in a log file in the default WP upload directory, together with the demo content and widgets import files used in the importing process.
29
-
30
- NOTE: This plugin is still a work in progress!
31
 
32
  NOTE: There is no setting to "connect" authors from the demo import file to the existing users in your WP site (like there is in the original WP Importer plugin). All demo content will be imported under the current user.
33
 
@@ -72,17 +70,35 @@ function ocdi_import_files() {
72
  return array(
73
  array(
74
  'import_file_name' => 'Demo Import 1',
 
75
  'import_file_url' => 'http://www.your_domain.com/ocdi/demo-content.xml',
76
  'import_widget_file_url' => 'http://www.your_domain.com/ocdi/widgets.json',
77
  'import_customizer_file_url' => 'http://www.your_domain.com/ocdi/customizer.dat',
 
 
 
 
 
 
78
  'import_preview_image_url' => 'http://www.your_domain.com/ocdi/preview_import_image1.jpg',
79
  'import_notice' => __( 'After you import this demo, you will have to setup the slider separately.', 'your-textdomain' ),
80
  ),
81
  array(
82
  'import_file_name' => 'Demo Import 2',
 
83
  'import_file_url' => 'http://www.your_domain.com/ocdi/demo-content2.xml',
84
  'import_widget_file_url' => 'http://www.your_domain.com/ocdi/widgets2.json',
85
  'import_customizer_file_url' => 'http://www.your_domain.com/ocdi/customizer2.dat',
 
 
 
 
 
 
 
 
 
 
86
  'import_preview_image_url' => 'http://www.your_domain.com/ocdi/preview_import_image2.jpg',
87
  'import_notice' => __( 'A special note for this import.', 'your-textdomain' ),
88
  ),
@@ -91,7 +107,7 @@ function ocdi_import_files() {
91
  add_filter( 'pt-ocdi/import_files', 'ocdi_import_files' );
92
  `
93
 
94
- You can set content import, widgets, and customizer import files. You can also define a preview image, which will be used only when multiple demo imports are defined, so that the user will see the difference between imports.
95
 
96
  = How to automatically assign "Front page", "Posts page" and menu locations after the importer is done? =
97
 
@@ -128,17 +144,35 @@ function ocdi_import_files() {
128
  return array(
129
  array(
130
  'import_file_name' => 'Demo Import 1',
 
131
  'local_import_file' => trailingslashit( get_template_directory() ) . 'ocdi/demo-content.xml',
132
  'local_import_widget_file' => trailingslashit( get_template_directory() ) . 'ocdi/widgets.json',
133
  'local_import_customizer_file' => trailingslashit( get_template_directory() ) . 'ocdi/customizer.dat',
 
 
 
 
 
 
134
  'import_preview_image_url' => 'http://www.your_domain.com/ocdi/preview_import_image1.jpg',
135
  'import_notice' => __( 'After you import this demo, you will have to setup the slider separately.', 'your-textdomain' ),
136
  ),
137
  array(
138
  'import_file_name' => 'Demo Import 2',
 
139
  'local_import_file' => trailingslashit( get_template_directory() ) . 'ocdi/demo-content2.xml',
140
  'local_import_widget_file' => trailingslashit( get_template_directory() ) . 'ocdi/widgets2.json',
141
  'local_import_customizer_file' => trailingslashit( get_template_directory() ) . 'ocdi/customizer2.dat',
 
 
 
 
 
 
 
 
 
 
142
  'import_preview_image_url' => 'http://www.your_domain.com/ocdi/preview_import_image2.jpg',
143
  'import_notice' => __( 'A special note for this import.', 'your-textdomain' ),
144
  ),
@@ -220,6 +254,33 @@ function ocdi_plugin_page_setup( $default_settings ) {
220
  add_filter( 'pt-ocdi/plugin_page_setup', 'ocdi_plugin_page_setup' );
221
  `
222
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
  = I can't activate the plugin, because of a fatal error, what can I do? =
224
 
225
  *Update: since version 1.2.0, there is now a admin error notice, stating that the minimal PHP version required for this plugin is 5.3.2.*
@@ -228,7 +289,7 @@ You want to activate the plugin, but this error shows up:
228
 
229
  *Plugin could not be activated because it triggered a fatal error*
230
 
231
- This happens, because your hosting server is using a very old version of PHP. This plugin requires PHP version of at least **5.3.x**, but we recommend version *5.6.x*. Please contact your hosting company and ask them to update the PHP version for your site.
232
 
233
  = Issues with the import, that we can't fix in the plugin =
234
 
@@ -242,6 +303,19 @@ Please visit this [docs page](https://github.com/proteusthemes/one-click-demo-im
242
 
243
  == Changelog ==
244
 
 
 
 
 
 
 
 
 
 
 
 
 
 
245
  = 1.4.0 =
246
 
247
  *Release Date - 29 October 2016*
1
  === One Click Demo Import ===
2
+ Contributors: capuderg, cyman, Prelc
3
  Tags: import, content, demo, data, widgets, settings
4
  Requires at least: 4.0.0
5
+ Tested up to: 4.7
6
+ Stable tag: 2.0.0
7
  License: GPLv3 or later
8
 
9
  Import your demo content, widgets and theme settings with one click. Theme authors! Enable simple demo import for your theme demo data.
21
 
22
  This plugin will create a submenu page under Appearance with the title **Import demo data**.
23
 
24
+ If the theme you are using does not have any predefined import files, then you will be presented with three file upload inputs. First one is required and you will have to upload a demo content XML file, for the actual demo import. The second one is optional and will ask you for a WIE or JSON file for widgets import. You create that file using the [Widget Importer & Exporter](https://wordpress.org/plugins/widget-importer-exporter/) plugin. The third one is also optional and will import the customizer settings, select the DAT file which you can generate from [Customizer Export/Import](https://wordpress.org/plugins/customizer-export-import/) plugin (the customizer settings will be imported only if the export file was created from the same theme). The final one is optional as well and will import your Redux framework settings. You can generate the export json file with the [Redux framework](https://wordpress.org/plugins/redux-framework/) plugin.
25
 
26
  This plugin is using the improved WP import 2.0 that is still in development and can be found here: https://github.com/humanmade/WordPress-Importer.
27
 
28
+ All progress of this plugin's work is logged in a log file in the default WP upload directory, together with the demo import files used in the importing process.
 
 
29
 
30
  NOTE: There is no setting to "connect" authors from the demo import file to the existing users in your WP site (like there is in the original WP Importer plugin). All demo content will be imported under the current user.
31
 
70
  return array(
71
  array(
72
  'import_file_name' => 'Demo Import 1',
73
+ 'categories' => array( 'Category 1', 'Category 2' ),
74
  'import_file_url' => 'http://www.your_domain.com/ocdi/demo-content.xml',
75
  'import_widget_file_url' => 'http://www.your_domain.com/ocdi/widgets.json',
76
  'import_customizer_file_url' => 'http://www.your_domain.com/ocdi/customizer.dat',
77
+ 'import_redux' => array(
78
+ array(
79
+ 'file_url' => 'http://www.your_domain.com/ocdi/redux.json',
80
+ 'option_name' => 'redux_option_name',
81
+ ),
82
+ ),
83
  'import_preview_image_url' => 'http://www.your_domain.com/ocdi/preview_import_image1.jpg',
84
  'import_notice' => __( 'After you import this demo, you will have to setup the slider separately.', 'your-textdomain' ),
85
  ),
86
  array(
87
  'import_file_name' => 'Demo Import 2',
88
+ 'categories' => array( 'New category', 'Old category' ),
89
  'import_file_url' => 'http://www.your_domain.com/ocdi/demo-content2.xml',
90
  'import_widget_file_url' => 'http://www.your_domain.com/ocdi/widgets2.json',
91
  'import_customizer_file_url' => 'http://www.your_domain.com/ocdi/customizer2.dat',
92
+ 'import_redux' => array(
93
+ array(
94
+ 'file_url' => 'http://www.your_domain.com/ocdi/redux.json',
95
+ 'option_name' => 'redux_option_name',
96
+ ),
97
+ array(
98
+ 'file_url' => 'http://www.your_domain.com/ocdi/redux2.json',
99
+ 'option_name' => 'redux_option_name_2',
100
+ ),
101
+ ),
102
  'import_preview_image_url' => 'http://www.your_domain.com/ocdi/preview_import_image2.jpg',
103
  'import_notice' => __( 'A special note for this import.', 'your-textdomain' ),
104
  ),
107
  add_filter( 'pt-ocdi/import_files', 'ocdi_import_files' );
108
  `
109
 
110
+ You can set content import, widgets, customizer and Redux framework import files. You can also define a preview image, which will be used only when multiple demo imports are defined, so that the user will see the difference between imports. Categories can be assigned to each demo import, so that they can be filtered easily.
111
 
112
  = How to automatically assign "Front page", "Posts page" and menu locations after the importer is done? =
113
 
144
  return array(
145
  array(
146
  'import_file_name' => 'Demo Import 1',
147
+ 'categories' => array( 'Category 1', 'Category 2' ),
148
  'local_import_file' => trailingslashit( get_template_directory() ) . 'ocdi/demo-content.xml',
149
  'local_import_widget_file' => trailingslashit( get_template_directory() ) . 'ocdi/widgets.json',
150
  'local_import_customizer_file' => trailingslashit( get_template_directory() ) . 'ocdi/customizer.dat',
151
+ 'local_import_redux' => array(
152
+ array(
153
+ 'file_path' => trailingslashit( get_template_directory() ) . 'ocdi/redux.json',
154
+ 'option_name' => 'redux_option_name',
155
+ ),
156
+ ),
157
  'import_preview_image_url' => 'http://www.your_domain.com/ocdi/preview_import_image1.jpg',
158
  'import_notice' => __( 'After you import this demo, you will have to setup the slider separately.', 'your-textdomain' ),
159
  ),
160
  array(
161
  'import_file_name' => 'Demo Import 2',
162
+ 'categories' => array( 'New category', 'Old category' ),
163
  'local_import_file' => trailingslashit( get_template_directory() ) . 'ocdi/demo-content2.xml',
164
  'local_import_widget_file' => trailingslashit( get_template_directory() ) . 'ocdi/widgets2.json',
165
  'local_import_customizer_file' => trailingslashit( get_template_directory() ) . 'ocdi/customizer2.dat',
166
+ 'local_import_redux' => array(
167
+ array(
168
+ 'file_path' => trailingslashit( get_template_directory() ) . 'ocdi/redux.json',
169
+ 'option_name' => 'redux_option_name',
170
+ ),
171
+ array(
172
+ 'file_path' => trailingslashit( get_template_directory() ) . 'ocdi/redux2.json',
173
+ 'option_name' => 'redux_option_name_2',
174
+ ),
175
+ ),
176
  'import_preview_image_url' => 'http://www.your_domain.com/ocdi/preview_import_image2.jpg',
177
  'import_notice' => __( 'A special note for this import.', 'your-textdomain' ),
178
  ),
254
  add_filter( 'pt-ocdi/plugin_page_setup', 'ocdi_plugin_page_setup' );
255
  `
256
 
257
+ = How to do something before the content import executes? =
258
+
259
+ In version 2.0.0 there is a new action hook: `pt-ocdi/before_content_import`, which will let you hook before the content import starts. An example of the code would look like this:
260
+
261
+ `
262
+ function ocdi_before_content_import( $selected_import ) {
263
+ if ( 'Demo Import 1' === $selected_import['import_file_name'] ) {
264
+ // Here you can do stuff for the "Demo Import 1" before the content import starts.
265
+ echo "before import 1";
266
+ }
267
+ else {
268
+ // Here you can do stuff for all other imports before the content import starts.
269
+ echo "before import 2";
270
+ }
271
+ }
272
+ add_action( 'pt-ocdi/before_content_import', 'ocdi_before_content_import' );
273
+ `
274
+
275
+ = How can I enable the `customize_save*` wp action hooks in the customizer import? =
276
+
277
+ It's easy, just add this to your theme:
278
+
279
+ `add_action( 'pt-ocdi/enable_wp_customize_save_hooks', '__return_true' );`
280
+
281
+ This will enable the following WP hooks when importing the customizer data: `customize_save`, `customize_save_*`, `customize_save_after`.
282
+
283
+
284
  = I can't activate the plugin, because of a fatal error, what can I do? =
285
 
286
  *Update: since version 1.2.0, there is now a admin error notice, stating that the minimal PHP version required for this plugin is 5.3.2.*
289
 
290
  *Plugin could not be activated because it triggered a fatal error*
291
 
292
+ This happens, because your hosting server is using a very old version of PHP. This plugin requires PHP version of at least **5.3.x**, but we recommend version *5.6.x* or better yet *7.x*. Please contact your hosting company and ask them to update the PHP version for your site.
293
 
294
  = Issues with the import, that we can't fix in the plugin =
295
 
303
 
304
  == Changelog ==
305
 
306
+ = 2.0.0 =
307
+
308
+ *Release Date - 10 December 2016*
309
+
310
+ * Add new layout for multiple predefined demo imports (a grid layout instead of the dropdown selector),
311
+ * Add support for Redux framework import,
312
+ * Change the code structure of the plugin (plugin rewrite, namespaces, autoloading),
313
+ * Now the whole import (content, widgets, customizer, redux) goes through even if something goes wrong in the content import (before content import errors blocked further import),
314
+ * Add `pt-ocdi/before_content_import` action hook, that theme authors can use to hook into before the content import starts,
315
+ * Fix frontend error reporting through multiple AJAX calls,
316
+ * Fix post formats (video/quote/gallery,...) not importing,
317
+ * Fix customizer import does not save some options (because of the missing WP actions - these can be enabled via a filter, more in the FAQ section).
318
+
319
  = 1.4.0 =
320
 
321
  *Release Date - 29 October 2016*
vendor/autoload.php CHANGED
@@ -2,6 +2,6 @@
2
 
3
  // autoload.php @generated by Composer
4
 
5
- require_once __DIR__ . '/composer' . '/autoload_real.php';
6
 
7
- return ComposerAutoloaderInit3386d3451f83bf87ed4e429dad5a4f19::getLoader();
2
 
3
  // autoload.php @generated by Composer
4
 
5
+ require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInit5e05a8e52ae52aaddbd9f3cfe3ad95a2::getLoader();
vendor/composer/autoload_psr4.php CHANGED
@@ -7,4 +7,5 @@ $baseDir = dirname($vendorDir);
7
 
8
  return array(
9
  'ProteusThemes\\WPContentImporter2\\' => array($vendorDir . '/proteusthemes/wp-content-importer-v2/src'),
 
10
  );
7
 
8
  return array(
9
  'ProteusThemes\\WPContentImporter2\\' => array($vendorDir . '/proteusthemes/wp-content-importer-v2/src'),
10
+ 'OCDI\\' => array($baseDir . '/inc'),
11
  );
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInit3386d3451f83bf87ed4e429dad5a4f19
6
  {
7
  private static $loader;
8
 
@@ -19,15 +19,15 @@ class ComposerAutoloaderInit3386d3451f83bf87ed4e429dad5a4f19
19
  return self::$loader;
20
  }
21
 
22
- spl_autoload_register(array('ComposerAutoloaderInit3386d3451f83bf87ed4e429dad5a4f19', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
- spl_autoload_unregister(array('ComposerAutoloaderInit3386d3451f83bf87ed4e429dad5a4f19', 'loadClassLoader'));
25
 
26
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION');
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
- call_user_func(\Composer\Autoload\ComposerStaticInit3386d3451f83bf87ed4e429dad5a4f19::getInitializer($loader));
31
  } else {
32
  $map = require __DIR__ . '/autoload_namespaces.php';
33
  foreach ($map as $namespace => $path) {
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInit5e05a8e52ae52aaddbd9f3cfe3ad95a2
6
  {
7
  private static $loader;
8
 
19
  return self::$loader;
20
  }
21
 
22
+ spl_autoload_register(array('ComposerAutoloaderInit5e05a8e52ae52aaddbd9f3cfe3ad95a2', 'loadClassLoader'), true, true);
23
  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit5e05a8e52ae52aaddbd9f3cfe3ad95a2', 'loadClassLoader'));
25
 
26
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION');
27
  if ($useStaticLoader) {
28
  require_once __DIR__ . '/autoload_static.php';
29
 
30
+ call_user_func(\Composer\Autoload\ComposerStaticInit5e05a8e52ae52aaddbd9f3cfe3ad95a2::getInitializer($loader));
31
  } else {
32
  $map = require __DIR__ . '/autoload_namespaces.php';
33
  foreach ($map as $namespace => $path) {
vendor/composer/autoload_static.php CHANGED
@@ -4,13 +4,17 @@
4
 
5
  namespace Composer\Autoload;
6
 
7
- class ComposerStaticInit3386d3451f83bf87ed4e429dad5a4f19
8
  {
9
  public static $prefixLengthsPsr4 = array (
10
  'P' =>
11
  array (
12
  'ProteusThemes\\WPContentImporter2\\' => 33,
13
  ),
 
 
 
 
14
  );
15
 
16
  public static $prefixDirsPsr4 = array (
@@ -18,13 +22,17 @@ class ComposerStaticInit3386d3451f83bf87ed4e429dad5a4f19
18
  array (
19
  0 => __DIR__ . '/..' . '/proteusthemes/wp-content-importer-v2/src',
20
  ),
 
 
 
 
21
  );
22
 
23
  public static function getInitializer(ClassLoader $loader)
24
  {
25
  return \Closure::bind(function () use ($loader) {
26
- $loader->prefixLengthsPsr4 = ComposerStaticInit3386d3451f83bf87ed4e429dad5a4f19::$prefixLengthsPsr4;
27
- $loader->prefixDirsPsr4 = ComposerStaticInit3386d3451f83bf87ed4e429dad5a4f19::$prefixDirsPsr4;
28
 
29
  }, null, ClassLoader::class);
30
  }
4
 
5
  namespace Composer\Autoload;
6
 
7
+ class ComposerStaticInit5e05a8e52ae52aaddbd9f3cfe3ad95a2
8
  {
9
  public static $prefixLengthsPsr4 = array (
10
  'P' =>
11
  array (
12
  'ProteusThemes\\WPContentImporter2\\' => 33,
13
  ),
14
+ 'O' =>
15
+ array (
16
+ 'OCDI\\' => 5,
17
+ ),
18
  );
19
 
20
  public static $prefixDirsPsr4 = array (
22
  array (
23
  0 => __DIR__ . '/..' . '/proteusthemes/wp-content-importer-v2/src',
24
  ),
25
+ 'OCDI\\' =>
26
+ array (
27
+ 0 => __DIR__ . '/../..' . '/inc',
28
+ ),
29
  );
30
 
31
  public static function getInitializer(ClassLoader $loader)
32
  {
33
  return \Closure::bind(function () use ($loader) {
34
+ $loader->prefixLengthsPsr4 = ComposerStaticInit5e05a8e52ae52aaddbd9f3cfe3ad95a2::$prefixLengthsPsr4;
35
+ $loader->prefixDirsPsr4 = ComposerStaticInit5e05a8e52ae52aaddbd9f3cfe3ad95a2::$prefixDirsPsr4;
36
 
37
  }, null, ClassLoader::class);
38
  }
vendor/composer/installed.json CHANGED
@@ -1,20 +1,20 @@
1
  [
2
  {
3
  "name": "proteusthemes/wp-content-importer-v2",
4
- "version": "v0.2.0",
5
- "version_normalized": "0.2.0.0",
6
  "source": {
7
  "type": "git",
8
  "url": "https://github.com/proteusthemes/WordPress-Importer.git",
9
- "reference": "d0f410cfe3921cab85682dfbccfaccbcdf7d9672"
10
  },
11
  "dist": {
12
  "type": "zip",
13
- "url": "https://api.github.com/repos/proteusthemes/WordPress-Importer/zipball/d0f410cfe3921cab85682dfbccfaccbcdf7d9672",
14
- "reference": "d0f410cfe3921cab85682dfbccfaccbcdf7d9672",
15
  "shasum": ""
16
  },
17
- "time": "2016-10-29 11:19:31",
18
  "type": "library",
19
  "installation-source": "source",
20
  "autoload": {
@@ -41,7 +41,7 @@
41
  "wp"
42
  ],
43
  "support": {
44
- "source": "https://github.com/proteusthemes/WordPress-Importer/tree/v0.2.0"
45
  }
46
  }
47
  ]
1
  [
2
  {
3
  "name": "proteusthemes/wp-content-importer-v2",
4
+ "version": "v0.4.0",
5
+ "version_normalized": "0.4.0.0",
6
  "source": {
7
  "type": "git",
8
  "url": "https://github.com/proteusthemes/WordPress-Importer.git",
9
+ "reference": "7d93b7adbfbf8d7496968d9352dcf948606b1a55"
10
  },
11
  "dist": {
12
  "type": "zip",
13
+ "url": "https://api.github.com/repos/proteusthemes/WordPress-Importer/zipball/7d93b7adbfbf8d7496968d9352dcf948606b1a55",
14
+ "reference": "7d93b7adbfbf8d7496968d9352dcf948606b1a55",
15
  "shasum": ""
16
  },
17
+ "time": "2016-12-01 18:39:14",
18
  "type": "library",
19
  "installation-source": "source",
20
  "autoload": {
41
  "wp"
42
  ],
43
  "support": {
44
+ "source": "https://github.com/proteusthemes/WordPress-Importer/tree/v0.4.0"
45
  }
46
  }
47
  ]
vendor/proteusthemes/wp-content-importer-v2/src/WXRImporter.php CHANGED
@@ -907,8 +907,45 @@ class WXRImporter extends \WP_Importer {
907
  if ( isset( $this->mapping['term'][ $key ] ) ) {
908
  $term_ids[ $taxonomy ][] = (int) $this->mapping['term'][ $key ];
909
  } else {
910
- $meta[] = array( 'key' => '_wxr_import_term', 'value' => $term );
911
- $requires_remapping = true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
912
  }
913
  }
914
 
@@ -1635,14 +1672,22 @@ class WXRImporter extends \WP_Importer {
1635
  return false;
1636
  }
1637
 
1638
- $original_id = isset( $data['id'] ) ? (int) $data['id'] : 0;
1639
- $parent_id = isset( $data['parent'] ) ? (int) $data['parent'] : 0;
 
 
 
 
 
 
 
1640
 
1641
  $mapping_key = sha1( $data['taxonomy'] . ':' . $data['slug'] );
1642
  $existing = $this->term_exists( $data );
1643
  if ( $existing ) {
1644
  $this->mapping['term'][ $mapping_key ] = $existing;
1645
  $this->mapping['term_id'][ $original_id ] = $existing;
 
1646
  return false;
1647
  }
1648
 
@@ -1655,23 +1700,23 @@ class WXRImporter extends \WP_Importer {
1655
  $allowed = array(
1656
  'slug' => true,
1657
  'description' => true,
 
1658
  );
1659
 
1660
  // Map the parent comment, or mark it as one we need to fix
1661
- // TODO: add parent mapping and remapping
1662
- /*$requires_remapping = false;
1663
- if ( $parent_id ) {
1664
- if ( isset( $this->mapping['term'][ $parent_id ] ) ) {
1665
- $data['parent'] = $this->mapping['term'][ $parent_id ];
1666
  } else {
1667
  // Prepare for remapping later
1668
- $meta[] = array( 'key' => '_wxr_import_parent', 'value' => $parent_id );
1669
  $requires_remapping = true;
1670
 
1671
- // Wipe the parent for now
1672
  $data['parent'] = 0;
1673
  }
1674
- }*/
1675
 
1676
  foreach ( $data as $key => $value ) {
1677
  if ( ! isset( $allowed[ $key ] ) ) {
@@ -1704,8 +1749,40 @@ class WXRImporter extends \WP_Importer {
1704
 
1705
  $term_id = $result['term_id'];
1706
 
 
1707
  $this->mapping['term'][ $mapping_key ] = $term_id;
1708
  $this->mapping['term_id'][ $original_id ] = $term_id;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1709
 
1710
  $this->logger->info( sprintf(
1711
  __( 'Imported "%s" (%s)', 'wordpress-importer' ),
@@ -1849,6 +1926,9 @@ class WXRImporter extends \WP_Importer {
1849
  if ( ! empty( $this->requires_remapping['comment'] ) ) {
1850
  $this->post_process_comments( $this->requires_remapping['comment'] );
1851
  }
 
 
 
1852
  }
1853
 
1854
  protected function post_process_posts( $todo ) {
@@ -2053,6 +2133,103 @@ class WXRImporter extends \WP_Importer {
2053
  }
2054
  }
2055
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2056
  /**
2057
  * Use stored mapping information to update old attachment URLs
2058
  */
907
  if ( isset( $this->mapping['term'][ $key ] ) ) {
908
  $term_ids[ $taxonomy ][] = (int) $this->mapping['term'][ $key ];
909
  } else {
910
+
911
+ /**
912
+ * Fix for the post format "categories".
913
+ * The issue in this importer is, that these post formats are misused as categories in WP export
914
+ * (as the export data <category> item in the post export item), but they are not actually
915
+ * exported as wp:category items in the XML file, so they need to be inserted on the fly (here).
916
+ *
917
+ * Maybe something better can be done in the future?
918
+ *
919
+ * Original issue reported here: https://wordpress.org/support/topic/post-format-videoquotegallery-became-format-standard/#post-8447683
920
+ *
921
+ */
922
+ if ( 'post_format' === $taxonomy ) {
923
+ $term_exists = term_exists( $term['slug'], $taxonomy );
924
+ $term_id = is_array( $term_exists ) ? $term_exists['term_id'] : $term_exists;
925
+
926
+ if ( empty( $term_id ) ) {
927
+ $t = wp_insert_term( $term['name'], $taxonomy, array( 'slug' => $term['slug'] ) );
928
+ if ( ! is_wp_error( $t ) ) {
929
+ $term_id = $t['term_id'];
930
+ $this->mapping['term'][ $key ] = $term_id;
931
+ } else {
932
+ $this->logger->warning( sprintf(
933
+ esc_html__( 'Failed to import term: %s - %s', 'wordpress-importer' ),
934
+ esc_html( $taxonomy ),
935
+ esc_html( $term['name'] )
936
+ ) );
937
+ continue;
938
+ }
939
+ }
940
+
941
+ if ( ! empty( $term_id ) ) {
942
+ $term_ids[ $taxonomy ][] = intval( $term_id );
943
+ }
944
+ } // End of fix.
945
+ else {
946
+ $meta[] = array( 'key' => '_wxr_import_term', 'value' => $term );
947
+ $requires_remapping = true;
948
+ }
949
  }
950
  }
951
 
1672
  return false;
1673
  }
1674
 
1675
+ $original_id = isset( $data['id'] ) ? (int) $data['id'] : 0;
1676
+
1677
+ /* FIX for OCDI!
1678
+ * As of WP 4.5, export.php returns the SLUG for the term's parent,
1679
+ * rather than an integer ID (this differs from a post_parent)
1680
+ * wp_insert_term and wp_update_term use the key: 'parent' and an integer value 'id'
1681
+ */
1682
+ $term_slug = isset( $data['slug'] ) ? $data['slug'] : '';
1683
+ $parent_slug = isset( $data['parent'] ) ? $data['parent'] : '';
1684
 
1685
  $mapping_key = sha1( $data['taxonomy'] . ':' . $data['slug'] );
1686
  $existing = $this->term_exists( $data );
1687
  if ( $existing ) {
1688
  $this->mapping['term'][ $mapping_key ] = $existing;
1689
  $this->mapping['term_id'][ $original_id ] = $existing;
1690
+ $this->mapping['term_slug'][ $term_slug ] = $existing;
1691
  return false;
1692
  }
1693
 
1700
  $allowed = array(
1701
  'slug' => true,
1702
  'description' => true,
1703
+ 'parent' => true, // The parent_id may have already been set, so pass this back to the newly inserted term.
1704
  );
1705
 
1706
  // Map the parent comment, or mark it as one we need to fix
1707
+ $requires_remapping = false;
1708
+ if ( $parent_slug ) {
1709
+ if ( isset( $this->mapping['term_slug'][ $parent_slug ] ) ) {
1710
+ $data['parent'] = $this->mapping['term_slug'][ $parent_slug ];
 
1711
  } else {
1712
  // Prepare for remapping later
1713
+ $meta[] = array( 'key' => '_wxr_import_parent', 'value' => $parent_slug );
1714
  $requires_remapping = true;
1715
 
1716
+ // Wipe the parent id for now
1717
  $data['parent'] = 0;
1718
  }
1719
+ }
1720
 
1721
  foreach ( $data as $key => $value ) {
1722
  if ( ! isset( $allowed[ $key ] ) ) {
1749
 
1750
  $term_id = $result['term_id'];
1751
 
1752
+ // Now prepare to map this new term.
1753
  $this->mapping['term'][ $mapping_key ] = $term_id;
1754
  $this->mapping['term_id'][ $original_id ] = $term_id;
1755
+ $this->mapping['term_slug'][ $term_slug ] = $term_id;
1756
+
1757
+ /*
1758
+ * Fix for OCDI!
1759
+ * The parent will be updated later in post_process_terms
1760
+ * we will need both the term_id AND the term_taxonomy to retrieve existing
1761
+ * term attributes. Those attributes will be returned with the corrected parent,
1762
+ * using wp_update_term.
1763
+ * Pass both the term_id along with the term_taxonomy as key=>value
1764
+ * in the requires_remapping['term'] array.
1765
+ */
1766
+ if ( $requires_remapping ) {
1767
+ $this->requires_remapping['term'][ $term_id ] = $data['taxonomy'];
1768
+ }
1769
+
1770
+ // Insert termmeta, if any, including the flag to remap the parent '_wxr_import_parent'.
1771
+ if( ! empty( $meta ) ){
1772
+ foreach ( $meta as $meta_item ){
1773
+ $result = add_term_meta ( $term_id, $meta_item['key'], $meta_item['value'] );
1774
+ if ( is_wp_error( $result ) ) {
1775
+ $this->logger->warning( sprintf(
1776
+ __( 'Failed to add metakey: %s, metavalue: %s to term_id: %d', 'wordpress-importer' ),
1777
+ $meta_item['key'], $meta_item['value'], $term_id ) );
1778
+ do_action( 'wxr_importer.process_failed.termmeta', $result, $data, $meta );
1779
+ } else {
1780
+ $this->logger->debug( sprintf(
1781
+ __( 'Meta for term_id %d : %s => %s ; successfully added!', 'wordpress-importer' ),
1782
+ $term_id, $meta_key, $meta_value ) );
1783
+ }
1784
+ }
1785
+ }
1786
 
1787
  $this->logger->info( sprintf(
1788
  __( 'Imported "%s" (%s)', 'wordpress-importer' ),
1926
  if ( ! empty( $this->requires_remapping['comment'] ) ) {
1927
  $this->post_process_comments( $this->requires_remapping['comment'] );
1928
  }
1929
+ if ( ! empty( $this->requires_remapping['term'] ) ) {
1930
+ $this->post_process_terms( $this->requires_remapping['term'] );
1931
+ }
1932
  }
1933
 
1934
  protected function post_process_posts( $todo ) {
2133
  }
2134
  }
2135
 
2136
+
2137
+ /**
2138
+ * There is no explicit 'top' or 'root' for a hierarchy of WordPress terms
2139
+ * Terms without a parent, or parent=0 are either unconnected (orphans)
2140
+ * or top-level siblings without an explicit root parent
2141
+ * An unconnected term (orphan) should have a null parent_slug
2142
+ * Top-level siblings without an explicit root parent, shall be identified
2143
+ * with the parent_slug: top
2144
+ * [we'll map parent_slug: top into parent 0]
2145
+ */
2146
+ protected function post_process_terms( $terms_to_be_remapped ) {
2147
+ $this->mapping['term_slug']['top'] = 0;
2148
+ // The term_id and term_taxonomy are passed-in with $this->requires_remapping['term'].
2149
+ foreach ( $terms_to_be_remapped as $termid => $term_taxonomy ) {
2150
+ // Basic check.
2151
+ if( empty( $termid ) || ! is_numeric( $termid ) ) {
2152
+ $this->logger->warning( sprintf(
2153
+ __( 'Faulty term_id provided in terms-to-be-remapped array %s', 'wordpress-importer' ),
2154
+ $termid
2155
+ ) );
2156
+ continue;
2157
+ }
2158
+ // This cast to integer may be unnecessary.
2159
+ $term_id = (int) $termid;
2160
+
2161
+ if( empty( $term_taxonomy ) ){
2162
+ $this->logger->warning( sprintf(
2163
+ __( 'No taxonomy provided in terms-to-be-remapped array for term #%d', 'wordpress-importer' ),
2164
+ $term_id
2165
+ ) );
2166
+ continue;
2167
+ }
2168
+
2169
+ $data = array();
2170
+ $parent_slug = get_term_meta( $term_id, '_wxr_import_parent', true );
2171
+
2172
+ if ( empty( $parent_slug ) ) {
2173
+ $this->logger->warning( sprintf(
2174
+ __( 'No parent_slug identified in remapping-array for term: %d', 'wordpress-importer' ),
2175
+ $term_id
2176
+ ) );
2177
+ continue;
2178
+ }
2179
+
2180
+ if ( ! isset( $this->mapping['term_slug'][ $parent_slug ] ) || ! is_numeric( $this->mapping['term_slug'][ $parent_slug ] ) ) {
2181
+ $this->logger->warning( sprintf(
2182
+ __( 'The term(%d)"s parent_slug (%s) is not found in the remapping-array.', 'wordpress-importer' ),
2183
+ $term_id,
2184
+ $parent_slug
2185
+ ) );
2186
+ continue;
2187
+ }
2188
+
2189
+ $mapped_parent = (int) $this->mapping['term_slug'][ $parent_slug ];
2190
+
2191
+ $termattributes = get_term_by( 'id', $term_id, $term_taxonomy, ARRAY_A );
2192
+ // Note: the default OBJECT return results in a reserved-word clash with 'parent' [$termattributes->parent], so instead return an associative array.
2193
+
2194
+ if ( empty( $termattributes ) ) {
2195
+ $this->logger->warning( sprintf(
2196
+ __( 'No data returned by get_term_by for term_id #%d', 'wordpress-importer' ),
2197
+ $term_id
2198
+ ) );
2199
+ continue;
2200
+ }
2201
+ // Check if the correct parent id is already correctly mapped.
2202
+ if ( isset( $termattributes['parent'] ) && $termattributes['parent'] == $mapped_parent ) {
2203
+ // Clear out our temporary meta key.
2204
+ delete_term_meta( $term_id, '_wxr_import_parent' );
2205
+ continue;
2206
+ }
2207
+
2208
+ // Otherwise set the mapped parent and update the term.
2209
+ $termattributes['parent'] = $mapped_parent;
2210
+
2211
+ $result = wp_update_term( $term_id, $termattributes['taxonomy'], $termattributes );
2212
+
2213
+ if ( is_wp_error( $result ) ) {
2214
+ $this->logger->warning( sprintf(
2215
+ __( 'Could not update "%s" (term #%d) with mapped data', 'wordpress-importer' ),
2216
+ $termattributes['name'],
2217
+ $term_id
2218
+ ) );
2219
+ $this->logger->debug( $result->get_error_message() );
2220
+ continue;
2221
+ }
2222
+ // Clear out our temporary meta key.
2223
+ delete_term_meta( $term_id, '_wxr_import_parent' );
2224
+ $this->logger->debug( sprintf(
2225
+ __( 'Term %d was successfully updated with parent %d', 'wordpress-importer' ),
2226
+ $term_id,
2227
+ $mapped_parent
2228
+ ) );
2229
+ }
2230
+ }
2231
+
2232
+
2233
  /**
2234
  * Use stored mapping information to update old attachment URLs
2235
  */
views/plugin-page.php ADDED
@@ -0,0 +1,177 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The plugin page view - the "settings" page of the plugin.
4
+ *
5
+ * @package ocdi
6
+ */
7
+
8
+ namespace OCDI;
9
+
10
+ ?>
11
+
12
+ <div class="ocdi wrap about-wrap">
13
+
14
+ <h1 class="ocdi__title dashicons-before dashicons-upload"><?php esc_html_e( 'One Click Demo Import', 'pt-ocdi' ); ?></h1>
15
+
16
+ <?php
17
+
18
+ // Display warrning if PHP safe mode is enabled, since we wont be able to change the max_execution_time.
19
+ if ( ini_get( 'safe_mode' ) ) {
20
+ printf(
21
+ esc_html__( '%sWarning: your server is using %sPHP safe mode%s. This means that you might experience server timeout errors.%s', 'pt-ocdi' ),
22
+ '<div class="notice notice-warning is-dismissible"><p>',
23
+ '<strong>',
24
+ '</strong>',
25
+ '</p></div>'
26
+ );
27
+ }
28
+
29
+ // Start output buffer for displaying the plugin intro text.
30
+ ob_start();
31
+ ?>
32
+
33
+ <div class="ocdi__intro-notice notice notice-warning is-dismissible">
34
+ <p><?php esc_html_e( 'Before you begin, make sure all the required plugins are activated.', 'pt-ocdi' ); ?></p>
35
+ </div>
36
+
37
+ <div class="ocdi__intro-text">
38
+ <p class="about-description">
39
+ <?php esc_html_e( 'Importing demo data (post, pages, images, theme settings, ...) is the easiest way to setup your theme.', 'pt-ocdi' ); ?>
40
+ <?php esc_html_e( 'It will allow you to quickly edit everything instead of creating content from scratch.', 'pt-ocdi' ); ?>
41
+ </p>
42
+
43
+ <hr>
44
+
45
+ <p><?php esc_html_e( 'When you import the data, the following things might happen:', 'pt-ocdi' ); ?></p>
46
+
47
+ <ul>
48
+ <li><?php esc_html_e( 'No existing posts, pages, categories, images, custom post types or any other data will be deleted or modified.', 'pt-ocdi' ); ?></li>
49
+ <li><?php esc_html_e( 'Posts, pages, images, widgets, menus and other theme settings will get imported.', 'pt-ocdi' ); ?></li>
50
+ <li><?php esc_html_e( 'Please click on the Import button only once and wait, it can take a couple of minutes.', 'pt-ocdi' ); ?></li>
51
+ </ul>
52
+
53
+ <hr>
54
+ </div>
55
+
56
+ <?php
57
+ $plugin_intro_text = ob_get_clean();
58
+
59
+ // Display the plugin intro text (can be replaced with custom text through the filter below).
60
+ echo wp_kses_post( apply_filters( 'pt-ocdi/plugin_intro_text', $plugin_intro_text ) );
61
+ ?>
62
+
63
+
64
+ <?php if ( empty( $this->import_files ) ) : ?>
65
+
66
+ <div class="notice notice-info is-dismissible">
67
+ <p><?php esc_html_e( 'There are no predefined import files available in this theme. Please upload the import files manually!', 'pt-ocdi' ); ?></p>
68
+ </div>
69
+
70
+ <div class="ocdi__file-upload-container">
71
+ <h2><?php esc_html_e( 'Manual demo files upload', 'pt-ocdi' ); ?></h2>
72
+
73
+ <div class="ocdi__file-upload">
74
+ <h3><label for="content-file-upload"><?php esc_html_e( 'Choose a XML file for content import:', 'pt-ocdi' ); ?></label></h3>
75
+ <input id="ocdi__content-file-upload" type="file" name="content-file-upload">
76
+ </div>
77
+
78
+ <div class="ocdi__file-upload">
79
+ <h3><label for="widget-file-upload"><?php esc_html_e( 'Choose a WIE or JSON file for widget import:', 'pt-ocdi' ); ?></label> <span><?php esc_html_e( '(*optional)', 'pt-ocdi' ); ?></span></h3>
80
+ <input id="ocdi__widget-file-upload" type="file" name="widget-file-upload">
81
+ </div>
82
+
83
+ <div class="ocdi__file-upload">
84
+ <h3><label for="customizer-file-upload"><?php esc_html_e( 'Choose a DAT file for customizer import:', 'pt-ocdi' ); ?></label> <span><?php esc_html_e( '(*optional)', 'pt-ocdi' ); ?></span></h3>
85
+ <input id="ocdi__customizer-file-upload" type="file" name="customizer-file-upload">
86
+ </div>
87
+
88
+ <?php if ( class_exists( 'ReduxFramework' ) ) : ?>
89
+ <div class="ocdi__file-upload">
90
+ <h3><label for="redux-file-upload"><?php esc_html_e( 'Choose a JSON file for Redux import:', 'pt-ocdi' ); ?></label> <span><?php esc_html_e( '(*optional)', 'pt-ocdi' ); ?></span></h3>
91
+ <input id="ocdi__redux-file-upload" type="file" name="redux-file-upload">
92
+ <div>
93
+ <label for="redux-option-name" class="ocdi__redux-option-name-label"><?php esc_html_e( 'Enter the Redux option name:', 'pt-ocdi' ); ?></label>
94
+ <input id="ocdi__redux-option-name" type="text" name="redux-option-name">
95
+ </div>
96
+ </div>
97
+ <?php endif; ?>
98
+ </div>
99
+
100
+ <p class="ocdi__button-container">
101
+ <button class="ocdi__button button button-hero button-primary js-ocdi-import-data"><?php esc_html_e( 'Import Demo Data', 'pt-ocdi' ); ?></button>
102
+ </p>
103
+
104
+ <?php elseif ( 1 === count( $this->import_files ) ) : ?>
105
+
106
+ <div class="ocdi__demo-import-notice js-ocdi-demo-import-notice"><?php
107
+ if ( is_array( $this->import_files ) && ! empty( $this->import_files[0]['import_notice'] ) ) {
108
+ echo wp_kses_post( $this->import_files[0]['import_notice'] );
109
+ }
110
+ ?></div>
111
+
112
+ <p class="ocdi__button-container">
113
+ <button class="ocdi__button button button-hero button-primary js-ocdi-import-data"><?php esc_html_e( 'Import Demo Data', 'pt-ocdi' ); ?></button>
114
+ </p>
115
+
116
+ <?php else : ?>
117
+
118
+ <!-- OCDI grid layout -->
119
+ <div class="ocdi__gl js-ocdi-gl">
120
+ <?php
121
+ // Prepare navigation data.
122
+ $categories = Helpers::get_all_demo_import_categories( $this->import_files );
123
+ ?>
124
+ <?php if ( ! empty( $categories ) ) : ?>
125
+ <div class="ocdi__gl-header js-ocdi-gl-header">
126
+ <nav class="ocdi__gl-navigation">
127
+ <ul>
128
+ <li class="active"><a href="#all" class="ocdi__gl-navigation-link js-ocdi-nav-link"><?php esc_html_e( 'All', 'pt-ocdi' ); ?></a></li>
129
+ <?php foreach ( $categories as $key => $name ) : ?>
130
+ <li><a href="#<?php echo esc_attr( $key ); ?>" class="ocdi__gl-navigation-link js-ocdi-nav-link"><?php echo esc_html( $name ); ?></a></li>
131
+ <?php endforeach; ?>
132
+ </ul>
133
+ </nav>
134
+ <div clas="ocdi__gl-search">
135
+ <input type="search" class="ocdi__gl-search-input js-ocdi-gl-search" name="ocdi-gl-search" value="" placeholder="<?php esc_html_e( 'Search demos...', 'pt-ocdi' ); ?>">
136
+ </div>
137
+ </div>
138
+ <?php endif; ?>
139
+ <div class="ocdi__gl-item-container wp-clearfix js-ocdi-gl-item-container">
140
+ <?php foreach ( $this->import_files as $index => $import_file ) : ?>
141
+ <?php
142
+ // Prepare import item display data.
143
+ $img_src = isset( $import_file['import_preview_image_url'] ) ? $import_file['import_preview_image_url'] : '';
144
+ // Default to the theme screenshot, if a custom preview image is not defined.
145
+ if ( empty( $img_src ) ) {
146
+ $theme = wp_get_theme();
147
+ $img_src = $theme->get_screenshot();
148
+ }
149
+
150
+ ?>
151
+ <div class="ocdi__gl-item js-ocdi-gl-item" data-categories="<?php echo esc_attr( Helpers::get_demo_import_item_categories( $import_file ) ); ?>" data-name="<?php echo esc_attr( strtolower( $import_file['import_file_name'] ) ); ?>">
152
+ <div class="ocdi__gl-item-image-container">
153
+ <?php if ( ! empty( $img_src ) ) : ?>
154
+ <img class="ocdi__gl-item-image" src="<?php echo esc_url( $img_src ) ?>">
155
+ <?php else : ?>
156
+ <div class="ocdi__gl-item-image ocdi__gl-item-image--no-image"><?php esc_html_e( 'No preview image.', 'pt-ocdi' ); ?></div>
157
+ <?php endif; ?>
158
+ </div>
159
+ <div class="ocdi__gl-item-footer">
160
+ <h4 class="ocdi__gl-item-title"><?php echo esc_html( $import_file['import_file_name'] ); ?></h4>
161
+ <button class="ocdi__gl-item-button button button-primary js-ocdi-gl-import-data" value="<?php echo esc_attr( $index ); ?>"><?php esc_html_e( 'Import', 'pt-ocdi' ); ?></button>
162
+ </div>
163
+ </div>
164
+ <?php endforeach; ?>
165
+ </div>
166
+ </div>
167
+
168
+ <div id="js-ocdi-modal-content"></div>
169
+
170
+ <?php endif; ?>
171
+
172
+ <p class="ocdi__ajax-loader js-ocdi-ajax-loader">
173
+ <span class="spinner"></span> <?php esc_html_e( 'Importing, please wait!', 'pt-ocdi' ); ?>
174
+ </p>
175
+
176
+ <div class="ocdi__response js-ocdi-ajax-response"></div>
177
+ </div>