2020-04-07 13:03:04 +00:00
< ? php
2020-08-13 14:53:39 +00:00
/**
* This file handles the widget imports .
*
* @ package GP Premium
*/
if ( ! defined ( 'ABSPATH' ) ) {
exit ; // No direct access, please.
}
2020-04-07 13:03:04 +00:00
2020-08-13 14:53:39 +00:00
/**
* Widget importer class .
*/
2020-04-07 13:03:04 +00:00
class GeneratePress_Sites_Widget_Importer {
/**
* Instance .
2020-08-13 14:53:39 +00:00
*
* @ var $_instance
2020-04-07 13:03:04 +00:00
*/
2020-08-13 14:53:39 +00:00
private static $_instance = null ; // phpcs:ignore -- Want the underscore.
2020-04-07 13:03:04 +00:00
2020-08-13 14:53:39 +00:00
/**
* Get our instance .
*/
2020-04-07 13:03:04 +00:00
public static function instance () {
if ( ! isset ( self :: $_instance ) ) {
2020-08-13 14:53:39 +00:00
self :: $_instance = new self ();
2020-04-07 13:03:04 +00:00
}
return self :: $_instance ;
}
/**
* Available widgets
*
* Gather site ' s widgets into array with ID base , name , etc .
* Used by export and import functions .
*
* @ since 0.4
* @ global array $wp_registered_widget_updates
* @ return array Widget information
*/
2020-08-13 14:53:39 +00:00
public function wie_available_widgets () {
2020-04-07 13:03:04 +00:00
global $wp_registered_widget_controls ;
$widget_controls = $wp_registered_widget_controls ;
$available_widgets = array ();
foreach ( $widget_controls as $widget ) {
// No duplicates.
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' ];
}
}
2020-08-13 14:53:39 +00:00
return apply_filters ( 'wie_available_widgets' , $available_widgets ); // phpcs:ignore -- Keep the plugin prefix.
2020-04-07 13:03:04 +00:00
}
/**
* Import widget JSON data
*
* @ since 0.4
* @ global array $wp_registered_sidebars
* @ param object $data JSON widget data from . wie file .
* @ return array Results array
*/
2020-08-13 14:53:39 +00:00
public function wie_import_data ( $data ) {
2020-04-07 13:03:04 +00:00
global $wp_registered_sidebars ;
// Have valid data?
// If no data or could not decode.
if ( empty ( $data ) || ! is_object ( $data ) ) {
wp_die (
esc_html__ ( 'Import data could not be read. Please try a different file.' , 'widget-importer-exporter' ),
'' ,
array (
'back_link' => true ,
)
);
}
// Hook before import.
2020-08-13 14:53:39 +00:00
do_action ( 'wie_before_import' ); // phpcs:ignore -- Keep the plugin prefix.
2020-04-07 13:03:04 +00:00
2020-08-13 14:53:39 +00:00
$data = apply_filters ( 'wie_import_data' , $data ); // phpcs:ignore -- Keep the plugin prefix.
2020-04-07 13:03:04 +00:00
// Get all available widgets site supports.
$available_widgets = $this -> wie_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 = esc_html__ ( 'Widget area does not exist in theme (using Inactive)' , 'widget-importer-exporter' );
}
// Result for sidebar
// Sidebar name if theme supports it; otherwise ID.
$results [ $sidebar_id ][ 'name' ] = ! empty ( $wp_registered_sidebars [ $sidebar_id ][ 'name' ] ) ? $wp_registered_sidebars [ $sidebar_id ][ 'name' ] : $sidebar_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 = esc_html__ ( 'Site does not support widget' , 'widget-importer-exporter' ); // 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.
2020-08-13 14:53:39 +00:00
$widget = apply_filters ( 'wie_widget_settings' , $widget ); // phpcs:ignore -- Keep the plugin prefix.
2020-04-07 13:03:04 +00:00
// 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 ( wp_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).
2020-08-13 14:53:39 +00:00
$widget = apply_filters ( 'wie_widget_settings_array' , $widget ); // phpcs:ignore -- Keep the plugin prefix.
2020-04-07 13:03:04 +00:00
// 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 , true ) && ( array ) $widget === $check_widget ) {
$fail = true ;
$widget_message_type = 'warning' ;
// Explain why widget not imported.
$widget_message = esc_html__ ( 'Widget already exists' , 'widget-importer-exporter' );
break ;
}
}
}
// No failure.
if ( ! $fail ) {
2020-08-13 14:53:39 +00:00
// Add widget instance.
2020-04-07 13:03:04 +00:00
$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.
// Which sidebars have which widgets, get fresh every time.
$sidebars_widgets = get_option ( 'sidebars_widgets' );
// Avoid rarely fatal error when the option is an empty string
// https://github.com/stevengliebe/widget-importer-exporter/pull/11.
if ( ! $sidebars_widgets ) {
$sidebars_widgets = array ();
}
// Use ID number from new widget instance.
$new_instance_id = $id_base . '-' . $new_instance_id_number ;
// Add new instance to sidebar.
$sidebars_widgets [ $use_sidebar_id ][] = $new_instance_id ;
// Save the amended data.
update_option ( 'sidebars_widgets' , $sidebars_widgets );
// 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 ,
);
2020-08-13 14:53:39 +00:00
do_action ( 'wie_after_widget_import' , $after_widget_import ); // phpcs:ignore -- Keep the plugin prefix.
2020-04-07 13:03:04 +00:00
// Success message.
if ( $sidebar_available ) {
$widget_message_type = 'success' ;
$widget_message = esc_html__ ( 'Imported' , 'widget-importer-exporter' );
} else {
$widget_message_type = 'warning' ;
$widget_message = esc_html__ ( 'Imported to Inactive' , 'widget-importer-exporter' );
}
}
2020-08-13 14:53:39 +00:00
// Result for widget instance.
2020-04-07 13:03:04 +00:00
$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' ] : esc_html__ ( 'No Title' , 'widget-importer-exporter' ); // 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.
2020-08-13 14:53:39 +00:00
do_action ( 'wie_after_import' ); // phpcs:ignore -- Keep the plugin prefix.
2020-04-07 13:03:04 +00:00
// Return results.
2020-08-13 14:53:39 +00:00
return apply_filters ( 'wie_import_results' , $results ); // phpcs:ignore -- Keep the plugin prefix.
2020-04-07 13:03:04 +00:00
}
}