'capability_here'
* To add a page to the network admin (wp-admin/network), use: 'network_admin_menu' => 'capability_here'
* To add a page to the user (wp-admin/user) admin, use: 'user_admin_menu' => 'capability_here'
*
* @since 2.0.0
* @var array
*/
protected $supported_panels = array(
'network_admin_menu' => 'manage_network',
);
/**
* The customer license, if it exists.
*
* @since 2.0.0
* @var object
*/
public $license;
/**
* The customer object, if it exists.
*
* @since 2.0.0
* @var object
*/
public $customer;
/**
* Is this an old install migrating.
*
* @since 2.0.0
* @var bool|null
*/
private ?bool $is_migration = null;
/**
* The integration object, if it exists.
*
* @since 2.2.0
* @var mixed
*/
protected $integration;
/**
* Overrides original construct method.
*
* We need to override the construct method to make sure
* we make the necessary changes to the Wizard page when it's
* being run for the first time.
*
* @since 2.0.0
* @return void
*/
public function __construct() {
if (!$this->is_core_loaded()) {
require_once wu_path('inc/functions/documentation.php');
/**
* Loads the necessary apis.
*/
WP_Ultimo()->load_public_apis();
$this->highlight_menu_slug = false;
$this->type = 'menu';
$this->position = 10_101_010;
$this->menu_icon = 'dashicons-wu-wp-ultimo';
add_action('admin_enqueue_scripts', array($this, 'register_scripts'));
} // end if;
parent::__construct();
add_action('admin_action_download_migration_logs', array($this, 'download_migration_logs'));
/*
* Serve the installers
*/
add_action('wp_ajax_wu_setup_install', array($this, 'setup_install'));
/*
* Load installers
*/
add_action('wu_handle_ajax_installers', array(Core_Installer::get_instance(), 'handle'), 10, 3);
add_action('wu_handle_ajax_installers', array(Default_Content_Installer::get_instance(), 'handle'), 10, 3);
add_action('wu_handle_ajax_installers', array(Migrator::get_instance(), 'handle'), 10, 3);
/*
* Redirect on activation
*/
add_action('wu_activation', array($this, 'redirect_to_wizard'));
} // end __construct;
/**
* Download the migration logs.
*
* @since 2.0.7
* @return void
*/
public function download_migration_logs() {
check_admin_referer('download_migration_logs', 'nonce');
$path = Logger::get_logs_folder();
$file = $path . Migrator::LOG_FILE_NAME . '.log';
$file_name = str_replace($path, '', $file);
header('Content-Type: application/octet-stream');
header("Content-Disposition: attachment; filename=$file_name");
header('Pragma: no-cache');
readfile($file);
exit;
} // end download_migration_logs;
/**
* Loads the extra elements we need on the wizard itself.
*
* @since 1.8.2
* @return void
*/
public function page_loaded() {
parent::page_loaded();
$this->license = \WP_Ultimo\License::get_instance()->get_license();
$this->customer = \WP_Ultimo\License::get_instance()->get_customer();
$this->set_settings();
} // end page_loaded;
/**
* Checks if this is a migration or not.
*
* @since 2.0.0
* @return boolean
*/
public function is_migration() {
if ($this->is_migration === null) {
$this->is_migration = Migrator::is_legacy_network();
} // end if;
return $this->is_migration;
} // end is_migration;
/**
* Adds missing setup from settings when WP Ultimo is not fully loaded.
*
* @since 2.0.0
* @return void
*/
public function set_settings() {
WP_Ultimo()->settings->default_sections();
} // end set_settings;
/**
* Redirects to the wizard, if we need to.
*
* @since 2.0.0
* @return void
*/
public function redirect_to_wizard() {
if (!\WP_Ultimo\Requirements::run_setup() && wu_request('page') !== 'wp-ultimo-setup') {
wp_redirect(wu_network_admin_url('wp-ultimo-setup'));
exit;
} // end if;
} // end redirect_to_wizard;
/**
* Handles the ajax actions for installers and migrators.
*
* @since 2.0.0
* @return void
*/
public function setup_install() {
global $wpdb;
if (!current_user_can('manage_network')) {
wp_send_json_error(new \WP_Error('not-allowed', __('Permission denied.', 'wp-ultimo')));
exit;
} // end if;
/*
* Load tables.
*/
WP_Ultimo()->tables = \WP_Ultimo\Loaders\Table_Loader::get_instance();
$installer = wu_request('installer', '');
/*
* Installers should hook into this filter
*/
$status = apply_filters('wu_handle_ajax_installers', true, $installer, $this);
if (is_wp_error($status)) {
wp_send_json_error($status);
} // end if;
wp_send_json_success();
} // end setup_install;
/**
* Check if the core was loaded.
*
* @since 2.0.0
* @return boolean
*/
public function is_core_loaded() {
return \WP_Ultimo\Requirements::met() && \WP_Ultimo\Requirements::run_setup();
} // end is_core_loaded;
/**
* Returns the logo for the wizard.
*
* @since 2.0.0
* @return string
*/
public function get_logo() {
return wu_get_asset('logo.png', 'img');
} // end get_logo;
/**
* Returns the title of the page.
*
* @since 2.0.0
* @return string Title of the page.
*/
public function get_title(): string {
return sprintf(__('Installation', 'wp-ultimo'));
} // end get_title;
/**
* Returns the title of menu for this page.
*
* @since 2.0.0
* @return string Menu label of the page.
*/
public function get_menu_title() {
return WP_Ultimo()->is_loaded() ? __('WP Ultimo Install', 'wp-ultimo') : __('WP Ultimo', 'wp-ultimo');
} // end get_menu_title;
/**
* Returns the sections for this Wizard.
*
* @since 2.0.0
* @return array
*/
public function get_sections() {
$allowed = \WP_Ultimo\License::get_instance()->allowed();
$sections = array(
'welcome' => array(
'title' => __('Welcome', 'wp-ultimo'),
'description' => implode('
', array(
__('...and thanks for choosing WP Ultimo!', 'wp-ultimo'),
__('This quick setup wizard will make sure your server is correctly setup, help you configure your new network, and migrate data from previous WP Ultimo versions if necessary.', 'wp-ultimo'),
__('You will also have the option of importing default content. It should take 10 minutes or less!', 'wp-ultimo')
)),
'next_label' => __('Get Started →', 'wp-ultimo'),
'back' => false,
),
'checks' => array(
'title' => __('Pre-install Checks', 'wp-ultimo'),
'description' => __('Now it is time to see if this machine has what it takes to run WP Ultimo well!', 'wp-ultimo'),
'next_label' => \WP_Ultimo\Requirements::met() ? __('Go to the Next Step →', 'wp-ultimo') : __('Check Again', 'wp-ultimo'),
'handler' => array($this, 'handle_checks'),
'back' => false,
'fields' => array(
'requirements' => array(
'type' => 'note',
'desc' => array($this, 'renders_requirements_table'),
)
),
),
'activation' => array(
'title' => __('License Activation', 'wp-ultimo'),
'description' => __('Let\'s make sure you are able to keep your copy up-to-date with our latest updates via admin panel notifications and more.', 'wp-ultimo'),
'handler' => array($this, 'handle_activation'),
'next_label' => __('Agree & Activate →', 'wp-ultimo'),
'back' => false,
'skip' => $allowed,
'fields' => array(
'terms' => array(
'type' => 'note',
'desc' => array($this, '_terms_of_support'),
),
'license_key' => array(
'type' => 'text',
'title' => __('License Key', 'wp-ultimo'),
'placeholder' => __('E.g. sk_***********', 'wp-ultimo'),
'tooltip' => __('Your WP Ultimo License Key', 'wp-ultimo'),
'desc' => array($this, '_desc_and_validation_error'),
'wrapper_classes' => $allowed ? 'wu-hidden' : '',
'html_attr' => array(
$allowed ? 'disabled' : 'data-none' => 'disabled',
),
),
'license' => array(
'wrapper_classes' => $allowed ? 'sm:wu-w-auto sm:wu-block' : 'sm:wu-w-auto wu-hidden',
'classes' => 'sm:wu--mx-6 sm:wu--mt-4 sm:wu--mb-6',
'type' => 'note',
'desc' => array($this, '_current_license'),
),
),
),
'installation' => array(
'title' => __('Installation', 'wp-ultimo'),
'description' => __('Now, let\'s update your database and install the Sunrise.php file, which are necessary for the correct functioning of WP Ultimo.', 'wp-ultimo'),
'next_label' => Core_Installer::get_instance()->all_done() ? __('Go to the Next Step →', 'wp-ultimo') : __('Install', 'wp-ultimo'),
'fields' => array(
'terms' => array(
'type' => 'note',
'desc' => fn() => $this->render_installation_steps(Core_Installer::get_instance()->get_steps(), false),
),
),
),
);
/*
* In case of migrations, add different sections.
*/
if ($this->is_migration()) {
$dry_run = wu_request('dry-run', true);
$next = true;
$errors = Migrator::get_instance()->get_errors();
$back_traces = Migrator::get_instance()->get_back_traces();
$next_label = __('Migrate!', 'wp-ultimo');
$description = __('No errors found during dry run! Now it is time to actually migrate!
We strongly recommend creating a backup of your database before moving forward with the migration.', 'wp-ultimo');
if ($dry_run) {
$next_label = __('Run Check', 'wp-ultimo');
$description = __('It seems that you were running WP Ultimo 1.X on this network. This migrator will convert the data from the old version to the new one.', 'wp-ultimo') . '
' . __('First, let\'s run a test migration to see if we can spot any potential errors.', 'wp-ultimo');
} // end if;
$fields = array(
'migration' => array(
'type' => 'note',
'desc' => fn() => $this->render_installation_steps(Migrator::get_instance()->get_steps(), false),
),
);
if ($errors) {
$subject = 'Errors on migrating my network';
$user = wp_get_current_user();
$message_lines = array(
'Hi there,',
sprintf('My name is %s.', $user->display_name),
sprintf('License Key: %s', License::get_instance()->get_license_key()),
'I tried to migrate my network from version 1 to version 2, but was not able to do it successfully...',
'Here are the error messages I got:',
sprintf('```%s%s%s```', PHP_EOL, implode(PHP_EOL, $errors), PHP_EOL),
sprintf('```%s%s%s```', PHP_EOL, $back_traces ? implode(PHP_EOL, $back_traces) : 'No backtraces found.', PHP_EOL),
'Kind regards.'
);
$message = implode(PHP_EOL . PHP_EOL, $message_lines);
$description = __('The dry run test detected issues during the test migration. Please, contact our support team to get help migrating from 1.X to version 2.', 'wp-ultimo');
$next = true;
$next_label = __('Try Again!', 'wp-ultimo');
$error_list = '' . __('List of errors detected:', 'wp-ultimo') . '
';
$errors[] = sprintf('
%1$s', __('Download migration error log', 'wp-ultimo'), add_query_arg(array(
'action' => 'download_migration_logs',
'nonce' => wp_create_nonce('download_migration_logs'),
), network_admin_url('admin.php')));
$errors[] = sprintf('
%1$s', __('Rollback to version 1.10.13', 'wp-ultimo'), add_query_arg(array(
'page' => 'wp-ultimo-rollback',
'version' => '1.10.13',
'type' => 'select-version',
), network_admin_url('admin.php')));
$error_list .= implode('
', $errors);
$fields = array_merge(array(
'errors' => array(
'type' => 'note',
'classes' => 'wu-flex-grow',
'desc' => function() use ($error_list) {
/** Reset errors */
Migrator::get_instance()->session->set('errors', array());
return sprintf('