<?php

namespace CleantalkSP\Updater;

use CleantalkSP\SpbctWP\Cron;
use CleantalkSP\SpbctWP\API;
use CleantalkSP\SpbctWP\Scanner\ScanningLog\ScanningLogFacade;
use CleantalkSP\SpbctWP\Variables\Cookie;
use CleantalkSP\SpbctWP\DB;
use CleantalkSP\SpbctWP\Helpers\Data;
use CleantalkSP\SpbctWP\VulnerabilityAlarm\VulnerabilityAlarm;

/**
 * Updater scripts handlers.
 * Updater::runUpdateScripts() generates functions calling from this methods list.
 *
 * @psalm-suppress UnusedClass
 */
class UpdaterScripts
{
    public static function updateTo_1_9_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        //Adding send logs cron hook if not exists
        if ( ! wp_next_scheduled('spbc_send_logs_hook') ) {
            wp_schedule_event(time() + 1800, 'hourly', 'spbc_send_logs_hook');
        }
        // Update Security FireWall cron hook
        if ( ! wp_next_scheduled('spbc_security_firewall_update_hook') ) {
            wp_schedule_event(time() + 1800, 'hourly', 'spbc_security_firewall_update_hook');
        }
        // Send logs cron hook
        if ( ! wp_next_scheduled('spbc_send_firewall_logs_hook') ) {
            wp_schedule_event(time() + 1800, 'hourly', 'spbc_send_firewall_logs_hook');
        }

        return;
    }

    public static function updateTo_1_10_0()  //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        wp_clear_scheduled_hook('spbc_send_logs_hourly_hook');
        wp_clear_scheduled_hook('spbc_send_daily_report');
        wp_clear_scheduled_hook('spbc_send_daily_report_hook');
        wp_clear_scheduled_hook('spbc_security_firewall_update_hourly_hook');
        wp_clear_scheduled_hook('spbc_send_firewall_logs_hourly_hook');

        wp_schedule_event(time() + 1800, 'hourly', 'spbc_send_logs_hook');
        wp_schedule_event(time() + 43200, 'daily', 'spbc_send_report_hook');
        wp_schedule_event(time() + 43200, 'daily', 'spbc_security_firewall_update_hook');
        wp_schedule_event(time() + 1800, 'hourly', 'spbc_send_firewall_logs_hook');
        wp_schedule_event(time() + 1800, 'hourly', 'spbc_access_key_notices_hook');
    }

    public static function updateTo_1_19_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        wp_clear_scheduled_hook('spbc_send_logs_hook');
        wp_clear_scheduled_hook('spbc_send_report_hook');
        wp_clear_scheduled_hook('spbc_security_firewall_update_hook');
        wp_clear_scheduled_hook('spbc_send_firewall_logs_hook');
        wp_clear_scheduled_hook('spbc_access_key_notices_hook');

        // Self cron system
        Cron::addTask('send_logs', 'spbc_send_logs', 3600, time() + 1800);
        Cron::addTask('send_report', 'spbc_send_daily_report', 86400, time() + 43200);
        Cron::addTask('firewall_update', 'spbc_security_firewall_update__init', 86400, time() + 43200);
        Cron::addTask('send_firewall_logs', 'spbc_send_firewall_logs', 3600, time() + 1800);
        Cron::addTask('access_key_notices', 'spbc_access_key_notices', 3600, time() + 3500);
    }

    public static function updateTo_1_20_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        wp_clear_scheduled_hook('spbc_access_key_notices_hook');
    }

    public static function updateTo_1_21_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;
        // Clearing errors because format changed
        $spbc->data['errors'] = array();
    }

    public static function updateTo_1_22_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;
        // Adding service ID and refreshing other account params
        if ( ! empty($spbc->settings['spbc_key']) ) {
            $result = API::method__notice_paid_till(
                $spbc->settings['spbc_key'],
                preg_replace('/http[s]?:\/\//', '', get_option('home'), 1),
                'security'
            );
            if ( empty($result['error']) ) {
                $spbc->data['notice_show']  = $result['show_notice'];
                $spbc->data['notice_renew'] = $result['renew'];
                $spbc->data['notice_trial'] = $result['trial'];
                $spbc->data['service_id']   = $result['service_id'];
                if ( SPBC_WPMS && is_main_site() ) {
                    $spbc->network_settings['service_id'] = $result['service_id'];
                    $spbc->save('network_settings');
                }
            }
        }
    }

    public static function updateTo_2_0_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        // Scanner's cron
        Cron::addTask('perform_scan_wrapper', 'spbc_perform_scan_wrapper', 86400, time() + 86400);
        // Drop existing table and create scanner's table
    }

    public static function updateTo_2_1_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;
        unset($spbc->data['errors']);
        $spbc->save('data');
    }

    public static function updateTo_2_6_2() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        Cron::updateTask('send_logs', 'spbc_send_logs', 3600, time() + 1800);
        Cron::updateTask('send_report', 'spbc_send_daily_report', 86400, time() + 43200);
        Cron::updateTask('firewall_update', 'spbc_security_firewall_update__init', 86400, time() + 43200);
        Cron::updateTask('send_firewall_logs', 'spbc_send_firewall_logs', 3600, time() + 1800);
        Cron::updateTask('access_key_notices', 'spbc_access_key_notices', 3600, time() + 3500);
        Cron::updateTask('perform_scan_wrapper', 'spbc_perform_scan_wrapper', 86400, time() + 43200);
    }

    public static function updateTo_2_8_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        // Preparing for IPv6
        if ( isset($spbc->data['cdn']) && $spbc->data['cdn'] ) {
            unset($spbc->data['cdn']);
        }
        if ( isset($spbc->data['private_networks']) && $spbc->data['private_networks'] ) {
            unset($spbc->data['private_networks']);
        }

        unset($spbc->data['scanner']['last_wp_version']);
        Cron::removeTask('scanner_scan_deep_core');
        Cron::removeTask('scanner_scan_deep_plugin');
    }

    public static function updateTo_2_13_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        update_option('spbc_plugins', array(), false);
        update_option('spbc_themes', array(), false);
    }

    public static function updateTo_2_14_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;
        $spbc->data['cron']['running'] = false;
    }

    public static function updateTo_2_15_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;
        $spbc->data['cron']['running'] = false;
        spbc_mu_plugin__install();
    }

    public static function updateTo_2_16_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;
        $spbc->data['cron']['running'] = false;
        spbc_mu_plugin__uninstall();
        spbc_mu_plugin__install();
    }

    public static function updateTo_2_17_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;
        $spbc->data['cron']['running'] = false;
    }

    public static function updateTo_2_22_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $wpdb, $spbc, $wp_version;

        // Set source_type = null for custom files
        // @psalm-suppress WpdbUnsafeMethodsIssue
        $wpdb->query(
            "UPDATE `" . SPBC_TBL_SCAN_FILES . "` SET source_type = NULL
		WHERE source_type = 'CORE' && real_full_hash IS NULL;"
        );

        // Set source = wordpress and version for core files
        // @psalm-suppress WpdbUnsafeMethodsIssue
        $wpdb->query(
            "UPDATE `" . SPBC_TBL_SCAN_FILES . "`
		SET source = 'wordpress',
			version = '$wp_version'
		WHERE source_type = 'CORE' && real_full_hash IS NOT NULL;"
        );

        // Updating version and source of plugins
        if ( $spbc->plugins === false ) {
            $spbc->plugins = array();
        }

        foreach ( $spbc->plugins as $name => $version ) {
            // @psalm-suppress WpdbUnsafeMethodsIssue
            $wpdb->query(
                "UPDATE `" . SPBC_TBL_SCAN_FILES . "`
                SET source = '$name',
                    version = '$version'
                WHERE path LIKE '%$name%' && real_full_hash IS NOT NULL;"
            );
        }

        // Updating version and source of themes
        if ( $spbc->themes === false ) {
            $spbc->themes = array();
        }

        foreach ( $spbc->themes as $name => $version ) {
            // @psalm-suppress WpdbUnsafeMethodsIssue
            $wpdb->query(
                "UPDATE `" . SPBC_TBL_SCAN_FILES . "`
                SET source_type = 'THEME',
                    source = '$name',
                    version = '$version'
                WHERE path LIKE '%$name%' && real_full_hash IS NOT NULL;"
            );
        }

        // @psalm-suppress WpdbUnsafeMethodsIssue
        $wpdb->query(
            "UPDATE `" . SPBC_TBL_SCAN_FILES . "`
		SET checked = 'YES_HEURISTIC'
		WHERE checked = 'YES' AND real_full_hash <> full_hash;"
        );

        // Cron fix
        $spbc->data['cron']['running'] = false;

        Cron::addTask('scanner_update_signatures', 'spbc_scanner__signatures_update', 86400, time() + 20);
        $spbc->error_delete('scan_modified', 'and_save_data');
    }

    public static function updateTo_2_24_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $wpdb;

        // @psalm-suppress WpdbUnsafeMethodsIssue
        $wpdb->query(
            "UPDATE `" . SPBC_TBL_SCAN_FILES . "`
		SET weak_spots = NULL,
			checked = 'NO'
		WHERE weak_spots IS NOT NULL;"
        );
    }

    public static function updateTo_2_25_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        $spbc->data['last_php_log_sent'] = 0;
        $spbc->save('data');

        Cron::addTask('send_php_logs', 'spbc_PHP_logs__send', 3600, time() + 300);
    }

    public static function updateTo_2_25_1() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        $spbc->data['last_php_log_sent'] = time();
        $spbc->save('data');
    }

    public static function updateTo_2_26_1() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        if ( file_exists(WPMU_PLUGIN_DIR . '/security-malware-firewall-mu.php') ) {
            unlink(WPMU_PLUGIN_DIR . '/security-malware-firewall-mu.php');
        }

        spbc_mu_plugin__install();
    }

    public static function updateTo_2_27() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        if ( file_exists(WPMU_PLUGIN_DIR . '/security-malware-firewall-mu.php') ) {
            unlink(WPMU_PLUGIN_DIR . '/security-malware-firewall-mu.php');
        }
        if ( file_exists(WPMU_PLUGIN_DIR . '/0security-malware-firewall-mu.php') ) {
            unlink(WPMU_PLUGIN_DIR . '/0security-malware-firewall-mu.php');
        }

        spbc_mu_plugin__install();
    }

    public static function updateTo_2_28_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        Cookie::set('spbc_is_logged_in', '0', time() - 30, '/');
    }

    public static function updateTo_2_30_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        if ( ! is_dir(SPBC_PLUGIN_DIR . 'backups') ) {
            mkdir(SPBC_PLUGIN_DIR . 'backups');
        }
    }

    public static function updateTo_2_31_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;
        Cron::removeTask('perform_scan_wrapper');
        Cron::removeTask('perform_scan_wrapper_act');

        $hour_minutes       = $spbc->settings['scanner__auto_start_manual_time']
            ? explode(':', $spbc->settings['scanner__auto_start_manual_time'])
            : explode(':', date('H:i'));
        $scanner_start_time =
            mktime(
                (int)$hour_minutes[0],
                (int)$hour_minutes[1]
            ) - $spbc->settings['scanner__auto_start_manual_tz'] * 3600 + 3600;

        Cron::addTask('scanner__launch', 'spbc_scanner__launch', 86400, $scanner_start_time);

        // Deletting all errors
        if ( isset($spbc->data['errors']) ) {
            unset($spbc->data['errors']);
        }
    }

    public static function updateTo_2_37_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;
        $spbc->error_delete('allow_url_fopen', true);
    }

    public static function updateTo_2_42_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;
        if ( SPBC_WPMS ) {
            $spbc->network_settings['waf__enabled']       = $spbc->default_network_settings['waf__enabled'];
            $spbc->network_settings['waf__xss_check']     = $spbc->default_network_settings['waf__xss_check'];
            $spbc->network_settings['waf__sql_check']     = $spbc->default_network_settings['waf__sql_check'];
            $spbc->network_settings['waf__file_check']    = $spbc->default_network_settings['waf__file_check'];
            $spbc->network_settings['waf__exploit_check'] = $spbc->default_network_settings['waf__exploit_check'];

            $spbc->save('network_settings');
        }
    }


    public static function updateTo_2_47_1() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        spbc_mu_plugin__install();
    }

    public static function updateTo_2_48_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $wpdb;

        if ( SPBC_WPMS ) {
            $initial_blog = get_current_blog_id();
            $blogs        = array_keys($wpdb->get_results('SELECT blog_id FROM ' . $wpdb->blogs, OBJECT_K));

            foreach ( $blogs as $blog ) {
                set_time_limit(30);

                switch_to_blog($blog);

                // Getting key
                $net_settings = get_site_option('spbc_network_settings');
                $settings     = $net_settings['allow_custom_key']
                    ? get_option('spbc_settings')
                    : $net_settings;

                // Update plugin status
                if ( ! empty($settings['spbc_key']) ) {
                    //Clearing all errors
                    delete_option('spbc_errors');

                    // Checking account status
                    $result = API::method__notice_paid_till(
                        $settings['spbc_key'],
                        preg_replace('/http[s]?:\/\//', '', get_option('home'), 1), // Site URL
                        'security'
                    );

                    $data              = get_option('spbc_data', array());
                    $data['key_is_ok'] = false;

                    // Passed without errors
                    if ( empty($result['error']) ) {
                        // Key is valid
                        if ( $result['valid'] ) {
                            $data['key_is_ok']        = true;
                            $data['user_token']       = isset($result['user_token']) ? $result['user_token'] : '';
                            $data['notice_show']      = $result['show_notice'];
                            $data['notice_renew']     = $result['renew'];
                            $data['notice_trial']     = $result['trial'];
                            $data['auto_update_app']  = isset($result['show_auto_update_notice']) ? $result['show_auto_update_notice'] : 0;
                            $data['service_id']       = $result['service_id'];
                            $data['moderate']         = $result['moderate'];
                            $data['auto_update_app '] = isset($result['auto_update_app']) ? $result['auto_update_app'] : 0;
                            $data['license_trial']    = isset($result['license_trial']) ? $result['license_trial'] : 0;
                            $data['account_name_ob']  = isset($result['account_name_ob']) ? $result['account_name_ob'] : '';
                        }
                    }

                    update_option('spbc_data', $data);
                }
            }

            switch_to_blog($initial_blog);
        }
    }


    public static function updateTo_2_49_2() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;
        $spbc->settings['block_delay__5_fails'] = 3600;
        $spbc->save('settings');
    }

    public static function updateTo_2_55_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;
        $spbc->remote_calls['update_security_firewall']             = array('last_call' => 0, 'cooldown' => 300);
        $spbc->remote_calls['update_security_firewall__write_base'] = array('last_call' => 0, 'cooldown' => 0);
        $spbc->save('remote_calls', true, false);
    }

    public static function updateTo_2_60_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc, $wpdb;

        $spbc->settings['scanner__auto_start_manual_time'] = ! preg_match(
            '@\d{2}:\d{2}@',
            $spbc->settings['scanner__auto_start_manual_time']
        )
            ? $spbc->settings['scanner__auto_start_manual_time'] = '09:00'
            : $spbc->settings['scanner__auto_start_manual_time'];
    }

    public static function updateTo_2_62_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        $spbc->settings['bfp__allowed_wrong_auths']   = 5;
        $spbc->settings['bfp__delay__1_fails']        = 3;
        $spbc->settings['bfp__delay__5_fails']        = 10;
        $spbc->settings['bfp__block_period__5_fails'] = isset($spbc->settings['block_timer__5_fails'])
            ? $spbc->settings['block_timer__5_fails']
            : 3600;
        $spbc->settings['bfp__count_interval']        = 900;
        $spbc->save('settings');

        // Updating cron tasks
        $tasks = get_option(SPBC_CRON);
        if ( $tasks ) {
            foreach ( $tasks as &$task ) {
                $task['params']     = isset($task['params']) ? $task['params'] : array();
                $task['last_call']  = isset($task['last_call']) ? $task['last_call'] : 0;
                $task['processing'] = isset($task['processing']) ? $task['processing'] : false;
            }
        }
        update_option(SPBC_CRON, $tasks);
    }

    public static function updateTo_2_63_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        // Updating cron tasks
        $tasks = get_option(SPBC_CRON);
        if ( isset($tasks['firewall_update']) ) {
            $tasks['firewall_update']['next_call'] += rand(0, 3600);
        }
        update_option(SPBC_CRON, $tasks);

        delete_option('spbc_deactivation_in_process');
    }

    public static function updateTo_2_64_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc, $wpdb;

        // Old setting name => New setting name
        $keys_map = array(
            '2fa_enable'                             => '2fa__enable',
            '2fa_roles'                              => '2fa__roles',
            'bfp_allowed_wrong_auths'                => 'bfp__allowed_wrong_auths',
            'bfp_delay__1_fails'                     => 'bfp__delay__1_fails',
            'bfp_delay__5_fails'                     => 'bfp__delay__5_fails',
            'bfp_block_period__5_fails'              => 'bfp__block_period__5_fails',
            'bfp_count_interval'                     => 'bfp__count_interval',
            'custom_key'                             => 'misc__custom_key',
            'traffic_control_enabled'                => 'traffic_control__enabled',
            'traffic_control_autoblock_amount'       => 'traffic_control__autoblock_amount',
            'traffic_control_autoblock_period'       => 'traffic_control__autoblock_period',
            'scanner_auto_start'                     => 'scanner__auto_start',
            'scanner_auto_start_manual'              => 'scanner__auto_start_manual',
            'scanner_auto_start_manual_time'         => 'scanner__auto_start_manual_time',
            'scanner_auto_start_manual_tz'           => 'scanner__auto_start_manual_tz',
            'scanner_outbound_links'                 => 'scanner__outbound_links',
            'scanner_outbound_links_mirrors'         => 'scanner__outbound_links_mirrors',
            'scanner_heuristic_analysis'             => 'scanner__heuristic_analysis',
            'scanner_signature_analysis'             => 'scanner__signature_analysis',
            'scanner_auto_cure'                      => 'scanner__auto_cure',
            'scanner_frontend_analysis'              => 'scanner__frontend_analysis',
            'scanner_dir_exclusions'                 => 'scanner__dir_exclusions',
            'waf_enabled'                            => 'waf__enabled',
            'waf_xss_check'                          => 'waf__xss_check',
            'waf_sql_check'                          => 'waf__sql_check',
            'waf_file_check'                         => 'waf__file_check',
            'waf_exploit_check'                      => 'waf__exploit_check',
            'backend_logs_enable'                    => 'misc__backend_logs_enable',
            'set_cookies'                            => 'data__set_cookies',
            'disable_xmlrpc'                         => 'wp__disable_xmlrpc',
            'disable_rest_api_for_non_authenticated' => 'wp__disable_rest_api_for_non_authenticated',
            'forbid_to_show_in_iframes'              => 'misc__forbid_to_show_in_iframes',
            'show_link_in_login_form'                => 'misc__show_link_in_login_form',
            'additional_headers'                     => 'data__additional_headers',
            'use_buitin_http_api'                    => 'wp__use_builtin_http_api',
            'complete_deactivation'                  => 'misc__complete_deactivation',
        );

        if ( is_multisite() ) {
            $initial_blog = get_current_blog_id();
            $blogs        = array_keys($wpdb->get_results('SELECT blog_id FROM ' . $wpdb->blogs, OBJECT_K));
            foreach ( $blogs as $blog ) {
                switch_to_blog($blog);

                $settings = get_option('spbc_settings');

                if ( $settings ) {
                    // replacing old key to new keys
                    foreach ( $settings as $key => $value ) {
                        if ( array_key_exists($key, $keys_map) ) {
                            $_settings[$keys_map[$key]] = $value;
                        } else {
                            $_settings[$key] = $value;
                        }
                    }
                    update_option('spbc_settings', $_settings);
                }
            }
            switch_to_blog($initial_blog);
        } else {
            $spbc->data['current_settings_template_id']   = null;
            $spbc->data['current_settings_template_name'] = null;
            $spbc->save('data');

            $settings = (array)$spbc->settings;

            if ( $settings ) {
                // replacing old key to new keys
                foreach ( $settings as $key => $value ) {
                    if ( array_key_exists($key, $keys_map) ) {
                        $_settings[$keys_map[$key]] = $value;
                    } else {
                        $_settings[$key] = $value;
                    }
                }

                $spbc->settings = $_settings;
                $spbc->save('settings');
            }
        }
    }

    public static function updateTo_2_65_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $wpdb, $spbc;

        // Perform all sqls for each blog
        if ( SPBC_WPMS ) {
            // Get all blogs
            $initial_blog = get_current_blog_id();
            $blogs        = array_keys($wpdb->get_results('SELECT blog_id FROM ' . $wpdb->blogs, OBJECT_K));

            foreach ( $blogs as $blog ) {
                switch_to_blog($blog);
                $spbc->settings['admin_bar__show']                 = 1;
                $spbc->settings['admin_bar__users_online_counter'] = 1;
                $spbc->settings['admin_bar__brute_force_counter']  = 1;
                $spbc->settings['admin_bar__firewall_counter']     = 1;
                $spbc->settings['monitoring__users']               = 1;
                $spbc->save('settings');
            }
            switch_to_blog($initial_blog);
        } else {
            $spbc->settings['admin_bar__show']                 = 1;
            $spbc->settings['admin_bar__users_online_counter'] = 1;
            $spbc->settings['admin_bar__brute_force_counter']  = 1;
            $spbc->settings['admin_bar__firewall_counter']     = 1;
            $spbc->settings['monitoring__users']               = 1;
            $spbc->save('settings');
        }
    }

    public static function updateTo_2_66_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        unset($spbc->remote_calls['update_security_firewall__write_base']);
        $spbc->remote_calls['update_security_firewall__worker'] = array('last_call' => 0, 'cooldown' => 1);
        $spbc->remote_calls['debug']                            = array('last_call' => 0, 'cooldown' => 1);
        $spbc->save('remote_calls', true, false);

        Cron::updateTask('firewall_update', 'spbc_security_firewall_update__init', 86400);
    }

    public static function updateTo_2_66_1() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        $task = Cron::getTask('firewall_update');
        Cron::updateTask(
            'firewall_update',
            'spbc_security_firewall_update__init',
            isset($task['period']) ? $task['period'] : time() + 42300,
            isset($task['next_call']) ? $task['next_call'] : time() + 42300
        );
    }

    public static function updateTo_2_66_2() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;
        $spbc->error_delete('firewall_update', 'save_data', 'cron');
    }

    public static function updateTo_2_72_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        $spbc->data['scanner']['last_scan'] = isset($spbc->data['scanner']['last_scan']) ? $spbc->data['scanner']['last_scan'] : 0;
        $spbc->data['ms__key_tries']        = 0;
        $spbc->save('data');

        if ( $spbc->is_multisite ) {
            $spbc->network_settings = array_merge((array)$spbc->network_settings, $spbc->default_network_settings);
            $spbc->network_data     = array_merge((array)$spbc->network_data, $spbc->default_network_data);
            $spbc->save('network_settings');
            $spbc->save('network_data');
        }
    }

    public static function updateTo_2_72_2() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        $spbc->fw_stats['is_on_maintenance'] = false;
        $spbc->save('fw_stats', true, false);
    }

    public static function updateTo_2_73_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        Data::remove(\CleantalkSP\Variables\Server::get('DOCUMENT_ROOT') . '/fw_filesindex.php');
        Data::remove(\CleantalkSP\Variables\Server::get('DOCUMENT_ROOT') . '/fw_files');
        Data::remove(SPBC_PLUGIN_DIR . '/fw_files');

        // Adding possible missing params to tasks
        $cron_option = get_option('spbc_cron');
        if ( $cron_option ) {
            foreach ( $cron_option as $_task => &$details ) {
                $details['processing'] = isset($details['processing']) ? $details['processing'] : false;
                $details['last_call']  = isset($details['last_call']) ? $details['last_call'] : 0;
            }
        }
        update_option('spbc_cron', $cron_option);

        // New setting "List unknown files"
        $spbc->settings['scanner__list_unknown'] = 0;
        $spbc->save('settings');

        // Deleting useless data
        if ( isset($spbc->data['cron']) ) {
            unset($spbc->data['cron']);
            $spbc->save('data');
        }
    }

    public static function updateTo_2_74_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        Data::remove(\CleantalkSP\Variables\Server::get('DOCUMENT_ROOT') . '/fw_filesindex.php');
        Data::remove(\CleantalkSP\Variables\Server::get('DOCUMENT_ROOT') . '/fw_files');
        Data::remove(SPBC_PLUGIN_DIR . '/fw_files');

        // Adding possible missing params to tasks
        $cron_option = get_option('spbc_cron');
        if ( $cron_option ) {
            foreach ( $cron_option as $_task => &$details ) {
                $details['processing'] = isset($details['processing']) ? $details['processing'] : false;
                $details['last_call']  = isset($details['last_call']) ? $details['last_call'] : 0;
            }
            unset($details);
        }
        update_option('spbc_cron', $cron_option);

        // Deleting useless data
        if ( isset($spbc->data['cron']) ) {
            unset($spbc->data['cron']);
            $spbc->save('data');
        }

        // Updating hidden option
        $spbc->settings['monitoring__users'] = 1;
        $spbc->save('settings');
    }

    public static function updateTo_2_75_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        // Clear these options because new format was implemented
        $spbc->plugings = array();
        $spbc->save('plugins', true, false);
        $spbc->themes = array();
        $spbc->save('themes', true, false);

        // New listing files
        $spbc->settings['scanner__important_files_listing'] = 0;
        $spbc->save('settings');

        $spbc->scanner_listing = array('accessible_urls' => array(),);
        $spbc->save('scanner_listing', true, false);

        $spbc->remote_calls['scanner__check_listing'] = array('last_call' => 0,);
        $spbc->save('remote_calls', true, false);

        // New domain exceptions
        $spbc->settings['scanner__frontend_analysis__domains_exclusions'] = implode(
            "\n",
            array(
                'googletagmanager.com',
                'google.com',
                'twitter.com',
                'youtube.com',
                'youtube-nocookie.com',
                'img.youtube.com',
                'rutube.ru',
                'dailymotion.com',
                'yandex.ru',
                'flikr.com',
                'facebook',
                'vimeo.com',
                'metacafe.com',
                'yahoo.com',
                'mailchimp.com',
                'mail.ru',
                'ok.ru',
                'vk.com',
            )
        );
        $spbc->save('settings');
    }

    public static function updateTo_2_76_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;
        $spbc->settings['scanner__list_unknown__older_than'] = 1;
        $spbc->save('settings');
    }

    public static function updateTo_2_80_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        // New setting
        $spbc->settings['waf__file_check__uploaded_plugins'] = 0;
        $spbc->save('settings');

        // New remote calls
        $spbc->remote_calls['scanner__check_file']            = array('last_call' => 0, 'cooldown' => 0);
        $spbc->remote_calls['scanner__check_file__heuristic'] = array('last_call' => 0, 'cooldown' => 0);
        $spbc->remote_calls['scanner__check_file__signature'] = array('last_call' => 0, 'cooldown' => 0);
        $spbc->save('remote_calls', true, false);
    }

    public static function updateTo_2_82_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        // Default parameter there_was_signature_treatment
        $spbc->settings['there_was_signature_treatment'] = 0;
        $spbc->save('settings');

        // START OF cleaning from heuristic results
        $heuristic_marked_files = DB::getInstance()->fetchAll(
            'SELECT weak_spots, checked, status, severity, fast_hash'
            . ' FROM ' . SPBC_TBL_SCAN_FILES
            . ' WHERE '
            . ' STATUS NOT IN ("APROVED","APPROVED_BY_CT","QUARANTINED") AND'
            . '    weak_spots LIKE "%DANGER%"'
            . ' OR weak_spots LIKE "%DANGER%"'
            . ' OR weak_spots LIKE "%SUSPICIOUS%";'
        );

        if ( empty($heuristic_marked_files) ) {
            return;
        }

        foreach ( $heuristic_marked_files as &$file ) {
            // Processing weak_spots
            $file['weak_spots'] = json_decode($file['weak_spots'], true);
            unset(
                $file['weak_spots']['CRITICAL'],
                $file['weak_spots']['DANGER'],
                $file['weak_spots']['SUSPICIOUS']
            );
            $file['weak_spots'] = ! empty($file['weak_spots'])
                ? json_encode($file['weak_spots'])
                : 'NULL';

            // Processing checked
            $file['checked'] = $file['checked'] === 'YES' || $file['checked'] === 'YES_SIGNATURE'
                ? 'YES_SIGNATURE'
                : 'NO';

            // Processing status
            $file['status'] = $file['weak_spots'] !== 'NULL'
                ? $file['status']
                : 'OK';

            // Processing severity
            $file['severity'] = $file['weak_spots'] !== 'NULL'
                ? $file['severity']
                : 'NULL';

            $file = '(\'' . implode("','", $file) . '\')';
            $file = str_replace('\'NULL\'', 'NULL', $file);
        }
        unset($file);

        DB::getInstance()->execute(
            'INSERT INTO ' . SPBC_TBL_SCAN_FILES
                . ' (weak_spots, checked, status, severity, fast_hash)'
                . ' VALUES ' . implode(',', $heuristic_marked_files)
            . ' ON DUPLICATE KEY UPDATE'
                . ' weak_spots = VALUES(weak_spots),'
                . ' checked = VALUES(checked),'
                . ' status = VALUES(status),'
                . ' severity = VALUES(severity);'
        );
        // END OF cleaning from heuristic results
    }

    public static function updateTo_2_86_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        $spbc->data['backup_for_heuristic_setting']    = $spbc->settings['scanner__heuristic_analysis'];
        $spbc->settings['scanner__heuristic_analysis'] = 0;
        $spbc->save('settings');
        $spbc->save('data');
    }

    public static function updateTo_2_86_1() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        if ( isset($spbc->data['backup_for_heuristic_setting']) ) {
            $spbc->settings['scanner__heuristic_analysis'] = $spbc->data['backup_for_heuristic_setting'];
            unset($spbc->data['backup_for_heuristic_setting']);
            $spbc->save('settings');
            $spbc->save('data');
        }
    }

    /**
     * Update to 2.87. Runs SPBC_TBL_SCAN_FILES table alteration to move "checked" column condition
     * to the brand new columns "checked_heuristic" and "checked_signatures"
     */
    public static function updateTo_2_87_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        // Adding info about extra package
        $spbc->data['extra_package']['backend_logs'] = 1;

        // New settings for custom block message
        $spbc->data['fw__custom_message']          = '';

        // Adding new remote call 'perform_service_get'
        $spbc->remote_calls['perform_service_get'] = array('last_call' => 0,);
        // Firewall
        $spbc->save('remote_calls');
        $spbc->save('settings');
        $spbc->save('data');

        // extracting fo files needs to update
        $scanned_files = DB::getInstance()->fetchAll(
            'SELECT full_hash, checked'
            . ' FROM ' . SPBC_TBL_SCAN_FILES
            . ' WHERE '
            . ' checked <> \'NO\''
        );

        if ( empty($scanned_files) ) {
            return;
        }

        $hashes_to_update = array();
        foreach ( $scanned_files as $file ) {
            $hashes_to_update[$file['checked']][] = $file['full_hash'];
        }

        $signs_of_file_checked_status = array(
            "YES" => array('\'1\'', '\'1\''),
            "YES_SIGNATURE" => array('\'1\'', '\'0\''),
            "YES_HEURISTIC" => array('\'0\'', '\'1\''),
        );

        foreach ( $signs_of_file_checked_status as $status => $signs ) {
            if ( !empty($hashes_to_update[$status]) ) {
                /** @var list<string> $hashes_escaped */
                $hashes_escaped = array_map(function ($v): string {
                    $value = is_scalar($v) ? (string) $v : '';
                    $escaped = esc_sql($value);
                    return is_string($escaped) ? $escaped : '';
                }, $hashes_to_update[$status]);
                $hashes_to_update[$status] = '\'' . implode("','", $hashes_escaped) . '\'';
                $queries[] = 'UPDATE ' . SPBC_TBL_SCAN_FILES
                    . ' SET'
                    . ' checked_signatures=' . $signs[0] . ','
                    . ' checked_heuristic=' . $signs[1]
                    . ' WHERE full_hash IN (' . $hashes_to_update[$status] . ')';
            }
        }

        if ( !empty($queries) ) {
            foreach ( $queries as $query ) {
                if ( $query !== '\'\'' ) {
                    DB::getInstance()->execute($query);
                }
            }
        }

        $unhandled_files = DB::getInstance()->fetchAll(
            'SELECT full_hash, checked'
            . ' FROM ' . SPBC_TBL_SCAN_FILES
            . ' WHERE '
            . ' checked <> \'NO\' AND checked_signatures = \'0\' AND checked_heuristic = \'0\''
        );

        if ( empty($unhandled_files) ) {
            $delete_row_query__checked =
                'ALTER TABLE ' . SPBC_TBL_SCAN_FILES
                . ' DROP COLUMN checked';
            DB::getInstance()->execute($delete_row_query__checked);
        }

        // END OF cleaning from heuristic results
    }

    public static function updateTo_2_88_2() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        $spbc->remote_calls['post_api_key'] = array('last_call' => 0);
        $spbc->save('remote_calls', true, false);
    }

    public static function updateTo_2_94_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        // Searching doubles
        $sql_search_doubles = '
            SELECT page_id
            FROM ' . SPBC_TBL_SCAN_FRONTEND . '
            GROUP BY page_id
            HAVING COUNT(page_id) > 1';
        $doubles = DB::getInstance()->execute($sql_search_doubles);

        if ($doubles) {
            // Create temp table like SPBC_TBL_SCAN_FRONTEND
            $sql_create_temp_table = '
                CREATE TABLE ' . SPBC_TBL_SCAN_FRONTEND . '_temp
                LIKE ' . SPBC_TBL_SCAN_FRONTEND;
            DB::getInstance()->execute($sql_create_temp_table);

            // Insert doubles
            $sql_insert_doubles = '
                INSERT INTO ' . SPBC_TBL_SCAN_FRONTEND . '_temp
                SELECT DISTINCT * FROM ' . SPBC_TBL_SCAN_FRONTEND . '
                GROUP BY page_id
                HAVING COUNT(page_id) > 1';
            DB::getInstance()->execute($sql_insert_doubles);

            // Delete from SPBC_TBL_SCAN_FRONTEND doubles
            $sql_delete_doubles = '
                DELETE FROM ' . SPBC_TBL_SCAN_FRONTEND . '
                WHERE page_id IN (
                    SELECT page_id
                    FROM ' . SPBC_TBL_SCAN_FRONTEND . '_temp
                )';
            DB::getInstance()->execute($sql_delete_doubles);

            // Insert doubles to SPBC_TBL_SCAN_FRONTEND
            $sql_insert_doubles = '
                INSERT INTO ' . SPBC_TBL_SCAN_FRONTEND . '
                SELECT *
                FROM ' . SPBC_TBL_SCAN_FRONTEND . '_temp';
            DB::getInstance()->execute($sql_insert_doubles);

            // Drop temp table
            DB::getInstance()->execute('DROP TABLE ' . SPBC_TBL_SCAN_FRONTEND . '_temp');
        }

        $sql_add_primary_key =
        'ALTER TABLE ' . SPBC_TBL_SCAN_FRONTEND
        . '  ADD PRIMARY KEY (page_id)';
        DB::getInstance()->execute($sql_add_primary_key);
    }

    public static function updateTo_2_96_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        $spbc->data['unsafe_permissions'] = array(
            'files' => array(),
            'dirs' => array(),
        );
        $spbc->save('data');
    }

    public static function updateTo_2_97_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        if (!isset($spbc->data['scanner']['first_scan__front_end'])) {
            $spbc->data['scanner']['first_scan__front_end'] = 1;
            $spbc->save('data');
        }
    }

    public static function updateTo_2_98_1() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        $spbc->remote_calls['secfw_send_logs'] = array('last_call' => 0);
        $spbc->save('remote_calls', true, false);
    }

    public static function updateTo_2_99_1() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        $spbc->settings['traffic_control__exclude_authorised_users'] = 0;
        $spbc->settings['traffic_control__autoblock_timeframe'] = 3600;
        $spbc->save('settings');
    }

    public static function updateTo_2_100_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        $spbc->data['secfw_data_files_info'] = array();
        $spbc->save('data');
    }

    public static function updateTo_2_102_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        ScanningLogFacade::clearLog();
    }

    public static function updateTo_2_104_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        $spbc->data['scanner']['scanner_start_local_date'] = null;
        $spbc->save('data');
    }

    public static function updateTo_2_105_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        $spbc->data['site_utc_offset_in_seconds'] = 0;
        $spbc->save('data');
    }

    public static function updateTo_2_106_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        if (isset($spbc->settings['traffic_control__autoblock_period'])) {
            if ((int)$spbc->settings['traffic_control__autoblock_period'] === 180) {
                $spbc->settings['traffic_control__autoblock_period'] = 300;
            }
            if ((int)$spbc->settings['traffic_control__autoblock_period'] === 600) {
                $spbc->settings['traffic_control__autoblock_period'] = 900;
            }
        }

        $spbc->save('settings');
    }

    public static function updateTo_2_108_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        $check_queue_of_manual_analysis_query =
            'SELECT fast_hash FROM ' . SPBC_TBL_SCAN_FILES
            . ' WHERE '
            . 'last_sent IS NOT NULL '
            . 'AND pscan_processing_status IS NULL '
            . 'AND status NOT IN ("APPROVED_BY_CT") '
            . 'AND analysis_status = "NEW" ';

        $result = DB::getInstance()->fetchAll($check_queue_of_manual_analysis_query);

        if ( !empty($result) && is_array($result) ) {
            foreach ($result as $_key => $value) {
                $hashes[] = '"' . esc_sql($value['fast_hash']) . '"';
            }

            $sql_in_string = '(' . implode(',', $hashes) . ')';

            $update_sql =
                'UPDATE ' . SPBC_TBL_SCAN_FILES
                . ' SET '
                . 'last_sent = ' . current_time('timestamp') . ', '
                . 'pscan_pending_queue = 1, '
                . 'analysis_status = NULL '
                . 'WHERE fast_hash IN ' . $sql_in_string;

            $result = DB::getInstance()->execute($update_sql);

            if ($result) {
                \CleantalkSP\SpbctWP\Cron::updateTask('scanner_resend_pscan_files', 'spbc_scanner_resend_pscan_files', 300, time() + 120);
            }
        }


        //remove mscan task
        \CleantalkSP\SpbctWP\Cron::removeTask('resend_files_for_analysis');
    }

    public static function updateTo_2_110_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        Cron::addTask('security_log_clear', 'spbc_security_log_clear', 86400, time() + 43200);
    }

    public static function updateTo_2_114_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        // New remote calls
        $spbc->remote_calls['scanner__check_dir']            = array('last_call' => 0, 'cooldown' => 0);
        $spbc->save('remote_calls', true, false);
    }

    public static function updateTo_2_117_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        $sql_add_new_status =
            'ALTER TABLE ' . SPBC_TBL_SCAN_FRONTEND
            . ' MODIFY status enum (\'UNKNOWN\', \'OK\', \'APROVED\', \'APPROVED_BY_CT\', \'DENIED_BY_CT\', \'MODIFIED\', \'INFECTED\', \'QUARANTINED\', \'DENIED_BY_CLOUD\', \'APPROVED_BY_CLOUD\') DEFAULT \'UNKNOWN\' NOT NULL';
        DB::getInstance()->execute($sql_add_new_status);
    }

    public static function updateTo_2_117_2() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        $spbc->settings['wp__dashboard_widget__show'] = 1;
        $spbc->save('settings');
    }

    public static function updateTo_2_120_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        delete_option('spbc_login_attempts');
    }

    public static function updateTo_2_121_1() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        $spbc->settings['waf_blocker__enabled'] = 0;
        $spbc->save('settings');
    }

    public static function updateTo_2_124_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        if ( ! isset($spbc->data['display_scanner_warnings']['signatures']) ) {
            $spbc->settings['display_scanner_warnings']['signatures'] = false;
            $spbc->save('data');
        }
    }

    public static function updateTo_2_124_1() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        if ( ! isset($spbc->data['scanner']['scanned_total']) ) {
            $spbc->data['scanner']['scanned_total'] = 0;
            $spbc->save('data');
        }
    }

    public static function updateTo_2_125_1()  //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        /*
         * Rename APROVED status to APPROVED_BY_USER
         */

        //change temp format of status
        $sql_add_new_temp_status =
            'ALTER TABLE ' . SPBC_TBL_SCAN_FILES
            . ' MODIFY status enum (\'UNKNOWN\',\'OK\', \'APROVED\', \'APPROVED_BY_USER\',\'APPROVED_BY_CT\',
            \'DENIED_BY_CT\',\'MODIFIED\',\'INFECTED\',\'QUARANTINED\',\'DENIED_BY_CLOUD\',\'APPROVED_BY_CLOUD\') 
            DEFAULT \'UNKNOWN\' NOT NULL';
        DB::getInstance()->execute($sql_add_new_temp_status);

        //set new status for old records
        $sql_rename_status = 'UPDATE ' . SPBC_TBL_SCAN_FILES . ' SET STATUS = \'APPROVED_BY_USER\' WHERE STATUS = \'APROVED\';';
        DB::getInstance()->execute($sql_rename_status);

        //set new format of status
        $sql_set_new_format =
            'ALTER TABLE ' . SPBC_TBL_SCAN_FILES
            . ' MODIFY status enum (\'UNKNOWN\',\'OK\', \'APPROVED_BY_USER\',\'APPROVED_BY_CT\',
            \'DENIED_BY_CT\',\'MODIFIED\',\'INFECTED\',\'QUARANTINED\',\'DENIED_BY_CLOUD\',\'APPROVED_BY_CLOUD\') 
            DEFAULT \'UNKNOWN\' NOT NULL';
        DB::getInstance()->execute($sql_set_new_format);

        /*
         * Refactor all the heuristic CRITICAL statuses to SUSPICIOUS if there is:
         *  - no cloud decision
         *  - no signatures threatments
         */
        $sql_get_heuristics_files = 'SELECT fast_hash, weak_spots
            FROM ' . SPBC_TBL_SCAN_FILES . '
            WHERE
            STATUS = "INFECTED" AND
            severity IN (\'CRITICAL\', \'DANGER\')
            AND weak_spots NOT LIKE "%SIGNATURES%"
            AND pscan_status IS NULL';
        $heuristic_files_to_reformat = DB::getInstance()->fetchAll($sql_get_heuristics_files, ARRAY_A);


        if ( !empty($heuristic_files_to_reformat) ) {
            foreach ($heuristic_files_to_reformat as $_file => &$data) {
                if (!empty($data['weak_spots']) && strpos($data['weak_spots'], 'CRITICAL') !== false) {
                    $new_weakspots = str_replace(array('CRITICAL','DANGER'), 'SUSPICIOUS', $data['weak_spots']);
                    $new_weakspots_esc = esc_sql($new_weakspots);
                    $fast_hash_esc = esc_sql($data['fast_hash']);
                    $sql_update_heuristic_file = 'UPDATE ' . SPBC_TBL_SCAN_FILES
                        . ' SET severity = \'SUSPICIOUS\', weak_spots = \'' . $new_weakspots_esc . '\''
                        . ' WHERE fast_hash = \'' . $fast_hash_esc . '\';';
                    DB::getInstance()->execute($sql_update_heuristic_file);
                }
            }
        }
    }

    public static function updateTo_2_126_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $wpdb;

        if ( is_multisite() ) {
            $initial_blog = get_current_blog_id();
            $blogs = array_keys($wpdb->get_results('SELECT blog_id FROM ' . $wpdb->blogs, OBJECT_K));
            // Deleting data from each blog
            foreach ( $blogs as $blog ) {
                switch_to_blog($blog);
                // @psalm-suppress WpdbUnsafeMethodsIssue
                $wpdb->query('DROP TABLE IF EXISTS ' . $wpdb->prefix . 'spbc_firewall__personal_ips');
            }
            switch_to_blog($initial_blog);
        } else {
            // @psalm-suppress WpdbUnsafeMethodsIssue
            $wpdb->query('DROP TABLE IF EXISTS ' . $wpdb->prefix . 'spbc_firewall__personal_ips');
        }
        // @psalm-suppress WpdbUnsafeMethodsIssue
        $wpdb->query('DROP TABLE IF EXISTS ' . $wpdb->base_prefix . 'spbc_firewall_data');
    }

    public static function updateTo_2_126_1() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        Cron::addTask('check_vulnerabilities', 'spbc_security_check_vulnerabilities', 86400, time() + 100);

        if ( ! isset($spbc->settings['vulnerability_check__enable_cron']) ) {
            $spbc->settings['vulnerability_check__enable_cron'] = 1;
        }
        if ( ! isset($spbc->settings['vulnerability_check__test_before_install']) ) {
            $spbc->settings['vulnerability_check__test_before_install'] = 1;
        }
        if ( ! isset($spbc->settings['vulnerability_check__warn_on_modules_pages']) ) {
            $spbc->settings['vulnerability_check__warn_on_modules_pages'] = 1;
        }

        $spbc->save('settings');
    }

    public static function migrateDbData_2_128_1() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $wpdb;

        $current_timestamp = current_time('timestamp');
        $sql = "
            UPDATE %s
               SET pscan_status = CASE analysis_status 
                                  WHEN 'NEW' THEN NULL
                                  WHEN 'SAFE' THEN 'SAFE'
                                  WHEN 'DANGEROUS' THEN 'DANGEROUS'
                                  ELSE pscan_status
                                  END,
               pscan_processing_status = NULL,
               pscan_pending_queue = NULL,
               pscan_balls = NULL,
               pscan_file_id = NULL,
               last_sent = CASE analysis_status 
                                  WHEN 'NEW' THEN NULL
                                  ELSE $current_timestamp
                                  END
             WHERE analysis_status IN('NEW', 'SAFE', 'DANGEROUS');
        ";

        if ( is_multisite() ) {
            $initial_blog = get_current_blog_id();
            $blogs = array_keys($wpdb->get_results('SELECT blog_id FROM ' . $wpdb->blogs, OBJECT_K));
            // Deleting data from each blog
            foreach ( $blogs as $blog ) {
                switch_to_blog($blog);
                $table_name = $wpdb->prefix . 'spbc_scan_results';
                // @psalm-suppress WpdbUnsafeMethodsIssue
                $exist = $wpdb->query("SHOW TABLES LIKE '" . $table_name . "';");
                if (!empty($exist)) {
                    // @psalm-suppress WpdbUnsafeMethodsIssue
                    $field_exist = $wpdb->query("SHOW COLUMNS FROM " . $table_name . " LIKE 'analysis_status';");
                    if (!empty($field_exist)) {
                        $wpdb->query(sprintf($sql, $table_name));
                    }
                }
            }
            switch_to_blog($initial_blog);
        } else {
            $table_name = $wpdb->prefix . 'spbc_scan_results';
            // @psalm-suppress WpdbUnsafeMethodsIssue
            $exist = $wpdb->query("SHOW TABLES LIKE '" . $table_name . "';");
            if (!empty($exist)) {
                // @psalm-suppress WpdbUnsafeMethodsIssue
                $field_exist = $wpdb->query("SHOW COLUMNS FROM " . $table_name . " LIKE 'analysis_status';");
                if (!empty($field_exist)) {
                    $wpdb->query(sprintf($sql, $table_name));
                }
            }
        }
    }

    public static function updateTo_2_133_1() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        if ( ! $spbc->scan_plugins_info ) {
            $spbc->scan_plugins_info = $spbc->default_scan_plugins_info;
        }
        if ( ! $spbc->scan_themes_info ) {
            $spbc->scan_themes_info = $spbc->default_scan_themes_info;
        }

        $spbc->save('scan_plugins_info');
        $spbc->save('scan_themes_info');
    }

    public static function updateTo_2_135() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        $sql_change_body_length =
            'ALTER TABLE ' . SPBC_TBL_SCAN_SIGNATURES . ' MODIFY body text NOT NULL';
        DB::getInstance()->execute($sql_change_body_length);
    }

    public static function updateTo_2_137_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $wpdb;

        DB::getInstance()->execute('DROP TABLE IF EXISTS ' . $wpdb->prefix . 'spbc_important_files');
        DB::getInstance()->execute('DROP TABLE IF EXISTS ' . $wpdb->prefix . 'spbc_important_file_snapshots');
    }

    public static function migrateDbData_2_141_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        $sql_delete_event_oversized =
            'DELETE FROM ' . SPBC_TBL_SECURITY_LOG . ' WHERE LENGTH(event)>16;';
        DB::getInstance()->execute($sql_delete_event_oversized);
    }

    public static function updateTo_2_141_0() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        $sql_change_event_length =
            'ALTER TABLE ' . SPBC_TBL_SECURITY_LOG . ' MODIFY event VARCHAR(16) NOT NULL;';
        DB::getInstance()->execute($sql_change_event_length);
    }

    public static function updateTo_2_144_1() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        $new_domains = implode(
            "\n",
            array(
                'googletagmanager.com',
                'google.com',
                'twitter.com',
                'youtube.com',
                'youtube-nocookie.com',
                'img.youtube.com',
                'dailymotion.com',
                'flikr.com',
                'facebook',
                'vimeo.com',
                'metacafe.com',
                'yahoo.com',
                'mailchimp.com',
                'vk.com',
                'widgets.wp.com'
            )
        );

        // New domain exceptions
        $spbc->settings['scanner__frontend_analysis__domains_exclusions'] = $new_domains;
        $spbc->settings['scanner__frontend_analysis__domains_exclusions_view'] = $new_domains;

        $spbc->save('settings');
    }

    public static function updateTo_2_149_1() //phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        // typo state handled
        if (isset($spbc->data['auto_update_app '])) {
            unset($spbc->data['auto_update_app ']);
        }

        // if no typo state exists - handle too
        if (isset($spbc->data['auto_update_app'])) {
            unset($spbc->data['auto_update_app']);
        }

        if (isset($spbc->data['notice_auto_update'])) {
            unset($spbc->data['notice_auto_update']);
        }

        $spbc->save('data');
    }

    /**
     * @return void
     */
    public static function updateTo_2_154_1() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        $sql_change_signatures_enum =
            'ALTER TABLE '
            . SPBC_TBL_SCAN_SIGNATURES
            . " MODIFY COLUMN `type` ENUM('FILE','CODE_PHP','CODE_HTML','CODE_JS','WAF_RULE','TRIGGER','CRON') NOT NULL";
        DB::getInstance()->execute($sql_change_signatures_enum);
    }

    /**
     * @return void
     */
    public static function updateTo_2_159_1() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        $current_state = get_option('spbc_vulnerabilities');
        if ( false !== $current_state ) {
            update_option('spbc_vulnerabilities', '', false);
            update_option('spbc_vulnerabilities', $current_state, false);
        }
    }

    /**
     * @return void
     */
    public static function updateTo_2_164_0() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $wpdb;
        $table = $wpdb->base_prefix . 'spbc_users_pass';

        $indexes = $wpdb->get_results("SHOW INDEX FROM `$table` WHERE Column_name = 'user_id'");
        $drop_sql = '';
        foreach ($indexes as $index) {
            if ($index->Key_name !== 'PRIMARY') {
                $drop_sql .= "DROP INDEX `{$index->Key_name}`,\n";
            }
        }
        if ($drop_sql) {
            $drop_sql = rtrim($drop_sql, ",\n");
            $wpdb->query("ALTER TABLE `$table` $drop_sql;");
        }
    }

    public static function updateTo_2_164_1() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $wpdb;

        // Update 2fa type
        $wpdb->query(
            $wpdb->prepare(
                "UPDATE {$wpdb->usermeta} 
             SET meta_value = %s 
             WHERE meta_key LIKE %s 
             AND meta_value LIKE %s",
                '2fa_application',
                'spbc_2fa_type',
                'google_authenticator'
            )
        );

        // Update token meta
        $wpdb->query(
            $wpdb->prepare(
                "UPDATE {$wpdb->usermeta} 
             SET meta_key = %s 
             WHERE meta_key LIKE %s",
                'spbc_2fa_app_token',
                'spbc_g2fa_token'
            )
        );
    }

    public static function updateTo_2_166_1() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        $map = [
            'scanner__dir_exclusions'      => 'scanner__path_exclusions',
            'scanner__dir_exclusions_view' => 'scanner__path_exclusions_view',
        ];

        foreach ($map as $old => $new) {
            if (!empty($spbc->settings[$old]) && empty($spbc->settings[$new])) {
                $spbc->settings[$new] = $spbc->settings[$old];
                unset($spbc->settings[$old]);
            }
        }

        $spbc->save('settings');
    }

    public static function updateTo_2_169_0() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        $old_2fa_roles = $spbc->settings['2fa_roles'];
        if ( ! $old_2fa_roles ) {
            return;
        }
        $wp_roles = new \WP_Roles();

        $new_2fa_roles = [];
        foreach ($old_2fa_roles as $role_display_name) {
            foreach ($wp_roles->roles as $role_key => $role_data) {
                if ($role_data['name'] === $role_display_name) {
                    $new_2fa_roles[] = $role_key;
                    break;
                }
            }
        }

        $spbc->settings['2fa_roles'] = $new_2fa_roles;
        $spbc->save('settings');
    }

    public static function updateTo_2_171_0() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        $rest_all = isset($spbc->settings['wp__disable_rest_api_for_non_authenticated']) && $spbc->settings['wp__disable_rest_api_for_non_authenticated'];
        $rest_users_only = isset($spbc->settings['wp__disable_rest_api_route_users']) && $spbc->settings['wp__disable_rest_api_route_users'];

        $mode = 0;

        if ($rest_all) {
            $mode = 2;
        } elseif ($rest_users_only) {
            $mode = 1;
        }

        $spbc->settings['wp__disable_rest_api'] = $mode;
        $spbc->save('settings');
    }

    public static function updateTo_2_172_0() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        if (!isset($spbc->settings['misc_disable_file_editor'])) {
            return;
        }

        if ($spbc->settings['misc_disable_file_editor'] === 0) {
            return;
        }

        // Get the config file
        $config_path = '';
        $home_option_path = '';
        $file_name = 'wp-config.php';
        if (function_exists('get_home_path')) {
            $home_option_path = get_home_path() . $file_name;
        }
        $abs_path = ABSPATH . $file_name;
        $abs_path_prepared = str_replace('\\', '/', ABSPATH) . $file_name;
        if (@file_exists($home_option_path)) {
            $config_path = $home_option_path;
        } elseif (@file_exists($abs_path)) {
            $config_path = $abs_path;
        } elseif (@file_exists($abs_path_prepared)) {
            $config_path = $abs_path_prepared;
        }
        if ($config_path === '') {
            return;
        }
        $config = file_get_contents($config_path);
        if ($config === false) {
            return;
        }

        // match the CleanTalk DISALLOW_FILE_EDIT block
        $pattern = '/\n?\/\*\s*CleanTalk\s+Security\s+Features\s*\*\/\s*\n\s*define\s*\(\s*[\'"]DISALLOW_FILE_EDIT[\'"]\s*,\s*true\s*\)\s*;\s*\n\s*\/\*\s*CleanTalk\s+Security\s+Features\s*\*\/\s*\n?/i';
        $matches_found = preg_match($pattern, $config);
        if ($matches_found) {
            preg_match($pattern, $config, $match);
        }
        $new_config = preg_replace($pattern, "\n", $config, 1);
        if ($new_config === $config) {
            return;
        } else {
            file_put_contents($config_path, $new_config);
        }

        $is_need_rollback = false;
        $is_need_rollback_admin = false;

        // check that site is not broken by get home page
        $home_url = home_url();
        $response = wp_remote_get($home_url);
        $code = wp_remote_retrieve_response_code($response);
        $body = wp_remote_retrieve_body($response);
        $pattern = '/Parse.*?error.*?wp-config\.php/i';
        $matches = preg_match($pattern, $body);
        if (($code !== 200 && $code !== 403) || is_wp_error($response) || empty($body) || $matches) {
            $is_need_rollback = true;
        }

        // check that site is not broken by get admin page
        $admin_url = admin_url();
        $response = wp_remote_get($admin_url);
        $code = wp_remote_retrieve_response_code($response);
        $body = wp_remote_retrieve_body($response);
        $matches = preg_match($pattern, $body);
        if (($code !== 200 && $code !== 403) || is_wp_error($response) || empty($body) || $matches) {
            $is_need_rollback_admin = true;
        }

        if ($is_need_rollback || $is_need_rollback_admin) {
            file_put_contents($config_path, $config);
            return;
        }

        // remove backups
        $backup_dir = defined('SPBC_PLUGIN_DIR')
            ? rtrim(SPBC_PLUGIN_DIR, '/\\') . '/cleantalk_backups'
            : rtrim(plugin_dir_path(__FILE__), '/\\') . '/cleantalk_backups';

        if (is_dir($backup_dir)) {
            $files = glob($backup_dir . '/*');
            foreach ($files as $file) {
                @unlink($file);
            }
            @rmdir($backup_dir);
        }
    }

    public static function updateTo_2_176_0() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        delete_option('spbc_rate_limit_2fa');
        delete_option('spbc_rate_limit_fswatcher');
    }

    public static function updateTo_2_178_0() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        Cron::removeTask('users_pass_check');
        $spbc->error_delete('users_pass_check', true, 'cron');
        Cron::updateTask('users_pass_check_routine', 'spbc_cron__users_pass_check_routine', 86400 * 10, time() + 1800);
    }

    /**
     * @return void
     */
    public static function updateTo_2_181() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
    {
        global $spbc;

        try {
            VulnerabilityAlarm::updateWPModulesVulnerabilities();
        } catch (\Exception $_e) {
            VulnerabilityAlarm::dropWPModulesVulnerabilities();
        }

        $spbc->data['spbc_security_check_vulnerabilities_last_call'] = time();
        $spbc->save('data');
    }
}
