| 1 |
<?php |
| 2 |
|
| 3 |
namespace LIBRARY; |
| 4 |
|
| 5 |
class BorderlessLibraryImporter { |
| 6 |
|
| 7 |
private static $instance; |
| 8 |
public $importer; |
| 9 |
public $plugin_installer; |
| 10 |
private $plugin_page; |
| 11 |
public $import_files; |
| 12 |
public $log_file_path; |
| 13 |
private $selected_index; |
| 14 |
private $selected_import_files; |
| 15 |
public $frontend_error_messages = array(); |
| 16 |
private $before_import_executed = false; |
| 17 |
private $plugin_page_setup = array(); |
| 18 |
private $imported_terms = array(); |
| 19 |
|
| 20 |
public static function get_instance() { |
| 21 |
if ( null === static::$instance ) { |
| 22 |
static::$instance = new static(); |
| 23 |
} |
| 24 |
|
| 25 |
return static::$instance; |
| 26 |
} |
| 27 |
|
| 28 |
protected function __construct() { |
| 29 |
add_action( 'admin_menu', array( $this, 'create_plugin_page' ) ); |
| 30 |
add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) ); |
| 31 |
add_action( 'wp_ajax_library_upload_manual_import_files', array( $this, 'upload_manual_import_files_callback' ) ); |
| 32 |
add_action( 'wp_ajax_library_import_demo_data', array( $this, 'import_demo_data_ajax_callback' ) ); |
| 33 |
add_action( 'wp_ajax_library_import_customizer_data', array( $this, 'import_customizer_data_ajax_callback' ) ); |
| 34 |
add_action( 'wp_ajax_library_after_import_data', array( $this, 'after_all_import_data_ajax_callback' ) ); |
| 35 |
add_action( 'after_setup_theme', array( $this, 'setup_plugin_with_filter_data' ) ); |
| 36 |
add_action( 'user_admin_notices', array( $this, 'start_notice_output_capturing' ), 0 ); |
| 37 |
add_action( 'admin_notices', array( $this, 'start_notice_output_capturing' ), 0 ); |
| 38 |
add_action( 'all_admin_notices', array( $this, 'finish_notice_output_capturing' ), PHP_INT_MAX ); |
| 39 |
add_action( 'admin_init', array( $this, 'redirect_from_old_default_admin_page' ) ); |
| 40 |
add_action( 'set_object_terms', array( $this, 'add_imported_terms' ), 10, 6 ); |
| 41 |
} |
| 42 |
|
| 43 |
|
| 44 |
|
| 45 |
private function __clone() {} |
| 46 |
public function __wakeup() {} |
| 47 |
|
| 48 |
|
| 49 |
public function create_plugin_page() { |
| 50 |
$this->plugin_page_setup = Helpers::get_plugin_page_setup_data(); |
| 51 |
|
| 52 |
$this->plugin_page = add_submenu_page( |
| 53 |
$this->plugin_page_setup['parent_slug'], |
| 54 |
$this->plugin_page_setup['page_title'], |
| 55 |
$this->plugin_page_setup['menu_title'], |
| 56 |
$this->plugin_page_setup['capability'], |
| 57 |
$this->plugin_page_setup['menu_slug'], |
| 58 |
Helpers::apply_filters( 'library/plugin_page_display_callback_function', array( $this, 'display_plugin_page' ) ) |
| 59 |
); |
| 60 |
|
| 61 |
add_submenu_page( |
| 62 |
'', |
| 63 |
$this->plugin_page_setup['page_title'], |
| 64 |
$this->plugin_page_setup['menu_title'], |
| 65 |
$this->plugin_page_setup['capability'], |
| 66 |
'pt-library' |
| 67 |
); |
| 68 |
|
| 69 |
register_importer( $this->plugin_page_setup['menu_slug'], $this->plugin_page_setup['page_title'], $this->plugin_page_setup['menu_title'], Helpers::apply_filters( 'library/plugin_page_display_callback_function', array( $this, 'display_plugin_page' ) ) ); |
| 70 |
} |
| 71 |
|
| 72 |
public function display_plugin_page() { |
| 73 |
|
| 74 |
if ( isset( $_GET['step'] ) && 'install-plugins' === $_GET['step'] ) { |
| 75 |
require_once BORDERLESS__LIBRARY__DIR . 'views/install-plugins.php'; |
| 76 |
|
| 77 |
return; |
| 78 |
} |
| 79 |
|
| 80 |
if ( isset( $_GET['step'] ) && 'import' === $_GET['step'] ) { |
| 81 |
require_once BORDERLESS__LIBRARY__DIR . 'views/import.php'; |
| 82 |
|
| 83 |
return; |
| 84 |
} |
| 85 |
|
| 86 |
require_once BORDERLESS__LIBRARY__DIR . 'views/plugin-page.php'; |
| 87 |
} |
| 88 |
|
| 89 |
public function admin_enqueue_scripts( $hook ) { |
| 90 |
if ( $this->plugin_page === $hook || ( 'admin.php' === $hook && $this->plugin_page_setup['menu_slug'] === esc_attr( $_GET['import'] ) ) ) { |
| 91 |
wp_enqueue_script('borderless-library-bootstrap-script', BORDERLESS__SCRIPTS . 'bootstrap.js', array(), BORDERLESS__VERSION, true); |
| 92 |
wp_enqueue_script('borderless-library-isotope-script', BORDERLESS__LIB . 'isotope.js', array(), '3.0.6', true); |
| 93 |
wp_enqueue_script('borderless-library-images-loaded-script', BORDERLESS__LIB . 'images-loaded.js', array(), '5.0.0', true); |
| 94 |
wp_enqueue_script('borderless-library-script', BORDERLESS__SCRIPTS . 'library.js', array(), BORDERLESS__VERSION, true); |
| 95 |
|
| 96 |
$theme = wp_get_theme(); |
| 97 |
|
| 98 |
wp_localize_script( 'borderless-library-script', 'library', |
| 99 |
array( |
| 100 |
'ajax_url' => admin_url( 'admin-ajax.php' ), |
| 101 |
'ajax_nonce' => wp_create_nonce( 'library-ajax-verification' ), |
| 102 |
'import_files' => $this->import_files, |
| 103 |
'wp_customize_on' => Helpers::apply_filters( 'library/enable_wp_customize_save_hooks', false ), |
| 104 |
'theme_screenshot' => $theme->get_screenshot(), |
| 105 |
'missing_plugins' => $this->plugin_installer->get_missing_plugins(), |
| 106 |
'plugin_url' => BORDERLESS__LIBRARY__URL, |
| 107 |
'import_url' => $this->get_plugin_settings_url( [ 'step' => 'import' ] ), |
| 108 |
'texts' => array( |
| 109 |
'missing_preview_image' => esc_html__( 'No preview image defined for this import.', 'borderless' ), |
| 110 |
'dialog_title' => esc_html__( 'Are you sure?', 'borderless' ), |
| 111 |
'dialog_no' => esc_html__( 'Cancel', 'borderless' ), |
| 112 |
'dialog_yes' => esc_html__( 'Yes, import!', 'borderless' ), |
| 113 |
'selected_import_title' => esc_html__( 'Selected demo import:', 'borderless' ), |
| 114 |
'installing' => esc_html__( 'Installing...', 'borderless' ), |
| 115 |
'importing' => esc_html__( 'Importing...', 'borderless' ), |
| 116 |
'successful_import' => esc_html__( 'Successfully Imported!', 'borderless' ), |
| 117 |
'install_plugin' => esc_html__( 'Install Plugin', 'borderless' ), |
| 118 |
'installed' => esc_html__( 'Installed', 'borderless' ), |
| 119 |
'import_failed' => esc_html__( 'Import Failed', 'borderless' ), |
| 120 |
'import_failed_subtitle' => esc_html__( 'Whoops, there was a problem importing your content.', 'borderless' ), |
| 121 |
'plugin_install_failed' => esc_html__( 'Looks like some of the plugins failed to install. Please try again. If this issue persists, please manually install the failing plugins and come back to this step to import the theme demo data.', 'borderless' ), |
| 122 |
'content_filetype_warn' => esc_html__( 'Invalid file type detected! Please select an XML file for the Content Import.', 'borderless' ), |
| 123 |
'widgets_filetype_warn' => esc_html__( 'Invalid file type detected! Please select a JSON or WIE file for the Widgets Import.', 'borderless' ), |
| 124 |
'customizer_filetype_warn' => esc_html__( 'Invalid file type detected! Please select a DAT file for the Customizer Import.', 'borderless' ), |
| 125 |
'redux_filetype_warn' => esc_html__( 'Invalid file type detected! Please select a JSON file for the Redux Import.', 'borderless' ), |
| 126 |
), |
| 127 |
) |
| 128 |
); |
| 129 |
|
| 130 |
wp_enqueue_style('borderless-library-style', BORDERLESS__STYLES.'library.css'); |
| 131 |
wp_enqueue_style('bootstrap', BORDERLESS__STYLES.'bootstrap.css'); |
| 132 |
wp_enqueue_style('bootstrap-icons', BORDERLESS__STYLES.'bootstrap-icons.css'); |
| 133 |
} |
| 134 |
} |
| 135 |
|
| 136 |
|
| 137 |
public function upload_manual_import_files_callback() { |
| 138 |
Helpers::verify_ajax_call(); |
| 139 |
|
| 140 |
if ( empty( $_FILES ) ) { |
| 141 |
wp_send_json_error( esc_html__( 'Manual import files are missing! Please select the import files and try again.', 'borderless' ) ); |
| 142 |
} |
| 143 |
|
| 144 |
Helpers::set_demo_import_start_time(); |
| 145 |
|
| 146 |
$this->log_file_path = Helpers::get_log_path(); |
| 147 |
$this->selected_index = 0; |
| 148 |
$this->selected_import_files = Helpers::process_uploaded_files( $_FILES, $this->log_file_path ); |
| 149 |
$this->import_files[ $this->selected_index ]['import_file_name'] = esc_html__( 'Manually uploaded files', 'borderless' ); |
| 150 |
|
| 151 |
Helpers::set_library_import_data_transient( $this->get_current_importer_data() ); |
| 152 |
|
| 153 |
wp_send_json_success(); |
| 154 |
} |
| 155 |
|
| 156 |
|
| 157 |
public function import_demo_data_ajax_callback() { |
| 158 |
ini_set( 'memory_limit', Helpers::apply_filters( 'library/import_memory_limit', '500M' ) ); |
| 159 |
|
| 160 |
Helpers::verify_ajax_call(); |
| 161 |
|
| 162 |
$use_existing_importer_data = $this->use_existing_importer_data(); |
| 163 |
|
| 164 |
if ( ! $use_existing_importer_data ) { |
| 165 |
Helpers::set_demo_import_start_time(); |
| 166 |
|
| 167 |
$this->log_file_path = Helpers::get_log_path(); |
| 168 |
$this->selected_index = empty( $_POST['selected'] ) ? 0 : absint( $_POST['selected'] ); |
| 169 |
|
| 170 |
if ( ! empty( $_FILES ) ) { |
| 171 |
$this->selected_import_files = Helpers::process_uploaded_files( $_FILES, $this->log_file_path ); |
| 172 |
$this->import_files[ $this->selected_index ]['import_file_name'] = esc_html__( 'Manually uploaded files', 'borderless' ); |
| 173 |
} |
| 174 |
elseif ( ! empty( $this->import_files[ $this->selected_index ] ) ) { |
| 175 |
|
| 176 |
$this->selected_import_files = Helpers::download_import_files( $this->import_files[ $this->selected_index ] ); |
| 177 |
|
| 178 |
if ( is_wp_error( $this->selected_import_files ) ) { |
| 179 |
Helpers::log_error_and_send_ajax_response( |
| 180 |
$this->selected_import_files->get_error_message(), |
| 181 |
$this->log_file_path, |
| 182 |
esc_html__( 'Downloaded files', 'borderless' ) |
| 183 |
); |
| 184 |
} |
| 185 |
|
| 186 |
$log_added = Helpers::append_to_file( |
| 187 |
sprintf( |
| 188 |
__( 'The import files for: %s were successfully downloaded!', 'borderless' ), |
| 189 |
$this->import_files[ $this->selected_index ]['import_file_name'] |
| 190 |
) . Helpers::import_file_info( $this->selected_import_files ), |
| 191 |
$this->log_file_path, |
| 192 |
esc_html__( 'Downloaded files' , 'borderless' ) |
| 193 |
); |
| 194 |
} |
| 195 |
else { |
| 196 |
wp_send_json( esc_html__( 'No import files specified!', 'borderless' ) ); |
| 197 |
} |
| 198 |
} |
| 199 |
|
| 200 |
Helpers::set_library_import_data_transient( $this->get_current_importer_data() ); |
| 201 |
|
| 202 |
if ( ! $this->before_import_executed ) { |
| 203 |
$this->before_import_executed = true; |
| 204 |
|
| 205 |
Helpers::do_action( 'library/before_content_import_execution', $this->selected_import_files, $this->import_files, $this->selected_index ); |
| 206 |
} |
| 207 |
|
| 208 |
if ( ! empty( $this->selected_import_files['content'] ) ) { |
| 209 |
$this->append_to_frontend_error_messages( $this->importer->import_content( $this->selected_import_files['content'] ) ); |
| 210 |
} |
| 211 |
|
| 212 |
Helpers::do_action( 'library/after_content_import_execution', $this->selected_import_files, $this->import_files, $this->selected_index ); |
| 213 |
Helpers::set_library_import_data_transient( $this->get_current_importer_data() ); |
| 214 |
|
| 215 |
if ( ! empty( $this->selected_import_files['customizer'] ) ) { |
| 216 |
wp_send_json( array( 'status' => 'customizerAJAX' ) ); |
| 217 |
} |
| 218 |
|
| 219 |
if ( false !== Helpers::has_action( 'library/after_all_import_execution' ) ) { |
| 220 |
wp_send_json( array( 'status' => 'afterAllImportAJAX' ) ); |
| 221 |
} |
| 222 |
|
| 223 |
$this->update_terms_count(); |
| 224 |
$this->final_response(); |
| 225 |
} |
| 226 |
|
| 227 |
|
| 228 |
public function import_customizer_data_ajax_callback() { |
| 229 |
Helpers::verify_ajax_call(); |
| 230 |
|
| 231 |
if ( $this->use_existing_importer_data() ) { |
| 232 |
Helpers::do_action( 'library/customizer_import_execution', $this->selected_import_files ); |
| 233 |
} |
| 234 |
|
| 235 |
if ( false !== Helpers::has_action( 'library/after_all_import_execution' ) ) { |
| 236 |
wp_send_json( array( 'status' => 'afterAllImportAJAX' ) ); |
| 237 |
} |
| 238 |
|
| 239 |
$this->final_response(); |
| 240 |
} |
| 241 |
|
| 242 |
|
| 243 |
public function after_all_import_data_ajax_callback() { |
| 244 |
Helpers::verify_ajax_call(); |
| 245 |
|
| 246 |
if ( $this->use_existing_importer_data() ) { |
| 247 |
Helpers::do_action( 'library/after_all_import_execution', $this->selected_import_files, $this->import_files, $this->selected_index ); |
| 248 |
} |
| 249 |
|
| 250 |
$this->update_terms_count(); |
| 251 |
|
| 252 |
$this->final_response(); |
| 253 |
} |
| 254 |
|
| 255 |
|
| 256 |
private function final_response() { |
| 257 |
delete_transient( 'library_importer_data' ); |
| 258 |
|
| 259 |
$response['title'] = esc_html__( 'Import Complete!', 'borderless' ); |
| 260 |
$response['subtitle'] = '<p>' . esc_html__( 'Your Website is ready.', 'borderless' ) . '</p>'; |
| 261 |
$response['message'] = '<i class="borderless-library-import__imported-icon bi bi-check-circle-fill"></i>'; |
| 262 |
|
| 263 |
if ( ! empty( $this->frontend_error_messages ) ) { |
| 264 |
$response['subtitle'] = '<p>' . esc_html__( 'Your Website is ready, but some things could not be imported.', 'borderless' ) . '</p>'; |
| 265 |
$response['subtitle'] .= sprintf( |
| 266 |
wp_kses( |
| 267 |
__( '<p><a href="%s" target="_blank">View error log</a> for more information.</p>', 'borderless' ), |
| 268 |
array( |
| 269 |
'p' => [], |
| 270 |
'a' => [ |
| 271 |
'href' => [], |
| 272 |
'target' => [], |
| 273 |
], |
| 274 |
) |
| 275 |
), |
| 276 |
Helpers::get_log_url( $this->log_file_path ) |
| 277 |
); |
| 278 |
|
| 279 |
$response['message'] = '<div class="notice notice-warning"><p>' . $this->frontend_error_messages_display() . '</p></div>'; |
| 280 |
} |
| 281 |
|
| 282 |
wp_send_json( $response ); |
| 283 |
} |
| 284 |
|
| 285 |
|
| 286 |
private function use_existing_importer_data() { |
| 287 |
if ( $data = get_transient( 'library_importer_data' ) ) { |
| 288 |
$this->frontend_error_messages = empty( $data['frontend_error_messages'] ) ? array() : $data['frontend_error_messages']; |
| 289 |
$this->log_file_path = empty( $data['log_file_path'] ) ? '' : $data['log_file_path']; |
| 290 |
$this->selected_index = empty( $data['selected_index'] ) ? 0 : $data['selected_index']; |
| 291 |
$this->selected_import_files = empty( $data['selected_import_files'] ) ? array() : $data['selected_import_files']; |
| 292 |
$this->import_files = empty( $data['import_files'] ) ? array() : $data['import_files']; |
| 293 |
$this->before_import_executed = empty( $data['before_import_executed'] ) ? false : $data['before_import_executed']; |
| 294 |
$this->imported_terms = empty( $data['imported_terms'] ) ? [] : $data['imported_terms']; |
| 295 |
$this->importer->set_importer_data( $data ); |
| 296 |
|
| 297 |
return true; |
| 298 |
} |
| 299 |
return false; |
| 300 |
} |
| 301 |
|
| 302 |
|
| 303 |
public function get_current_importer_data() { |
| 304 |
return array( |
| 305 |
'frontend_error_messages' => $this->frontend_error_messages, |
| 306 |
'log_file_path' => $this->log_file_path, |
| 307 |
'selected_index' => $this->selected_index, |
| 308 |
'selected_import_files' => $this->selected_import_files, |
| 309 |
'import_files' => $this->import_files, |
| 310 |
'before_import_executed' => $this->before_import_executed, |
| 311 |
'imported_terms' => $this->imported_terms, |
| 312 |
); |
| 313 |
} |
| 314 |
|
| 315 |
|
| 316 |
public function get_log_file_path() { |
| 317 |
return $this->log_file_path; |
| 318 |
} |
| 319 |
|
| 320 |
|
| 321 |
public function append_to_frontend_error_messages( $text ) { |
| 322 |
$lines = array(); |
| 323 |
|
| 324 |
if ( ! empty( $text ) ) { |
| 325 |
$text = str_replace( '<br>', PHP_EOL, $text ); |
| 326 |
$lines = explode( PHP_EOL, $text ); |
| 327 |
} |
| 328 |
|
| 329 |
foreach ( $lines as $line ) { |
| 330 |
if ( ! empty( $line ) && ! in_array( $line , $this->frontend_error_messages ) ) { |
| 331 |
$this->frontend_error_messages[] = $line; |
| 332 |
} |
| 333 |
} |
| 334 |
} |
| 335 |
|
| 336 |
|
| 337 |
public function frontend_error_messages_display() { |
| 338 |
$output = ''; |
| 339 |
|
| 340 |
if ( ! empty( $this->frontend_error_messages ) ) { |
| 341 |
foreach ( $this->frontend_error_messages as $line ) { |
| 342 |
$output .= esc_html( $line ); |
| 343 |
$output .= '<br>'; |
| 344 |
} |
| 345 |
} |
| 346 |
|
| 347 |
return $output; |
| 348 |
} |
| 349 |
|
| 350 |
|
| 351 |
public function setup_plugin_with_filter_data() { |
| 352 |
if ( ! ( is_admin() || ( defined( 'WP_CLI' ) && WP_CLI ) ) ) { |
| 353 |
return; |
| 354 |
} |
| 355 |
|
| 356 |
$this->import_files = Helpers::validate_import_file_info( Helpers::apply_filters( 'library/import_files', array() ) ); |
| 357 |
|
| 358 |
$import_actions = new ImportActions(); |
| 359 |
$import_actions->register_hooks(); |
| 360 |
|
| 361 |
$importer_options = Helpers::apply_filters( 'library/importer_options', array( |
| 362 |
'fetch_attachments' => true, |
| 363 |
) ); |
| 364 |
|
| 365 |
$logger_options = Helpers::apply_filters( 'library/logger_options', array( |
| 366 |
'logger_min_level' => 'warning', |
| 367 |
) ); |
| 368 |
|
| 369 |
$logger = new Logger(); |
| 370 |
$logger->min_level = $logger_options['logger_min_level']; |
| 371 |
|
| 372 |
$this->importer = new Importer( $importer_options, $logger ); |
| 373 |
|
| 374 |
$this->plugin_installer = new PluginInstaller(); |
| 375 |
$this->plugin_installer->init(); |
| 376 |
} |
| 377 |
|
| 378 |
public function get_plugin_page_setup() { |
| 379 |
return $this->plugin_page_setup; |
| 380 |
} |
| 381 |
|
| 382 |
public function start_notice_output_capturing() { |
| 383 |
$screen = get_current_screen(); |
| 384 |
|
| 385 |
if ( false === strpos( $screen->base, $this->plugin_page_setup['menu_slug'] ) ) { |
| 386 |
return; |
| 387 |
} |
| 388 |
|
| 389 |
echo '<div class="library-notices-wrapper js-library-notice-wrapper">'; |
| 390 |
} |
| 391 |
|
| 392 |
public function finish_notice_output_capturing() { |
| 393 |
if ( is_network_admin() ) { |
| 394 |
return; |
| 395 |
} |
| 396 |
|
| 397 |
$screen = get_current_screen(); |
| 398 |
|
| 399 |
if ( false === strpos( $screen->base, $this->plugin_page_setup['menu_slug'] ) ) { |
| 400 |
return; |
| 401 |
} |
| 402 |
|
| 403 |
echo '</div><!-- /.library-notices-wrapper -->'; |
| 404 |
} |
| 405 |
|
| 406 |
public function get_plugin_settings_url( $query_parameters = [] ) { |
| 407 |
if ( empty( $this->plugin_page_setup ) ) { |
| 408 |
$this->plugin_page_setup = Helpers::get_plugin_page_setup_data(); |
| 409 |
} |
| 410 |
|
| 411 |
$parameters = array_merge( |
| 412 |
array( 'page' => $this->plugin_page_setup['menu_slug'] ), |
| 413 |
$query_parameters |
| 414 |
); |
| 415 |
|
| 416 |
$url = menu_page_url( $this->plugin_page_setup['parent_slug'], false ); |
| 417 |
|
| 418 |
if ( empty( $url ) ) { |
| 419 |
$url = self_admin_url( $this->plugin_page_setup['parent_slug'] ); |
| 420 |
} |
| 421 |
|
| 422 |
return add_query_arg( $parameters, $url ); |
| 423 |
} |
| 424 |
|
| 425 |
public function redirect_from_old_default_admin_page() { |
| 426 |
global $pagenow; |
| 427 |
|
| 428 |
if ( $pagenow == 'themes.php' && isset( $_GET['page'] ) && $_GET['page'] == 'pt-library' ) { |
| 429 |
wp_safe_redirect( $this->get_plugin_settings_url() ); |
| 430 |
exit; |
| 431 |
} |
| 432 |
} |
| 433 |
|
| 434 |
public function add_imported_terms( $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids ){ |
| 435 |
|
| 436 |
if ( ! isset( $this->imported_terms[ $taxonomy ] ) ) { |
| 437 |
$this->imported_terms[ $taxonomy ] = array(); |
| 438 |
} |
| 439 |
|
| 440 |
$this->imported_terms[ $taxonomy ] = array_unique( array_merge( $this->imported_terms[ $taxonomy ], $tt_ids ) ); |
| 441 |
} |
| 442 |
|
| 443 |
private function update_terms_count() { |
| 444 |
|
| 445 |
foreach ( $this->imported_terms as $tax => $terms ) { |
| 446 |
wp_update_term_count_now( $terms, $tax ); |
| 447 |
} |
| 448 |
} |
| 449 |
} |
| 450 |
|