PK G\0Q Q
readme.txtnu W+A === One Click Demo Import ===
Contributors: capuderg, cyman, Prelc
Tags: import, content, demo, data, widgets, settings, redux, theme options
Requires at least: 4.0.0
Tested up to: 4.7
Stable tag: 2.2.1
License: GPLv3 or later
Import your demo content, widgets and theme settings with one click. Theme authors! Enable simple demo import for your theme demo data.
== Description ==
The best feature of this plugin is, that theme authors can define import files in their themes and so all you (the user of the theme) have to do is click on the "Import Demo Data" button.
> **Are you a theme author?**
>
> Setup One Click Demo Imports for your theme and your users will thank you for it!
>
> [Follow this easy guide on how to setup this plugin for your themes!](http://proteusthemes.github.io/one-click-demo-import/)
>
> Also [sign up to the newsletter](http://proteusthemes.github.io/one-click-demo-import/#ocdi-newsletter-signup), so we can inform you about any updates, changes or improvements.
> **Are you a theme user?**
>
> Contact the author of your theme and [let them know about this plugin](http://proteusthemes.github.io/one-click-demo-import/theme-users.html). Theme authors can make any theme compatible with this plugin in 15 minutes and make it much more user-friendly.
>
> "[Where can I find the contact of the theme author?](http://proteusthemes.github.io/one-click-demo-import/theme-users.html)"
This plugin will create a submenu page under Appearance with the title **Import demo data**.
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.
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.
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.
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.
**Do you want to contribute?**
Please refer to the official [GitHub repository](https://github.com/proteusthemes/one-click-demo-import) of this plugin.
== Installation ==
**From your WordPress dashboard**
1. Visit 'Plugins > Add New',
2. Search for 'One Click Demo Import' and install the plugin,
3. Activate 'One Click Demo Import' from your Plugins page.
**From WordPress.org**
1. Download 'One Click Demo Import'.
2. Upload the 'one-click-demo-import' directory to your '/wp-content/plugins/' directory, using your favorite method (ftp, sftp, scp, etc...)
3. Activate 'One Click Demo Import' from your Plugins page.
**Once the plugin is activated you will find the actual import page in: Appearance -> Import Demo Data.**
== Frequently Asked Questions ==
= I have activated the plugin. Where is the "Import Demo Data" page? =
You will find the import page in *wp-admin -> Appearance -> Import Demo Data*.
= Where are the demo import files and the log files saved? =
The files used in the demo import will be saved to the default WordPress uploads directory. An example of that directory would be: `../wp-content/uploads/2016/03/`.
The log file will also be registered in the *wp-admin -> Media* section, so you can access it easily.
= How to predefine demo imports? =
This question is for theme authors. To predefine demo imports, you just have to add the following code structure, with your own values to your theme (using the `pt-ocdi/import_files` filter):
`
function ocdi_import_files() {
return array(
array(
'import_file_name' => 'Demo Import 1',
'categories' => array( 'Category 1', 'Category 2' ),
'import_file_url' => 'http://www.your_domain.com/ocdi/demo-content.xml',
'import_widget_file_url' => 'http://www.your_domain.com/ocdi/widgets.json',
'import_customizer_file_url' => 'http://www.your_domain.com/ocdi/customizer.dat',
'import_redux' => array(
array(
'file_url' => 'http://www.your_domain.com/ocdi/redux.json',
'option_name' => 'redux_option_name',
),
),
'import_preview_image_url' => 'http://www.your_domain.com/ocdi/preview_import_image1.jpg',
'import_notice' => __( 'After you import this demo, you will have to setup the slider separately.', 'your-textdomain' ),
),
array(
'import_file_name' => 'Demo Import 2',
'categories' => array( 'New category', 'Old category' ),
'import_file_url' => 'http://www.your_domain.com/ocdi/demo-content2.xml',
'import_widget_file_url' => 'http://www.your_domain.com/ocdi/widgets2.json',
'import_customizer_file_url' => 'http://www.your_domain.com/ocdi/customizer2.dat',
'import_redux' => array(
array(
'file_url' => 'http://www.your_domain.com/ocdi/redux.json',
'option_name' => 'redux_option_name',
),
array(
'file_url' => 'http://www.your_domain.com/ocdi/redux2.json',
'option_name' => 'redux_option_name_2',
),
),
'import_preview_image_url' => 'http://www.your_domain.com/ocdi/preview_import_image2.jpg',
'import_notice' => __( 'A special note for this import.', 'your-textdomain' ),
),
);
}
add_filter( 'pt-ocdi/import_files', 'ocdi_import_files' );
`
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.
= How to automatically assign "Front page", "Posts page" and menu locations after the importer is done? =
You can do that, with the `pt-ocdi/after_import` action hook. The code would look something like this:
`
function ocdi_after_import_setup() {
// Assign menus to their locations.
$main_menu = get_term_by( 'name', 'Main Menu', 'nav_menu' );
set_theme_mod( 'nav_menu_locations', array(
'main-menu' => $main_menu->term_id,
)
);
// Assign front page and posts page (blog page).
$front_page_id = get_page_by_title( 'Home' );
$blog_page_id = get_page_by_title( 'Blog' );
update_option( 'show_on_front', 'page' );
update_option( 'page_on_front', $front_page_id->ID );
update_option( 'page_for_posts', $blog_page_id->ID );
}
add_action( 'pt-ocdi/after_import', 'ocdi_after_import_setup' );
`
= What about using local import files (from theme folder)? =
You have to use the same filter as in above example, but with a slightly different array keys: `local_*`. The values have to be absolute paths (not URLs) to your import files. To use local import files, that reside in your theme folder, please use the below code. Note: make sure your import files are readable!
`
function ocdi_import_files() {
return array(
array(
'import_file_name' => 'Demo Import 1',
'categories' => array( 'Category 1', 'Category 2' ),
'local_import_file' => trailingslashit( get_template_directory() ) . 'ocdi/demo-content.xml',
'local_import_widget_file' => trailingslashit( get_template_directory() ) . 'ocdi/widgets.json',
'local_import_customizer_file' => trailingslashit( get_template_directory() ) . 'ocdi/customizer.dat',
'local_import_redux' => array(
array(
'file_path' => trailingslashit( get_template_directory() ) . 'ocdi/redux.json',
'option_name' => 'redux_option_name',
),
),
'import_preview_image_url' => 'http://www.your_domain.com/ocdi/preview_import_image1.jpg',
'import_notice' => __( 'After you import this demo, you will have to setup the slider separately.', 'your-textdomain' ),
),
array(
'import_file_name' => 'Demo Import 2',
'categories' => array( 'New category', 'Old category' ),
'local_import_file' => trailingslashit( get_template_directory() ) . 'ocdi/demo-content2.xml',
'local_import_widget_file' => trailingslashit( get_template_directory() ) . 'ocdi/widgets2.json',
'local_import_customizer_file' => trailingslashit( get_template_directory() ) . 'ocdi/customizer2.dat',
'local_import_redux' => array(
array(
'file_path' => trailingslashit( get_template_directory() ) . 'ocdi/redux.json',
'option_name' => 'redux_option_name',
),
array(
'file_path' => trailingslashit( get_template_directory() ) . 'ocdi/redux2.json',
'option_name' => 'redux_option_name_2',
),
),
'import_preview_image_url' => 'http://www.your_domain.com/ocdi/preview_import_image2.jpg',
'import_notice' => __( 'A special note for this import.', 'your-textdomain' ),
),
);
}
add_filter( 'pt-ocdi/import_files', 'ocdi_import_files' );
`
= How to handle different "after import setups" depending on which predefined import was selected? =
This question might be asked by a theme author wanting to implement different after import setups for multiple predefined demo imports. Lets say we have predefined two demo imports with the following names: 'Demo Import 1' and 'Demo Import 2', the code for after import setup would be (using the `pt-ocdi/after_import` filter):
`
function ocdi_after_import( $selected_import ) {
echo "This will be displayed on all after imports!";
if ( 'Demo Import 1' === $selected_import['import_file_name'] ) {
echo "This will be displayed only on after import if user selects Demo Import 1";
// Set logo in customizer
set_theme_mod( 'logo_img', get_template_directory_uri() . '/assets/images/logo1.png' );
}
elseif ( 'Demo Import 2' === $selected_import['import_file_name'] ) {
echo "This will be displayed only on after import if user selects Demo Import 2";
// Set logo in customizer
set_theme_mod( 'logo_img', get_template_directory_uri() . '/assets/images/logo2.png' );
}
}
add_action( 'pt-ocdi/after_import', 'ocdi_after_import' );
`
= Can I add some code before the widgets get imported? =
Of course you can, use the `pt-ocdi/before_widgets_import` action. You can also target different predefined demo imports like in the example above. Here is a simple example code of the `pt-ocdi/before_widgets_import` action:
`
function ocdi_before_widgets_import( $selected_import ) {
echo "Add your code here that will be executed before the widgets get imported!";
}
add_action( 'pt-ocdi/before_widgets_import', 'ocdi_before_widgets_import' );
`
= I'm a theme author and I want to change the plugin intro text, how can I do that? =
You can change the plugin intro text by using the `pt-ocdi/plugin_intro_text` filter:
`
function ocdi_plugin_intro_text( $default_text ) {
$default_text .= '
This is a custom text added to this plugin intro text.
';
return $default_text;
}
add_filter( 'pt-ocdi/plugin_intro_text', 'ocdi_plugin_intro_text' );
`
To add some text in a separate "box", you should wrap your text in a div with a class of 'ocdi__intro-text', like in the code example above.
= How to disable generation of smaller images (thumbnails) during the content import =
This will greatly improve the time needed to import the content (images), but only the original sized images will be imported. You can disable it with a filter, so just add this code to your theme function.php file:
`add_filter( 'pt-ocdi/regenerate_thumbnails_in_content_import', '__return_false' );`
= How to change the location, title and other parameters of the plugin page? =
As a theme author you do not like the location of the "Import Demo Data" plugin page in *Appearance -> Import Demo Data*? You can change that with the filter below. Apart from the location, you can also change the title or the page/menu and some other parameters as well.
`
function ocdi_plugin_page_setup( $default_settings ) {
$default_settings['parent_slug'] = 'themes.php';
$default_settings['page_title'] = esc_html__( 'One Click Demo Import' , 'pt-ocdi' );
$default_settings['menu_title'] = esc_html__( 'Import Demo Data' , 'pt-ocdi' );
$default_settings['capability'] = 'import';
$default_settings['menu_slug'] = 'pt-one-click-demo-import';
return $default_settings;
}
add_filter( 'pt-ocdi/plugin_page_setup', 'ocdi_plugin_page_setup' );
`
= How to do something before the content import executes? =
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:
`
function ocdi_before_content_import( $selected_import ) {
if ( 'Demo Import 1' === $selected_import['import_file_name'] ) {
// Here you can do stuff for the "Demo Import 1" before the content import starts.
echo "before import 1";
}
else {
// Here you can do stuff for all other imports before the content import starts.
echo "before import 2";
}
}
add_action( 'pt-ocdi/before_content_import', 'ocdi_before_content_import' );
`
= How can I enable the `customize_save*` wp action hooks in the customizer import? =
It's easy, just add this to your theme:
`add_action( 'pt-ocdi/enable_wp_customize_save_hooks', '__return_true' );`
This will enable the following WP hooks when importing the customizer data: `customize_save`, `customize_save_*`, `customize_save_after`.
= How to configure the multi grid layout import popup confirmation? =
If you want to disable the popup confirmation modal window, use this filter:
`add_filter( 'pt-ocdi/enable_grid_layout_import_popup_confirmation', '__return_false' );`
If you want to just change some options for the jQuery modal window we use for the popup confirmation, then use this filter:
`
function my_theme_ocdi_confirmation_dialog_options ( $options ) {
return array_merge( $options, array(
'width' => 300,
'dialogClass' => 'wp-dialog',
'resizable' => false,
'height' => 'auto',
'modal' => true,
) );
}
add_filter( 'pt-ocdi/confirmation_dialog_options', 'my_theme_ocdi_confirmation_dialog_options', 10, 1 );
`
= How can I disable the ProteusThemes branding notice after successful demo import? =
You can disable the branding notice with a WP filter. All you need to do is add this bit of code to your theme:
`add_filter( 'pt-ocdi/disable_pt_branding', '__return_true' );`
and the notice will not be displayed.
= I can't activate the plugin, because of a fatal error, what can I do? =
*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.*
You want to activate the plugin, but this error shows up:
*Plugin could not be activated because it triggered a fatal error*
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.
= Issues with the import, that we can't fix in the plugin =
Please visit this [docs page](https://github.com/proteusthemes/one-click-demo-import/blob/master/docs/import-problems.md), for more answers to issues with importing data.
== Screenshots ==
1. Example of multiple predefined demo imports, that a user can choose from.
2. How the import page looks like, when only one demo import is predefined.
3. Example of how the import page looks like, when no demo imports are predefined a.k.a manual import.
== Changelog ==
= 2.2.1 =
*Release Date - 3 April 2017*
* Fix image importing error for server compressed files,
* Fix remapping of featured images,
* Fix custom post type existing posts check (no more multiple imports for custom post types).
= 2.2.0 =
*Release Date - 5 February 2017*
* Add ProteusThemes branding notice after successful import,
* Fix after import error reporting (duplicate errors were shown),
* Fix some undefined variables in the plugin, causing PHP notices.
= 2.1.0 =
*Release Date - 8 January 2017*
* Add grid layout import confirmation popup options filter,
* Fix term meta data double import,
* Fix WooCommerce product attributes import.
= 2.0.2 =
*Release Date - 13 December 2016*
* Fix issue with customizer options import
= 2.0.1 =
*Release Date - 12 December 2016*
* Fix issue with some browsers (Safari and IE) not supporting some FormData methods.
= 2.0.0 =
*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).
= 1.4.0 =
*Release Date - 29 October 2016*
* Add support for WP term meta data in content importer,
* Fix the issue of having both plugins (OCDI and the new WP importer v2) activated at the same time.
= 1.3.0 =
*Release Date - 1 October 2016*
* Import/plugin page re-design. Updated the plugin page styles to match WordPress (thanks to Oliver Juhas).
= 1.2.0 =
*Release Date - 9 July 2016*
* Now also accepts predefined local import files (from theme folder),
* Fixes PHP fatal error on plugin activation, for sites using PHP versions older then 5.3.2 (added admin error notice),
* Register log file in *wp-admin -> Media*, so that it's easier to access,
* No more "[WARNING] Could not find the author for ..." messages in the log file.
= 1.1.3 =
*Release Date - 17 June 2016*
* Updated plugin design,
* Changed the plugin page setup filter name from `pt-ocdi/plugin-page-setup` to `pt-ocdi/plugin_page_setup` (mind the underscore characters instead of dashes).
= 1.1.2 =
*Release Date - 12 June 2016*
* An 'import notice' field has been added to the predefined demo import settings. This notice is displayed above the import button (it also accepts HTML),
* Now displays proper error message, if the file-system method is not set to "direct",
* This plugin is now compatible with the new [Humanmade content importer plugin](https://github.com/humanmade/WordPress-Importer),
* Added a filter to the plugin page creation, so that theme authors can now change the location of the plugin page (Demo data import) and some other parameters as well.
= 1.1.1 =
*Release Date - 22 May 2016*
* Preview import images can now be defined for multiple predefined import files (check FAQ "How to predefine demo imports?" for more info),
* You can now also import customizer settings.
= 1.1.0 =
*Release Date - 14 May 2016*
* Content import now imports in multiple AJAX calls, so there should be no more server timeout errors,
* The setting for generation of multiple image sizes in the content import is again enabled by default,
* Plugin textdomain was loaded, so that translations can be made.
= 1.0.3 =
*Release Date - 27 April 2016*
* Added filter to enable image regeneration,
* Added filter to change the plugin intro text,
* Added action to execute custom code before widget import,
* Disabled author imports.
= 1.0.2 =
*Release Date - 15 April 2016*
* Monkey fix for WP version 4.5. - disabled generation of multiple image sizes in the content import.
= 1.0.1 =
*Release Date - 2 April 2016*
Small code fixes:
* Fixed undefined variable bug,
* Fixed naming of downloaded files and their filters.
= 1.0.0 =
*Release Date - 25 March 2016*
* Initial release!
PK G\Խ% % assets/js/main.jsnu W+A jQuery( function ( $ ) {
'use strict';
/**
* ---------------------------------------
* ------------- Events ------------------
* ---------------------------------------
*/
/**
* No or Single predefined demo import button click.
*/
$( '.js-ocdi-import-data' ).on( 'click', function () {
// Reset response div content.
$( '.js-ocdi-ajax-response' ).empty();
// Prepare data for the AJAX call
var data = new FormData();
data.append( 'action', 'ocdi_import_demo_data' );
data.append( 'security', ocdi.ajax_nonce );
data.append( 'selected', $( '#ocdi__demo-import-files' ).val() );
if ( $('#ocdi__content-file-upload').length ) {
data.append( 'content_file', $('#ocdi__content-file-upload')[0].files[0] );
}
if ( $('#ocdi__widget-file-upload').length ) {
data.append( 'widget_file', $('#ocdi__widget-file-upload')[0].files[0] );
}
if ( $('#ocdi__customizer-file-upload').length ) {
data.append( 'customizer_file', $('#ocdi__customizer-file-upload')[0].files[0] );
}
if ( $('#ocdi__redux-file-upload').length ) {
data.append( 'redux_file', $('#ocdi__redux-file-upload')[0].files[0] );
data.append( 'redux_option_name', $('#ocdi__redux-option-name').val() );
}
// AJAX call to import everything (content, widgets, before/after setup)
ajaxCall( data );
});
/**
* Grid Layout import button click.
*/
$( '.js-ocdi-gl-import-data' ).on( 'click', function () {
var selectedImportID = $( this ).val();
var $itemContainer = $( this ).closest( '.js-ocdi-gl-item' );
// If the import confirmation is enabled, then do that, else import straight away.
if ( ocdi.import_popup ) {
displayConfirmationPopup( selectedImportID, $itemContainer );
}
else {
gridLayoutImport( selectedImportID, $itemContainer );
}
});
/**
* Grid Layout categories navigation.
*/
(function () {
// Cache selector to all items
var $items = $( '.js-ocdi-gl-item-container' ).find( '.js-ocdi-gl-item' ),
fadeoutClass = 'ocdi-is-fadeout',
fadeinClass = 'ocdi-is-fadein',
animationDuration = 200;
// Hide all items.
var fadeOut = function () {
var dfd = jQuery.Deferred();
$items
.addClass( fadeoutClass );
setTimeout( function() {
$items
.removeClass( fadeoutClass )
.hide();
dfd.resolve();
}, animationDuration );
return dfd.promise();
};
var fadeIn = function ( category, dfd ) {
var filter = category ? '[data-categories*="' + category + '"]' : 'div';
if ( 'all' === category ) {
filter = 'div';
}
$items
.filter( filter )
.show()
.addClass( 'ocdi-is-fadein' );
setTimeout( function() {
$items
.removeClass( fadeinClass );
dfd.resolve();
}, animationDuration );
};
var animate = function ( category ) {
var dfd = jQuery.Deferred();
var promise = fadeOut();
promise.done( function () {
fadeIn( category, dfd );
} );
return dfd;
};
$( '.js-ocdi-nav-link' ).on( 'click', function( event ) {
event.preventDefault();
// Remove 'active' class from the previous nav list items.
$( this ).parent().siblings().removeClass( 'active' );
// Add the 'active' class to this nav list item.
$( this ).parent().addClass( 'active' );
var category = this.hash.slice(1);
// show/hide the right items, based on category selected
var $container = $( '.js-ocdi-gl-item-container' );
$container.css( 'min-width', $container.outerHeight() );
var promise = animate( category );
promise.done( function () {
$container.removeAttr( 'style' );
} );
} );
}());
/**
* Grid Layout search functionality.
*/
$( '.js-ocdi-gl-search' ).on( 'keyup', function( event ) {
if ( 0 < $(this).val().length ) {
// Hide all items.
$( '.js-ocdi-gl-item-container' ).find( '.js-ocdi-gl-item' ).hide();
// Show just the ones that have a match on the import name.
$( '.js-ocdi-gl-item-container' ).find( '.js-ocdi-gl-item[data-name*="' + $(this).val().toLowerCase() + '"]' ).show();
}
else {
$( '.js-ocdi-gl-item-container' ).find( '.js-ocdi-gl-item' ).show();
}
} );
/**
* ---------------------------------------
* --------Helper functions --------------
* ---------------------------------------
*/
/**
* Prepare grid layout import data and execute the AJAX call.
*
* @param int selectedImportID The selected import ID.
* @param obj $itemContainer The jQuery selected item container object.
*/
function gridLayoutImport( selectedImportID, $itemContainer ) {
// Reset response div content.
$( '.js-ocdi-ajax-response' ).empty();
// Hide all other import items.
$itemContainer.siblings( '.js-ocdi-gl-item' ).fadeOut( 500 );
$itemContainer.animate({
opacity: 0
}, 500, 'swing', function () {
$itemContainer.animate({
opacity: 1
}, 500 )
});
// Hide the header with category navigation and search box.
$itemContainer.closest( '.js-ocdi-gl' ).find( '.js-ocdi-gl-header' ).fadeOut( 500 );
// Append a title for the selected demo import.
$itemContainer.parent().prepend( '
' + ocdi.texts.selected_import_title + '
' );
// Remove the import button of the selected item.
$itemContainer.find( '.js-ocdi-gl-import-data' ).remove();
// Prepare data for the AJAX call
var data = new FormData();
data.append( 'action', 'ocdi_import_demo_data' );
data.append( 'security', ocdi.ajax_nonce );
data.append( 'selected', selectedImportID );
// AJAX call to import everything (content, widgets, before/after setup)
ajaxCall( data );
}
/**
* Display the confirmation popup.
*
* @param int selectedImportID The selected import ID.
* @param obj $itemContainer The jQuery selected item container object.
*/
function displayConfirmationPopup( selectedImportID, $itemContainer ) {
var $dialogContiner = $( '#js-ocdi-modal-content' );
var currentFilePreviewImage = ocdi.import_files[ selectedImportID ]['import_preview_image_url'] || ocdi.theme_screenshot;
var previewImageContent = '';
var importNotice = ocdi.import_files[ selectedImportID ]['import_notice'] || '';
var importNoticeContent = '';
var dialogOptions = $.extend(
{
'dialogClass': 'wp-dialog',
'resizable': false,
'height': 'auto',
'modal': true
},
ocdi.dialog_options,
{
'buttons':
[
{
text: ocdi.texts.dialog_no,
click: function() {
$(this).dialog('close');
}
},
{
text: ocdi.texts.dialog_yes,
class: 'button button-primary',
click: function() {
$(this).dialog('close');
gridLayoutImport( selectedImportID, $itemContainer );
}
}
]
});
if ( '' === currentFilePreviewImage ) {
previewImageContent = '
' +
previewImageContent +
importNoticeContent
);
// Display the confirmation popup.
$dialogContiner.dialog( dialogOptions );
}
/**
* The main AJAX call, which executes the import process.
*
* @param FormData data The data to be passed to the AJAX call.
*/
function ajaxCall( data ) {
$.ajax({
method: 'POST',
url: ocdi.ajax_url,
data: data,
contentType: false,
processData: false,
beforeSend: function() {
$( '.js-ocdi-ajax-loader' ).show();
}
})
.done( function( response ) {
if ( 'undefined' !== typeof response.status && 'newAJAX' === response.status ) {
ajaxCall( data );
}
else if ( 'undefined' !== typeof response.status && 'customizerAJAX' === response.status ) {
// Fix for data.set and data.delete, which they are not supported in some browsers.
var newData = new FormData();
newData.append( 'action', 'ocdi_import_customizer_data' );
newData.append( 'security', ocdi.ajax_nonce );
// Set the wp_customize=on only if the plugin filter is set to true.
if ( true === ocdi.wp_customize_on ) {
newData.append( 'wp_customize', 'on' );
}
ajaxCall( newData );
}
else if ( 'undefined' !== typeof response.status && 'afterAllImportAJAX' === response.status ) {
// Fix for data.set and data.delete, which they are not supported in some browsers.
var newData = new FormData();
newData.append( 'action', 'ocdi_after_import_data' );
newData.append( 'security', ocdi.ajax_nonce );
ajaxCall( newData );
}
else if ( 'undefined' !== typeof response.message ) {
$( '.js-ocdi-ajax-response' ).append( '
' );
$( '.js-ocdi-ajax-loader' ).hide();
});
}
} );
PK G\/IM M assets/css/main.cssnu W+A /* Overriding WordPress native styles */
.ocdi {
max-width: none;
}
.ocdi h2 {
text-align: inherit;
}
.ocdi h2:first-child,
.ocdi h3:first-child {
margin-top: 0;
}
.ocdi hr {
margin: 2.62em 0;
}
.feature-section + hr {
margin-top: 0;
}
#wpbody select {
height: auto;
padding: .62em;
line-height: inherit;
}
.ocdi .notice {
display: block !important;
}
/* Plugin elements */
.ocdi__demo-import-files {
width: 100%;
}
.ocdi__demo-import-preview-image-message {
font-style: italic;
}
/* Plugin title */
.ocdi__title:before {
width: auto;
height: auto;
font-size: inherit;
}
/* Plugin intro text */
.ocdi__intro-text ul {
padding: 0 4%;
list-style-type: square;
}
/* Plugin multi select import and Plugin file upload containers */
.ocdi__file-upload,
.ocdi__multi-select-import,
.ocdi__demo-import-notice:not(:empty) {
padding: 4%;
margin: 1.62em 0;
background-color: #ffffff;
border: 1px solid #e5e5e5;
}
.ocdi__file-upload {
margin: 0;
margin-bottom: -1px;
}
.ocdi__file-upload span {
font-size: .81em;
font-weight: normal;
opacity: .66;
}
.ocdi__demo-import-notice:not(:empty) {
border: 0;
border-left: 4px solid #00a0d2;
-webkit-box-shadow: 0 1px 1px 0 rgba(0,0,0,.1);
box-shadow: 0 1px 1px 0 rgba(0,0,0,.1);
}
[dir="rtl"] .ocdi__demo-import-notice:not(:empty) {
border: 0;
border-right: 4px solid #00a0d2;
}
/* Plugin button */
.ocdi__button-container {
margin-top: 1.62em;
}
/* AJAX loader */
p.ocdi__ajax-loader {
font-size: 1.5em;
display: none;
}
.ocdi__ajax-loader .spinner {
display: inline-block;
float: none;
visibility: visible;
margin-bottom: 6px;
}
/* New grid layout */
.ocdi__gl-navigation li a {
-webkit-box-shadow: none;
box-shadow: none;
}
.ocdi__gl-item {
float: left;
width: 100%;
margin: 0 0 20px 0;
position: relative;
border: 1px solid #ddd;
-webkit-box-shadow: 0 1px 1px -1px rgba(0,0,0,0.1);
box-shadow: 0 1px 1px -1px rgba(0,0,0,0.1);
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.ocdi__gl-item-image-container {
display: block;
overflow: hidden;
position: relative;
-webkit-backface-visibility: hidden;
-webkit-transition: opacity 0.2s ease-in-out;
transition: opacity 0.2s ease-in-out;
}
.ocdi__gl-item-image-container::after {
content: "";
display: block;
padding-top: 66.66666%;
}
.ocdi__gl-item-image {
height: auto;
position: absolute;
left: 0;
top: 0;
width: 100%;
-webkit-transition: opacity 0.2s ease-in-out;
transition: opacity 0.2s ease-in-out;
}
.ocdi__gl-item-image--no-image {
display: inline-block;
width: 50%;
text-align: center;
position: absolute;
top: 45%;
right: 25%;
left: 25%;
}
.ocdi__gl-item-footer {
height: 30px;
margin: 0;
padding: 10px;
-webkit-box-shadow: inset 0 1px 0 rgba(0,0,0,0.1);
box-shadow: inset 0 1px 0 rgba(0,0,0,0.1);
background: #ffffff;
background: rgba(255,255,255,0.65);
}
h4.ocdi__gl-item-title {
width: 70%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
display: inline-block;
margin: 6px 0 0 0;
}
.ocdi__gl-item-button {
float: right;
}
.ocdi__gl-header {
display: inline-block;
width: calc(100% - 40px);
background-color: #ffffff;
margin-bottom: 20px;
padding: 0 20px;
}
.ocdi__gl-navigation {
font-size: 13px;
width: 100%;
float: left;
}
.ocdi__gl-navigation ul {
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
}
.ocdi__gl-navigation li {
float: left;
margin: 0 15px;
}
.ocdi__gl-navigation li.active a,
.ocdi__gl-navigation li.active a:hover {
border-bottom: 4px solid #666666;
}
.ocdi__gl-navigation li a {
display: block;
text-align: center;
text-decoration: none;
color: #444444;
border-bottom: 4px solid #ffffff;
padding: 15px 0;
}
.ocdi__gl-navigation li a:hover {
color: #00a0d2;
border-bottom: 4px solid #ffffff;
cursor:pointer;
}
.ocdi__gl-search-input {
width: 100%;
margin: 10px 0;
}
@media (min-width: 640px) {
.ocdi__gl-navigation {
width: calc(100% - 180px);
}
.ocdi__gl-navigation li {
margin: 0;
}
.ocdi__gl-navigation li a {
padding: 15px;
}
.ocdi__gl-search-input {
display: inline-block;
width: 180px;
height: 30px;
margin: 0;
margin-top: 11px;
}
.ocdi__gl-item-container {
margin-right: -20px;
}
.ocdi__gl-item {
width: calc(50% - 20px);
margin: 0 20px 20px 0;
}
}
@media (min-width: 1120px) {
.ocdi__gl-item-container {
margin-right: -30px;
}
.ocdi__gl-item {
width: calc(33.333% - 30px);
margin: 0 30px 30px 0;
}
}
/* Grid animations */
@keyframes ocdi-fade {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
.ocdi-is-fadeout {
animation: ocdi-fade linear 200ms 1 forwards;
}
.ocdi-is-fadein {
animation: ocdi-fade linear 200ms 1 reverse forwards;
}
/* Grid layout modal window */
.ocdi__modal-image-container {
width: 100%;
height: 180px;
margin: 0;
overflow: hidden;
}
.ocdi__modal-item-title {
margin-top: 0.5em;
font-weight: bold;
}
.ocdi__modal-image-container img {
width: 100%;
}
.ocdi__modal-notice.ocdi__demo-import-notice:not(:empty) {
border: 1px solid #e5e5e5;
border-left: 4px solid #00a0d2;
margin: 1em 0 0;
}
/* Redux */
.ocdi__redux-option-name-label {
margin-right: 5px;
}
PK G\gs.U .U inc/Helpers.phpnu W+A ',
$import_file_info['import_file_name'],
''
)
);
}
}
else {
// Set the filename string for content import file.
$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' );
// Download the content import file.
$downloaded_files['content'] = $downloader->download_file( $import_file_info['import_file_url'], $content_filename );
// Return from this function if there was an error.
if ( is_wp_error( $downloaded_files['content'] ) ) {
return $downloaded_files['content'];
}
}
// ----- Set widget file path -----
// Get widgets file as well. If defined!
if ( ! empty( $import_file_info['import_widget_file_url'] ) ) {
// Set the filename string for widgets import file.
$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' );
// Download the widgets import file.
$downloaded_files['widgets'] = $downloader->download_file( $import_file_info['import_widget_file_url'], $widget_filename );
// Return from this function if there was an error.
if ( is_wp_error( $downloaded_files['widgets'] ) ) {
return $downloaded_files['widgets'];
}
}
else if ( ! empty( $import_file_info['local_import_widget_file'] ) ) {
if ( file_exists( $import_file_info['local_import_widget_file'] ) ) {
$downloaded_files['widgets'] = $import_file_info['local_import_widget_file'];
}
}
// ----- Set customizer file path -----
// Get customizer import file as well. If defined!
if ( ! empty( $import_file_info['import_customizer_file_url'] ) ) {
// Setup filename path to save the customizer content.
$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' );
// Download the customizer import file.
$downloaded_files['customizer'] = $downloader->download_file( $import_file_info['import_customizer_file_url'], $customizer_filename );
// Return from this function if there was an error.
if ( is_wp_error( $downloaded_files['customizer'] ) ) {
return $downloaded_files['customizer'];
}
}
else if ( ! empty( $import_file_info['local_import_customizer_file'] ) ) {
if ( file_exists( $import_file_info['local_import_customizer_file'] ) ) {
$downloaded_files['customizer'] = $import_file_info['local_import_customizer_file'];
}
}
// ----- Set Redux file paths -----
// Get Redux import file as well. If defined!
if ( ! empty( $import_file_info['import_redux'] ) && is_array( $import_file_info['import_redux'] ) ) {
$redux_items = array();
// Setup filename paths to save the Redux content.
foreach ( $import_file_info['import_redux'] as $index => $redux_item ) {
$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' );
// Download the Redux import file.
$file_path = $downloader->download_file( $redux_item['file_url'], $redux_filename );
// Return from this function if there was an error.
if ( is_wp_error( $file_path ) ) {
return $file_path;
}
$redux_items[] = array(
'option_name' => $redux_item['option_name'],
'file_path' => $file_path,
);
}
// Download the Redux import file.
$downloaded_files['redux'] = $redux_items;
}
else if ( ! empty( $import_file_info['local_import_redux'] ) ) {
$redux_items = array();
// Setup filename paths to save the Redux content.
foreach ( $import_file_info['local_import_redux'] as $redux_item ) {
if ( file_exists( $redux_item['file_path'] ) ) {
$redux_items[] = $redux_item;
}
}
// Download the Redux import file.
$downloaded_files['redux'] = $redux_items;
}
return $downloaded_files;
}
/**
* Write content to a file.
*
* @param string $content content to be saved to the file.
* @param string $file_path file path where the content should be saved.
* @return string|WP_Error path to the saved file or WP_Error object with error message.
*/
public static function write_to_file( $content, $file_path ) {
// Verify WP file-system credentials.
$verified_credentials = self::check_wp_filesystem_credentials();
if ( is_wp_error( $verified_credentials ) ) {
return $verified_credentials;
}
// By this point, the $wp_filesystem global should be working, so let's use it to create a file.
global $wp_filesystem;
if ( ! $wp_filesystem->put_contents( $file_path, $content ) ) {
return new \WP_Error(
'failed_writing_file_to_server',
sprintf(
__( 'An error occurred while writing file to your server! Tried to write a file to: %s%s.', 'pt-ocdi' ),
' ',
$file_path
)
);
}
// Return the file path on successful file write.
return $file_path;
}
/**
* Append content to the file.
*
* @param string $content content to be saved to the file.
* @param string $file_path file path where the content should be saved.
* @param string $separator_text separates the existing content of the file with the new content.
* @return boolean|WP_Error, path to the saved file or WP_Error object with error message.
*/
public static function append_to_file( $content, $file_path, $separator_text = '' ) {
// Verify WP file-system credentials.
$verified_credentials = self::check_wp_filesystem_credentials();
if ( is_wp_error( $verified_credentials ) ) {
return $verified_credentials;
}
// By this point, the $wp_filesystem global should be working, so let's use it to create a file.
global $wp_filesystem;
$existing_data = '';
if ( file_exists( $file_path ) ) {
$existing_data = $wp_filesystem->get_contents( $file_path );
}
// Style separator.
$separator = PHP_EOL . '---' . $separator_text . '---' . PHP_EOL;
if ( ! $wp_filesystem->put_contents( $file_path, $existing_data . $separator . $content . PHP_EOL ) ) {
return new \WP_Error(
'failed_writing_file_to_server',
sprintf(
__( 'An error occurred while writing file to your server! Tried to write a file to: %s%s.', 'pt-ocdi' ),
' ',
$file_path
)
);
}
return true;
}
/**
* Get data from a file
*
* @param string $file_path file path where the content should be saved.
* @return string $data, content of the file or WP_Error object with error message.
*/
public static function data_from_file( $file_path ) {
// Verify WP file-system credentials.
$verified_credentials = self::check_wp_filesystem_credentials();
if ( is_wp_error( $verified_credentials ) ) {
return $verified_credentials;
}
// By this point, the $wp_filesystem global should be working, so let's use it to read a file.
global $wp_filesystem;
$data = $wp_filesystem->get_contents( $file_path );
if ( ! $data ) {
return new \WP_Error(
'failed_reading_file_from_server',
sprintf(
__( 'An error occurred while reading a file from your server! Tried reading file from path: %s%s.', 'pt-ocdi' ),
' ',
$file_path
)
);
}
// Return the file data.
return $data;
}
/**
* Helper function: check for WP file-system credentials needed for reading and writing to a file.
*
* @return boolean|WP_Error
*/
private static function check_wp_filesystem_credentials() {
// Check if the file-system method is 'direct', if not display an error.
if ( ! ( 'direct' === get_filesystem_method() ) ) {
return new \WP_Error(
'no_direct_file_access',
sprintf(
__( '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' ),
'',
'',
'How to set direct filesystem method'
)
);
}
// Get plugin page settings.
$plugin_page_setup = apply_filters( 'pt-ocdi/plugin_page_setup', array(
'parent_slug' => 'themes.php',
'page_title' => esc_html__( 'One Click Demo Import' , 'pt-ocdi' ),
'menu_title' => esc_html__( 'Import Demo Data' , 'pt-ocdi' ),
'capability' => 'import',
'menu_slug' => 'pt-one-click-demo-import',
)
);
// Get user credentials for WP file-system API.
$demo_import_page_url = wp_nonce_url( $plugin_page_setup['parent_slug'] . '?page=' . $plugin_page_setup['menu_slug'], $plugin_page_setup['menu_slug'] );
if ( false === ( $creds = request_filesystem_credentials( $demo_import_page_url, '', false, false, null ) ) ) {
return new \WP_error(
'filesystem_credentials_could_not_be_retrieved',
__( 'An error occurred while retrieving reading/writing permissions to your server (could not retrieve WP filesystem credentials)!', 'pt-ocdi' )
);
}
// Now we have credentials, try to get the wp_filesystem running.
if ( ! WP_Filesystem( $creds ) ) {
return new \WP_Error(
'wrong_login_credentials',
__( 'Your WordPress login credentials don\'t allow to use WP_Filesystem!', 'pt-ocdi' )
);
}
return true;
}
/**
* Get log file path
*
* @return string, path to the log file
*/
public static function get_log_path() {
$upload_dir = wp_upload_dir();
$upload_path = apply_filters( 'pt-ocdi/upload_file_path', trailingslashit( $upload_dir['path'] ) );
$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' );
self::register_file_as_media_attachment( $log_path );
return $log_path;
}
/**
* Register file as attachment to the Media page.
*
* @param string $log_path log file path.
* @return void
*/
public static function register_file_as_media_attachment( $log_path ) {
// Check the type of file.
$log_mimes = array( 'txt' => 'text/plain' );
$filetype = wp_check_filetype( basename( $log_path ), apply_filters( 'pt-ocdi/file_mimes', $log_mimes ) );
// Prepare an array of post data for the attachment.
$attachment = array(
'guid' => self::get_log_url( $log_path ),
'post_mime_type' => $filetype['type'],
'post_title' => apply_filters( 'pt-ocdi/attachment_prefix', esc_html__( 'One Click Demo Import - ', 'pt-ocdi' ) ) . preg_replace( '/\.[^.]+$/', '', basename( $log_path ) ),
'post_content' => '',
'post_status' => 'inherit',
);
// Insert the file as attachment in Media page.
$attach_id = wp_insert_attachment( $attachment, $log_path );
}
/**
* Get log file url
*
* @param string $log_path log path to use for the log filename.
* @return string, url to the log file.
*/
public static function get_log_url( $log_path ) {
$upload_dir = wp_upload_dir();
$upload_url = apply_filters( 'pt-ocdi/upload_file_url', trailingslashit( $upload_dir['url'] ) );
return $upload_url . basename( $log_path );
}
/**
* Check if the AJAX call is valid.
*/
public static function verify_ajax_call() {
check_ajax_referer( 'ocdi-ajax-verification', 'security' );
// Check if user has the WP capability to import data.
if ( ! current_user_can( 'import' ) ) {
wp_die(
sprintf(
__( '%sYour user role isn\'t high enough. You don\'t have permission to import demo data.%s', 'pt-ocdi' ),
'
',
'
'
)
);
}
}
/**
* Process uploaded files and return the paths to these files.
*
* @param array $uploaded_files $_FILES array form an AJAX request.
* @param string $log_file_path path to the log file.
* @return array of paths to the content import and widget import files.
*/
public static function process_uploaded_files( $uploaded_files, $log_file_path ) {
// Variable holding the paths to the uploaded files.
$selected_import_files = array();
// Upload settings to disable form and type testing for AJAX uploads.
$upload_overrides = array(
'test_form' => false,
'test_type' => false,
);
// Handle demo content and widgets file upload.
$content_file_info = wp_handle_upload( $_FILES['content_file'], $upload_overrides );
$widget_file_info = wp_handle_upload( $_FILES['widget_file'], $upload_overrides );
$customizer_file_info = wp_handle_upload( $_FILES['customizer_file'], $upload_overrides );
$redux_file_info = wp_handle_upload( $_FILES['redux_file'], $upload_overrides );
if ( empty( $content_file_info['file'] ) || isset( $content_file_info['error'] ) ) {
// Write error to log file and send an AJAX response with the error.
self::log_error_and_send_ajax_response(
__( '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' ),
$log_file_path,
esc_html__( 'Upload files', 'pt-ocdi' )
);
}
// Set uploaded content file.
$selected_import_files['content'] = $content_file_info['file'];
// Process widget import file.
if ( $widget_file_info && ! isset( $widget_file_info['error'] ) ) {
// Set uploaded widget file.
$selected_import_files['widgets'] = $widget_file_info['file'];
}
else {
// Add this error to log file.
$log_added = self::append_to_file(
sprintf(
__( 'Widget file was not uploaded. Error: %s', 'pt-ocdi' ),
$widget_file_info['error']
),
$log_file_path,
esc_html__( 'Upload files' , 'pt-ocdi' )
);
}
// Process Customizer import file.
if ( $customizer_file_info && ! isset( $customizer_file_info['error'] ) ) {
// Set uploaded customizer file.
$selected_import_files['customizer'] = $customizer_file_info['file'];
}
else {
// Add this error to log file.
$log_added = self::append_to_file(
sprintf(
__( 'Customizer file was not uploaded. Error: %s', 'pt-ocdi' ),
$customizer_file_info['error']
),
$log_file_path,
esc_html__( 'Upload files' , 'pt-ocdi' )
);
}
// Process Redux import file.
if ( $redux_file_info && ! isset( $redux_file_info['error'] ) ) {
if ( isset( $_POST['redux_option_name'] ) && empty( $_POST['redux_option_name'] ) ) {
// Write error to log file and send an AJAX response with the error.
self::log_error_and_send_ajax_response(
esc_html__( 'Missing Redux option name! Please also enter the Redux option name!', 'pt-ocdi' ),
$log_file_path,
esc_html__( 'Upload files', 'pt-ocdi' )
);
}
// Set uploaded Redux file.
$selected_import_files['redux'] = array(
array(
'option_name' => $_POST['redux_option_name'],
'file_path' => $redux_file_info['file'],
),
);
}
else {
// Add this error to log file.
$log_added = self::append_to_file(
sprintf(
__( 'Redux file was not uploaded. Error: %s', 'pt-ocdi' ),
$redux_file_info['error']
),
$log_file_path,
esc_html__( 'Upload files' , 'pt-ocdi' )
);
}
// Add this message to log file.
$log_added = self::append_to_file(
__( 'The import files were successfully uploaded!', 'pt-ocdi' ) . self::import_file_info( $selected_import_files ),
$log_file_path,
esc_html__( 'Upload files' , 'pt-ocdi' )
);
// Return array with paths of uploaded files.
return $selected_import_files;
}
/**
* Get import file information and max execution time.
*
* @param array $selected_import_files array of selected import files.
*/
public static function import_file_info( $selected_import_files ) {
$redux_file_string = '';
if ( ! empty( $selected_import_files['redux'] ) ) {
$redux_file_string = array_reduce( $selected_import_files['redux'], function( $string, $item ) {
return sprintf( '%1$s%2$s -> %3$s %4$s', $string, $item['option_name'], $item['file_path'], PHP_EOL );
}, '' );
}
return PHP_EOL .
sprintf(
__( 'Initial max execution time = %s', 'pt-ocdi' ),
ini_get( 'max_execution_time' )
) . PHP_EOL .
sprintf(
__( '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' ),
PHP_EOL,
get_site_url(),
$selected_import_files['content'],
empty( $selected_import_files['widgets'] ) ? esc_html__( 'not defined!', 'pt-ocdi' ) : $selected_import_files['widgets'],
empty( $selected_import_files['customizer'] ) ? esc_html__( 'not defined!', 'pt-ocdi' ) : $selected_import_files['customizer'],
empty( $redux_file_string ) ? esc_html__( 'not defined!', 'pt-ocdi' ) : $redux_file_string
);
}
/**
* Write the error to the log file and send the AJAX response.
*
* @param string $error_text text to display in the log file and in the AJAX response.
* @param string $log_file_path path to the log file.
* @param string $separator title separating the old and new content.
*/
public static function log_error_and_send_ajax_response( $error_text, $log_file_path, $separator = '' ) {
// Add this error to log file.
$log_added = self::append_to_file(
$error_text,
$log_file_path,
$separator
);
// Send JSON Error response to the AJAX call.
wp_send_json( $error_text );
}
/**
* Set the $demo_import_start_time class variable with the current date and time string.
*/
public static function set_demo_import_start_time() {
self::$demo_import_start_time = date( apply_filters( 'pt-ocdi/date_format_for_file_names', 'Y-m-d__H-i-s' ) );
}
/**
* Get the category list of all categories used in the predefined demo imports array.
*
* @param array $demo_imports Array of demo import items (arrays).
* @return array|boolean List of all the categories or false if there aren't any.
*/
public static function get_all_demo_import_categories( $demo_imports ) {
$categories = array();
foreach ( $demo_imports as $item ) {
if ( ! empty( $item['categories'] ) && is_array( $item['categories'] ) ) {
foreach ( $item['categories'] as $category ) {
$categories[ sanitize_key( $category ) ] = $category;
}
}
}
if ( empty( $categories ) ) {
return false;
}
return $categories;
}
/**
* Return the concatenated string of demo import item categories.
* These should be separated by comma and sanitized properly.
*
* @param array $item The predefined demo import item data.
* @return string The concatenated string of categories.
*/
public static function get_demo_import_item_categories( $item ) {
$sanitized_categories = array();
if ( isset( $item['categories'] ) ) {
foreach ( $item['categories'] as $category ) {
$sanitized_categories[] = sanitize_key( $category );
}
}
if ( ! empty( $sanitized_categories ) ) {
return implode( ',', $sanitized_categories );
}
return false;
}
/**
* Set the OCDI transient with the current importer data.
*
* @param array $data Data to be saved to the transient.
*/
public static function set_ocdi_import_data_transient( $data ) {
set_transient( 'ocdi_importer_data', $data, 0.1 * HOUR_IN_SECONDS );
}
}
PK G\誁 2 2 inc/WidgetImporter.phpnu W+A get_log_file_path();
// Import widgets and return result.
if ( ! empty( $widget_import_file_path ) ) {
$results = self::import_widgets( $widget_import_file_path );
}
// Check for errors, else write the results to the log file.
if ( is_wp_error( $results ) ) {
$error_message = $results->get_error_message();
// Add any error messages to the frontend_error_messages variable in OCDI main class.
$ocdi->append_to_frontend_error_messages( $error_message );
// Write error to log file.
Helpers::append_to_file(
$error_message,
$log_file_path,
esc_html__( 'Importing widgets', 'pt-ocdi' )
);
}
else {
ob_start();
self::format_results_for_log( $results );
$message = ob_get_clean();
// Add this message to log file.
$log_added = Helpers::append_to_file(
$message,
$log_file_path,
esc_html__( 'Importing widgets' , 'pt-ocdi' )
);
}
}
/**
* Imports widgets from a json file.
*
* @param string $data_file path to json file with WordPress widget export data.
*/
private static function import_widgets( $data_file ) {
// Get widgets data from file.
$data = self::process_import_file( $data_file );
// Return from this function if there was an error.
if ( is_wp_error( $data ) ) {
return $data;
}
// Import the widget data and save the results.
return self::import_data( $data );
}
/**
* Process import file - this parses the widget data and returns it.
*
* @param string $file path to json file.
* @return object $data decoded JSON string
*/
private static function process_import_file( $file ) {
// File exists?
if ( ! file_exists( $file ) ) {
return new \WP_Error(
'widget_import_file_not_found',
__( 'Error: Widget import file could not be found.', 'pt-ocdi' )
);
}
// Get file contents and decode.
$data = Helpers::data_from_file( $file );
// Return from this function if there was an error.
if ( is_wp_error( $data ) ) {
return $data;
}
return json_decode( $data );
}
/**
* Import widget JSON data
*
* @global array $wp_registered_sidebars
* @param object $data JSON widget data.
* @return array $results
*/
private static function import_data( $data ) {
global $wp_registered_sidebars;
// Have valid data? If no data or could not decode.
if ( empty( $data ) || ! is_object( $data ) ) {
return new \WP_Error(
'corrupted_widget_import_data',
__( 'Error: Widget import data could not be read. Please try a different file.', 'pt-ocdi' )
);
}
// Hook before import.
do_action( 'pt-ocdi/widget_importer_before_widgets_import' );
$data = apply_filters( 'pt-ocdi/before_widgets_import_data', $data );
// Get all available widgets site supports.
$available_widgets = self::available_widgets();
// Get all existing widget instances.
$widget_instances = array();
foreach ( $available_widgets as $widget_data ) {
$widget_instances[ $widget_data['id_base'] ] = get_option( 'widget_' . $widget_data['id_base'] );
}
// Begin results.
$results = array();
// Loop import data's sidebars.
foreach ( $data as $sidebar_id => $widgets ) {
// Skip inactive widgets (should not be in export file).
if ( 'wp_inactive_widgets' == $sidebar_id ) {
continue;
}
// Check if sidebar is available on this site. Otherwise add widgets to inactive, and say so.
if ( isset( $wp_registered_sidebars[ $sidebar_id ] ) ) {
$sidebar_available = true;
$use_sidebar_id = $sidebar_id;
$sidebar_message_type = 'success';
$sidebar_message = '';
}
else {
$sidebar_available = false;
$use_sidebar_id = 'wp_inactive_widgets'; // Add to inactive if sidebar does not exist in theme.
$sidebar_message_type = 'error';
$sidebar_message = __( 'Sidebar does not exist in theme (moving widget to Inactive)', 'pt-ocdi' );
}
// Result for sidebar.
$results[ $sidebar_id ]['name'] = ! empty( $wp_registered_sidebars[ $sidebar_id ]['name'] ) ? $wp_registered_sidebars[ $sidebar_id ]['name'] : $sidebar_id; // Sidebar name if theme supports it; otherwise ID.
$results[ $sidebar_id ]['message_type'] = $sidebar_message_type;
$results[ $sidebar_id ]['message'] = $sidebar_message;
$results[ $sidebar_id ]['widgets'] = array();
// Loop widgets.
foreach ( $widgets as $widget_instance_id => $widget ) {
$fail = false;
// Get id_base (remove -# from end) and instance ID number.
$id_base = preg_replace( '/-[0-9]+$/', '', $widget_instance_id );
$instance_id_number = str_replace( $id_base . '-', '', $widget_instance_id );
// Does site support this widget?
if ( ! $fail && ! isset( $available_widgets[ $id_base ] ) ) {
$fail = true;
$widget_message_type = 'error';
$widget_message = __( 'Site does not support widget', 'pt-ocdi' ); // Explain why widget not imported.
}
// Filter to modify settings object before conversion to array and import.
// Leave this filter here for backwards compatibility with manipulating objects (before conversion to array below).
// Ideally the newer wie_widget_settings_array below will be used instead of this.
$widget = apply_filters( 'pt-ocdi/widget_settings', $widget ); // Object.
// Convert multidimensional objects to multidimensional arrays.
// Some plugins like Jetpack Widget Visibility store settings as multidimensional arrays.
// Without this, they are imported as objects and cause fatal error on Widgets page.
// If this creates problems for plugins that do actually intend settings in objects then may need to consider other approach: https://wordpress.org/support/topic/problem-with-array-of-arrays.
// It is probably much more likely that arrays are used than objects, however.
$widget = json_decode( json_encode( $widget ), true );
// Filter to modify settings array.
// This is preferred over the older wie_widget_settings filter above.
// Do before identical check because changes may make it identical to end result (such as URL replacements).
$widget = apply_filters( 'pt-ocdi/widget_settings_array', $widget );
// Does widget with identical settings already exist in same sidebar?
if ( ! $fail && isset( $widget_instances[ $id_base ] ) ) {
// Get existing widgets in this sidebar.
$sidebars_widgets = get_option( 'sidebars_widgets' );
$sidebar_widgets = isset( $sidebars_widgets[ $use_sidebar_id ] ) ? $sidebars_widgets[ $use_sidebar_id ] : array(); // Check Inactive if that's where will go.
// Loop widgets with ID base.
$single_widget_instances = ! empty( $widget_instances[ $id_base ] ) ? $widget_instances[ $id_base ] : array();
foreach ( $single_widget_instances as $check_id => $check_widget ) {
// Is widget in same sidebar and has identical settings?
if ( in_array( "$id_base-$check_id", $sidebar_widgets ) && (array) $widget == $check_widget ) {
$fail = true;
$widget_message_type = 'warning';
$widget_message = __( 'Widget already exists', 'pt-ocdi' ); // Explain why widget not imported.
break;
}
}
}
// No failure.
if ( ! $fail ) {
// Add widget instance.
$single_widget_instances = get_option( 'widget_' . $id_base ); // All instances for that widget ID base, get fresh every time.
$single_widget_instances = ! empty( $single_widget_instances ) ? $single_widget_instances : array( '_multiwidget' => 1 ); // Start fresh if have to.
$single_widget_instances[] = $widget; // Add it.
// Get the key it was given.
end( $single_widget_instances );
$new_instance_id_number = key( $single_widget_instances );
// If key is 0, make it 1.
// When 0, an issue can occur where adding a widget causes data from other widget to load, and the widget doesn't stick (reload wipes it).
if ( '0' === strval( $new_instance_id_number ) ) {
$new_instance_id_number = 1;
$single_widget_instances[ $new_instance_id_number ] = $single_widget_instances[0];
unset( $single_widget_instances[0] );
}
// Move _multiwidget to end of array for uniformity.
if ( isset( $single_widget_instances['_multiwidget'] ) ) {
$multiwidget = $single_widget_instances['_multiwidget'];
unset( $single_widget_instances['_multiwidget'] );
$single_widget_instances['_multiwidget'] = $multiwidget;
}
// Update option with new widget.
update_option( 'widget_' . $id_base, $single_widget_instances );
// Assign widget instance to sidebar.
$sidebars_widgets = get_option( 'sidebars_widgets' ); // Which sidebars have which widgets, get fresh every time.
$new_instance_id = $id_base . '-' . $new_instance_id_number; // Use ID number from new widget instance.
$sidebars_widgets[ $use_sidebar_id ][] = $new_instance_id; // Add new instance to sidebar.
update_option( 'sidebars_widgets', $sidebars_widgets ); // Save the amended data.
// After widget import action.
$after_widget_import = array(
'sidebar' => $use_sidebar_id,
'sidebar_old' => $sidebar_id,
'widget' => $widget,
'widget_type' => $id_base,
'widget_id' => $new_instance_id,
'widget_id_old' => $widget_instance_id,
'widget_id_num' => $new_instance_id_number,
'widget_id_num_old' => $instance_id_number,
);
do_action( 'pt-ocdi/widget_importer_after_single_widget_import', $after_widget_import );
// Success message.
if ( $sidebar_available ) {
$widget_message_type = 'success';
$widget_message = __( 'Imported', 'pt-ocdi' );
}
else {
$widget_message_type = 'warning';
$widget_message = __( 'Imported to Inactive', 'pt-ocdi' );
}
}
// Result for widget instance.
$results[ $sidebar_id ]['widgets'][ $widget_instance_id ]['name'] = isset( $available_widgets[ $id_base ]['name'] ) ? $available_widgets[ $id_base ]['name'] : $id_base; // Widget name or ID if name not available (not supported by site).
$results[ $sidebar_id ]['widgets'][ $widget_instance_id ]['title'] = ! empty( $widget['title'] ) ? $widget['title'] : __( 'No Title', 'pt-ocdi' ); // Show "No Title" if widget instance is untitled.
$results[ $sidebar_id ]['widgets'][ $widget_instance_id ]['message_type'] = $widget_message_type;
$results[ $sidebar_id ]['widgets'][ $widget_instance_id ]['message'] = $widget_message;
}
}
// Hook after import.
do_action( 'pt-ocdi/widget_importer_after_widgets_import' );
// Return results.
return apply_filters( 'pt-ocdi/widget_import_results', $results );
}
/**
* Available widgets.
*
* Gather site's widgets into array with ID base, name, etc.
*
* @global array $wp_registered_widget_controls
* @return array $available_widgets, Widget information
*/
private static function available_widgets() {
global $wp_registered_widget_controls;
$widget_controls = $wp_registered_widget_controls;
$available_widgets = array();
foreach ( $widget_controls as $widget ) {
if ( ! empty( $widget['id_base'] ) && ! isset( $available_widgets[ $widget['id_base'] ] ) ) {
$available_widgets[ $widget['id_base'] ]['id_base'] = $widget['id_base'];
$available_widgets[ $widget['id_base'] ]['name'] = $widget['name'];
}
}
return apply_filters( 'pt-ocdi/available_widgets', $available_widgets );
}
/**
* Format results for log file
*
* @param array $results widget import results.
*/
private static function format_results_for_log( $results ) {
if ( empty( $results ) ) {
esc_html_e( 'No results for widget import!', 'pt-ocdi' );
}
// Loop sidebars.
foreach ( $results as $sidebar ) {
echo esc_html( $sidebar['name'] ) . ' : ' . esc_html( $sidebar['message'] ) . PHP_EOL . PHP_EOL;
// Loop widgets.
foreach ( $sidebar['widgets'] as $widget ) {
echo esc_html( $widget['name'] ) . ' - ' . esc_html( $widget['title'] ) . ' - ' . esc_html( $widget['message'] ) . PHP_EOL;
}
echo PHP_EOL;
}
}
}
PK G\/ inc/Logger.phpnu W+A error_output( $level, $message, $context = array() );
if ( $this->level_to_numeric( $level ) < $this->level_to_numeric( $this->min_level ) ) {
return;
}
printf(
'[%s] %s' . PHP_EOL,
strtoupper( $level ),
$message
);
}
/**
* Save messages for error output.
* Only the messages greater then Error.
*
* @param mixed $level level of reporting.
* @param string $message log message.
* @param array $context context to the log message.
*/
public function error_output( $level, $message, array $context = array() ) {
if ( $this->level_to_numeric( $level ) < $this->level_to_numeric( 'error' ) ) {
return;
}
$this->error_output .= sprintf(
'[%s] %s ',
strtoupper( $level ),
$message
);
}
}
PK G\BhG inc/Downloader.phpnu W+A set_download_directory_path( $download_directory_path );
}
/**
* Download file from a given URL.
*
* @param string $url URL of file to download.
* @param string $filename Filename of the file to save.
* @return string|WP_Error Full path to the downloaded file or WP_Error object with error message.
*/
public function download_file( $url, $filename ) {
$content = $this->get_content_from_url( $url );
// Check if there was an error and break out.
if ( is_wp_error( $content ) ) {
return $content;
}
return Helpers::write_to_file( $content, $this->download_directory_path . $filename );
}
/**
* Helper function: get content from an URL.
*
* @param string $url URL to the content file.
* @return string|WP_Error, content from the URL or WP_Error object with error message.
*/
private function get_content_from_url( $url ) {
// Test if the URL to the file is defined.
if ( empty( $url ) ) {
return new \WP_Error(
'missing_url',
__( 'Missing URL for downloading a file!', 'pt-ocdi' )
);
}
// Get file content from the server.
$response = wp_remote_get(
$url,
array( 'timeout' => apply_filters( 'pt-ocdi/timeout_for_downloading_import_file', 20 ) )
);
// Test if the get request was not successful.
if ( is_wp_error( $response ) || 200 !== $response['response']['code'] ) {
// Collect the right format of error data (array or WP_Error).
$response_error = $this->get_error_from_response( $response );
return new \WP_Error(
'download_error',
sprintf(
__( 'An error occurred while fetching file from: %1$s%2$s%3$s!%4$sReason: %5$s - %6$s.', 'pt-ocdi' ),
'',
$url,
'',
' ',
$response_error['error_code'],
$response_error['error_message']
) . ' ' .
apply_filters( 'pt-ocdi/message_after_file_fetching_error', '' )
);
}
// Return content retrieved from the URL.
return wp_remote_retrieve_body( $response );
}
/**
* Helper function: get the right format of response errors.
*
* @param array|WP_Error $response Array or WP_Error or the response.
* @return array Error code and error message.
*/
private function get_error_from_response( $response ) {
$response_error = array();
if ( is_array( $response ) ) {
$response_error['error_code'] = $response['response']['code'];
$response_error['error_message'] = $response['response']['message'];
}
else {
$response_error['error_code'] = $response->get_error_code();
$response_error['error_message'] = $response->get_error_message();
}
return $response_error;
}
/**
* Get download_directory_path attribute.
*/
public function get_download_directory_path() {
return $this->download_directory_path;
}
/**
* Set download_directory_path attribute.
* If no valid path is specified, the default WP upload directory will be used.
*
* @param string $download_directory_path Path, where the files will be saved.
*/
public function set_download_directory_path( $download_directory_path ) {
if ( file_exists( $download_directory_path ) ) {
$this->download_directory_path = $download_directory_path;
}
else {
$upload_dir = wp_upload_dir();
$this->download_directory_path = apply_filters( 'pt-ocdi/upload_file_path', trailingslashit( $upload_dir['path'] ) );
}
}
}
PK G\$
inc/ReduxImporter.phpnu W+A get_log_file_path();
// Redux plugin is not active!
if ( ! class_exists( 'ReduxFramework' ) ) {
$error_message = esc_html__( 'The Redux plugin is not activated, so the Redux import was skipped!', 'pt-ocdi' );
// Add any error messages to the frontend_error_messages variable in OCDI main class.
$ocdi->append_to_frontend_error_messages( $error_message );
// Write error to log file.
Helpers::append_to_file(
$error_message,
$log_file_path,
esc_html__( 'Importing Redux settings' , 'pt-ocdi' )
);
return;
}
foreach ( $import_data as $redux_item ) {
$redux_options_raw_data = Helpers::data_from_file( $redux_item['file_path'] );
$redux_options_data = json_decode( $redux_options_raw_data, true );
$redux_framework = \ReduxFrameworkInstances::get_instance( $redux_item['option_name'] );
if ( isset( $redux_framework->args['opt_name'] ) ) {
// Import Redux settings.
$redux_framework->set_options( $redux_options_data );
// Add this message to log file.
$log_added = Helpers::append_to_file(
sprintf( esc_html__( 'Redux settings import for: %s finished successfully!', 'pt-ocdi' ), $redux_item['option_name'] ),
$log_file_path,
esc_html__( 'Importing Redux settings' , 'pt-ocdi' )
);
}
else {
$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'] );
// Add any error messages to the frontend_error_messages variable in OCDI main class.
$ocdi->append_to_frontend_error_messages( $error_message );
// Write error to log file.
Helpers::append_to_file(
$error_message,
$log_file_path,
esc_html__( 'Importing Redux settings' , 'pt-ocdi' )
);
}
}
}
}
PK G\iX X inc/Importer.phpnu W+A include_required_files();
// Set the WordPress Importer v2 as the importer used in this plugin.
// More: https://github.com/humanmade/WordPress-Importer.
$this->importer = new WXRImporter( $importer_options );
// Set logger to the importer.
$this->logger = $logger;
if ( ! empty( $this->logger ) ) {
$this->set_logger( $this->logger );
}
// Get the OCDI (main plugin class) instance.
$this->ocdi = OneClickDemoImport::get_instance();
}
/**
* Include required files.
*/
private function include_required_files() {
if ( ! class_exists( '\WP_Importer' ) ) {
defined( 'WP_LOAD_IMPORTERS' ) || define( 'WP_LOAD_IMPORTERS', true );
require ABSPATH . '/wp-admin/includes/class-wp-importer.php';
}
}
/**
* Imports content from a WordPress export file.
*
* @param string $data_file path to xml file, file with WordPress export data.
*/
public function import( $data_file ) {
$this->importer->import( $data_file );
}
/**
* Set the logger used in the import
*
* @param object $logger logger instance.
*/
public function set_logger( $logger ) {
$this->importer->set_logger( $logger );
}
/**
* Get all protected variables from the WXR_Importer needed for continuing the import.
*/
public function get_importer_data() {
return $this->importer->get_importer_data();
}
/**
* Sets all protected variables from the WXR_Importer needed for continuing the import.
*
* @param array $data with set variables.
*/
public function set_importer_data( $data ) {
$this->importer->set_importer_data( $data );
}
/**
* Import content from an WP XML file.
*
* @param string $import_file_path Path to the import file.
*/
public function import_content( $import_file_path ) {
$this->microtime = microtime( true );
// Increase PHP max execution time. Just in case, even though the AJAX calls are only 25 sec long.
set_time_limit( apply_filters( 'pt-ocdi/set_time_limit_for_demo_data_import', 300 ) );
// Disable import of authors.
add_filter( 'wxr_importer.pre_process.user', '__return_false' );
// Check, if we need to send another AJAX request and set the importing author to the current user.
add_filter( 'wxr_importer.pre_process.post', array( $this, 'new_ajax_request_maybe' ) );
// Disables generation of multiple image sizes (thumbnails) in the content import step.
if ( ! apply_filters( 'pt-ocdi/regenerate_thumbnails_in_content_import', true ) ) {
add_filter( 'intermediate_image_sizes_advanced', '__return_null' );
}
// Import content.
if ( ! empty( $import_file_path ) ) {
ob_start();
$this->import( $import_file_path );
$message = ob_get_clean();
}
// Return any error messages for the front page output (errors, critical, alert and emergency level messages only).
return $this->logger->error_output;
}
/**
* Check if we need to create a new AJAX request, so that server does not timeout.
*
* @param array $data current post data.
* @return array
*/
public function new_ajax_request_maybe( $data ) {
$time = microtime( true ) - $this->microtime;
// We should make a new ajax call, if the time is right.
if ( $time > apply_filters( 'pt-ocdi/time_for_one_ajax_call', 25 ) ) {
$response = array(
'status' => 'newAJAX',
'message' => 'Time for new AJAX request!: ' . $time,
);
// Add any output to the log file and clear the buffers.
$message = ob_get_clean();
// Add any error messages to the frontend_error_messages variable in OCDI main class.
if ( ! empty( $message ) ) {
$this->ocdi->append_to_frontend_error_messages( $message );
}
// Add message to log file.
$log_added = Helpers::append_to_file(
__( 'New AJAX call!' , 'pt-ocdi' ) . PHP_EOL . $message,
$this->ocdi->get_log_file_path(),
''
);
// Set the current importer stat, so it can be continued on the next AJAX call.
$this->set_current_importer_data();
// Send the request for a new AJAX call.
wp_send_json( $response );
}
// Set importing author to the current user.
// Fixes the [WARNING] Could not find the author for ... log warning messages.
$current_user_obj = wp_get_current_user();
$data['post_author'] = $current_user_obj->user_login;
return $data;
}
/**
* Set current state of the content importer, so we can continue the import with new AJAX request.
*/
private function set_current_importer_data() {
$data = array_merge( $this->ocdi->get_current_importer_data(), $this->get_importer_data() );
Helpers::set_ocdi_import_data_transient( $data );
}
}
PK G\) F F inc/OneClickDemoImport.phpnu W+A 'themes.php',
'page_title' => esc_html__( 'One Click Demo Import' , 'pt-ocdi' ),
'menu_title' => esc_html__( 'Import Demo Data' , 'pt-ocdi' ),
'capability' => 'import',
'menu_slug' => 'pt-one-click-demo-import',
)
);
$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'],
apply_filters( 'pt-ocdi/plugin_page_display_callback_function', array( $this, 'display_plugin_page' ) )
);
}
/**
* Plugin page display.
* Output (HTML) is in another file.
*/
public function display_plugin_page() {
require_once PT_OCDI_PATH . 'views/plugin-page.php';
}
/**
* Enqueue admin scripts (JS and CSS)
*
* @param string $hook holds info on which admin page you are currently loading.
*/
public function admin_enqueue_scripts( $hook ) {
// Enqueue the scripts only on the plugin page.
if ( $this->plugin_page === $hook ) {
wp_enqueue_script( 'jquery-ui-dialog' );
wp_enqueue_style( 'wp-jquery-ui-dialog' );
wp_enqueue_script( 'ocdi-main-js', PT_OCDI_URL . 'assets/js/main.js' , array( 'jquery', 'jquery-ui-dialog' ), PT_OCDI_VERSION );
// Get theme data.
$theme = wp_get_theme();
wp_localize_script( 'ocdi-main-js', 'ocdi',
array(
'ajax_url' => admin_url( 'admin-ajax.php' ),
'ajax_nonce' => wp_create_nonce( 'ocdi-ajax-verification' ),
'import_files' => $this->import_files,
'wp_customize_on' => apply_filters( 'pt-ocdi/enable_wp_customize_save_hooks', false ),
'import_popup' => apply_filters( 'pt-ocdi/enable_grid_layout_import_popup_confirmation', true ),
'theme_screenshot' => $theme->get_screenshot(),
'texts' => array(
'missing_preview_image' => esc_html__( 'No preview image defined for this import.', 'pt-ocdi' ),
'dialog_title' => esc_html__( 'Are you sure?', 'pt-ocdi' ),
'dialog_no' => esc_html__( 'Cancel', 'pt-ocdi' ),
'dialog_yes' => esc_html__( 'Yes, import!', 'pt-ocdi' ),
'selected_import_title' => esc_html__( 'Selected demo import:', 'pt-ocdi' ),
),
'dialog_options' => apply_filters( 'pt-ocdi/confirmation_dialog_options', array() )
)
);
wp_enqueue_style( 'ocdi-main-css', PT_OCDI_URL . 'assets/css/main.css', array() , PT_OCDI_VERSION );
}
}
/**
* Main AJAX callback function for:
* 1). prepare import files (uploaded or predefined via filters)
* 2). execute 'before content import' actions (before import WP action)
* 3). import content
* 4). execute 'after content import' actions (before widget import WP action, widget import, customizer import, after import WP action)
*/
public function import_demo_data_ajax_callback() {
// Try to update PHP memory limit (so that it does not run out of it).
ini_set( 'memory_limit', apply_filters( 'pt-ocdi/import_memory_limit', '350M' ) );
// Verify if the AJAX call is valid (checks nonce and current_user_can).
Helpers::verify_ajax_call();
// Is this a new AJAX call to continue the previous import?
$use_existing_importer_data = $this->use_existing_importer_data();
if ( ! $use_existing_importer_data ) {
// Create a date and time string to use for demo and log file names.
Helpers::set_demo_import_start_time();
// Define log file path.
$this->log_file_path = Helpers::get_log_path();
// Get selected file index or set it to 0.
$this->selected_index = empty( $_POST['selected'] ) ? 0 : absint( $_POST['selected'] );
/**
* 1). Prepare import files.
* Manually uploaded import files or predefined import files via filter: pt-ocdi/import_files
*/
if ( ! empty( $_FILES ) ) { // Using manual file uploads?
// Get paths for the uploaded files.
$this->selected_import_files = Helpers::process_uploaded_files( $_FILES, $this->log_file_path );
// Set the name of the import files, because we used the uploaded files.
$this->import_files[ $this->selected_index ]['import_file_name'] = esc_html__( 'Manually uploaded files', 'pt-ocdi' );
}
elseif ( ! empty( $this->import_files[ $this->selected_index ] ) ) { // Use predefined import files from wp filter: pt-ocdi/import_files.
// Download the import files (content, widgets and customizer files).
$this->selected_import_files = Helpers::download_import_files( $this->import_files[ $this->selected_index ] );
// Check Errors.
if ( is_wp_error( $this->selected_import_files ) ) {
// Write error to log file and send an AJAX response with the error.
Helpers::log_error_and_send_ajax_response(
$this->selected_import_files->get_error_message(),
$this->log_file_path,
esc_html__( 'Downloaded files', 'pt-ocdi' )
);
}
// Add this message to log file.
$log_added = Helpers::append_to_file(
sprintf(
__( 'The import files for: %s were successfully downloaded!', 'pt-ocdi' ),
$this->import_files[ $this->selected_index ]['import_file_name']
) . Helpers::import_file_info( $this->selected_import_files ),
$this->log_file_path,
esc_html__( 'Downloaded files' , 'pt-ocdi' )
);
}
else {
// Send JSON Error response to the AJAX call.
wp_send_json( esc_html__( 'No import files specified!', 'pt-ocdi' ) );
}
}
// Save the initial import data as a transient, so other import parts (in new AJAX calls) can use that data.
Helpers::set_ocdi_import_data_transient( $this->get_current_importer_data() );
if ( ! $this->before_import_executed ) {
$this->before_import_executed = true;
/**
* 2). Execute the actions hooked to the 'pt-ocdi/before_content_import_execution' action:
*
* Default actions:
* 1 - Before content import WP action (with priority 10).
*/
do_action( 'pt-ocdi/before_content_import_execution', $this->selected_import_files, $this->import_files, $this->selected_index );
}
/**
* 3). Import content.
* Returns any errors greater then the "warning" logger level, that will be displayed on front page.
*/
$this->append_to_frontend_error_messages( $this->importer->import_content( $this->selected_import_files['content'] ) );
/**
* 4). Execute the actions hooked to the 'pt-ocdi/after_content_import_execution' action:
*
* Default actions:
* 1 - Before widgets import setup (with priority 10).
* 2 - Import widgets (with priority 20).
* 3 - Import Redux data (with priority 30).
*/
do_action( 'pt-ocdi/after_content_import_execution', $this->selected_import_files, $this->import_files, $this->selected_index );
// Save the import data as a transient, so other import parts (in new AJAX calls) can use that data.
Helpers::set_ocdi_import_data_transient( $this->get_current_importer_data() );
// Request the customizer import AJAX call.
if ( ! empty( $this->selected_import_files['customizer'] ) ) {
wp_send_json( array( 'status' => 'customizerAJAX' ) );
}
// Request the after all import AJAX call.
if ( false !== has_action( 'pt-ocdi/after_all_import_execution' ) ) {
wp_send_json( array( 'status' => 'afterAllImportAJAX' ) );
}
// Send a JSON response with final report.
$this->final_response();
}
/**
* AJAX callback for importing the customizer data.
* This request has the wp_customize set to 'on', so that the customizer hooks can be called
* (they can only be called with the $wp_customize instance). But if the $wp_customize is defined,
* then the widgets do not import correctly, that's why the customizer import has its own AJAX call.
*/
public function import_customizer_data_ajax_callback() {
// Verify if the AJAX call is valid (checks nonce and current_user_can).
Helpers::verify_ajax_call();
// Get existing import data.
if ( $this->use_existing_importer_data() ) {
/**
* Execute the customizer import actions.
*
* Default actions:
* 1 - Customizer import (with priority 10).
*/
do_action( 'pt-ocdi/customizer_import_execution', $this->selected_import_files );
}
// Request the after all import AJAX call.
if ( false !== has_action( 'pt-ocdi/after_all_import_execution' ) ) {
wp_send_json( array( 'status' => 'afterAllImportAJAX' ) );
}
// Send a JSON response with final report.
$this->final_response();
}
/**
* AJAX callback for the after all import action.
*/
public function after_all_import_data_ajax_callback() {
// Verify if the AJAX call is valid (checks nonce and current_user_can).
Helpers::verify_ajax_call();
// Get existing import data.
if ( $this->use_existing_importer_data() ) {
/**
* Execute the after all import actions.
*
* Default actions:
* 1 - after_import action (with priority 10).
*/
do_action( 'pt-ocdi/after_all_import_execution', $this->selected_import_files, $this->import_files, $this->selected_index );
}
// Send a JSON response with final report.
$this->final_response();
}
/**
* Send a JSON response with final report.
*/
private function final_response() {
// Delete importer data transient for current import.
delete_transient( 'ocdi_importer_data' );
// Display final messages (success or error messages).
if ( empty( $this->frontend_error_messages ) ) {
$response['message'] = '';
if ( ! apply_filters( 'pt-ocdi/disable_pt_branding', false ) ) {
$twitter_status = esc_html__( 'Just used One Click Demo Import plugin and it was awesome! Thanks @ProteusThemes! #OCDI https://www.proteusthemes.com/', 'pt-ocdi' );
$response['message'] .= sprintf(
__( '%1$s%6$sWasn\'t this a great One Click Demo Import experience?%7$s Created and maintained by %3$sProteusThemes%4$s. %2$s%5$sClick to Tweet!%4$s%8$s', 'pt-ocdi' ),
'
'
);
}
$response['message'] .= sprintf(
__( '%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' ),
'
',
' ',
'',
'',
'
'
);
}
else {
$response['message'] = $this->frontend_error_messages_display() . ' ';
$response['message'] .= sprintf(
__( '%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' ),
'