<?php
/**
 * MainWP Time Capsule
 *
 * MainWP Time Capsule Extension handler.
 * Extension URL: https://mainwp.com/extension/time-capsule/
 *
 * @package MainWP\Child
 *
 * Credits
 *
 * Plugin-Name: WP Time Capsule
 * Plugin-URI: https://wptimecapsule.com
 * Author: Revmakx
 * Author URI: http://www.revmakx.com
 * Licence: GPLv2 or later
 */

namespace MainWP\Child;

// phpcs:disable PSR1.Classes.ClassDeclaration, WordPress.WP.AlternativeFunctions, Generic.Metrics.CyclomaticComplexity -- required to achieve desired results, pull request solutions appreciated.

/**
 * Class MainWP_Child_Timecapsule
 *
 * MainWP Time Capsule Extension handler.
 */
class MainWP_Child_Timecapsule { //phpcs:ignore -- NOSONAR - multi methods.

    /**
     * Public static variable to hold the single instance of the class.
     *
     * @var mixed Default null
     */
    public static $instance = null;

    /**
     * Public variable to hold the infomration if the WP Time Capsule plugin is installed on the child site.
     *
     * @var bool If WP Time Capsule intalled, return true, if not, return false.
     */
    public $is_plugin_installed = false;

    /**
     * Create a public static instance.
     *
     * @return mixed Class instance.
     */
    public static function instance() {
        if ( null === static::$instance ) {
            static::$instance = new self();
        }
        return static::$instance;
    }

    /**
     * MainWP_Child_Timecapsule constructor.
     *
     * Run any time the class is called.
     *
     * @uses is_plugin_active() Determines whether a plugin is active.
     * @see https://developer.wordpress.org/reference/functions/is_plugin_active/
     */
    public function __construct() {
        require_once ABSPATH . 'wp-admin/includes/plugin.php'; // NOSONAR - WP compatible.
        if ( is_plugin_active( 'wp-time-capsule/wp-time-capsule.php' ) && defined( 'WPTC_CLASSES_DIR' ) ) {
            $this->is_plugin_installed = true;
        }

        if ( ! $this->is_plugin_installed ) {
            return;
        }

        add_filter( 'mainwp_site_sync_others_data', array( $this, 'sync_others_data' ), 10, 2 );
    }

    /**
     * Initiate action hooks.
     *
     * @uses get_option() Retrieves an option value based on an option name.
     * @see https://developer.wordpress.org/reference/functions/get_option/
     *
     * @return void
     */
    public function init() {
        if ( ! $this->is_plugin_installed ) {
            return;
        }

        if ( get_option( 'mainwp_time_capsule_ext_enabled' ) !== 'Y' ) {
            return;
        }

        add_action( 'mainwp_child_site_stats', array( $this, 'do_site_stats' ) );

        if ( get_option( 'mainwp_time_capsule_hide_plugin' ) === 'hide' ) {
            add_filter( 'all_plugins', array( $this, 'all_plugins' ) );
            add_action( 'admin_menu', array( $this, 'remove_menu' ) );
            add_filter( 'site_transient_update_plugins', array( &$this, 'remove_update_nag' ) );
            add_filter( 'mainwp_child_hide_update_notice', array( &$this, 'hide_update_notice' ) );
        }
    }

    /**
     * Fire off certain WP Time Capsule plugin actions.
     *
     * @return void
     *
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::set_showhide()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::get_root_files()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::get_tables()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::exclude_file_list()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::exclude_table_list()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::include_table_list()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::include_table_structure_only()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::include_file_list()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::get_files_by_key()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::process_wptc_login()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::get_installed_plugins()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::get_installed_themes()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::is_staging_need_request()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::get_staging_details_wptc()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::start_fresh_staging_wptc()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::get_staging_url_wptc()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::stop_staging_wptc()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::continue_staging_wptc()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::delete_staging_wptc()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::copy_staging_wptc()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::get_staging_current_status_key()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::wptc_sync_purchase()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::init_restore()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::save_settings_wptc()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::analyze_inc_exc()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::get_enabled_plugins()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::get_enabled_themes()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::get_system_info()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::update_vulns_settings()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::start_fresh_backup_tc_callback_wptc()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::save_manual_backup_name_wptc()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::progress_wptc()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::stop_fresh_backup_tc_callback_wptc()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::wptc_cron_status()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::get_this_backups_html()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::start_restore_tc_callback_wptc()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::get_sibling_files_callback_wptc()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::get_logs_rows()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::clear_wptc_logs()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::send_issue_report()
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::lazy_load_activity_log_wptc()
     * @uses \MainWP\Child\MainWP_Helper::write() Write response data to be sent to the MainWP Dashboard.
     */
    public function action() { // phpcs:ignore -- NOSONAR - Current complexity is the only way to achieve desired results, pull request solutions appreciated.
        if ( ! $this->is_plugin_installed ) {
            MainWP_Helper::write( array( 'error' => 'Please install WP Time Capsule plugin on child website' ) );
        }

        try {
            $this->require_files();
        } catch ( MainWP_Exception $e ) {
            $error = $e->getMessage();
            MainWP_Helper::write( array( 'error' => $error ) );
        }

        // to fix.
        if ( isset( $_POST['mwp_action'] ) && ! defined( 'WP_ADMIN' ) ) { // phpcs:ignore WordPress.Security.NonceVerification
            define( 'WP_ADMIN', true );
        }

        if ( function_exists( '\wptc_load_files' ) ) {
            \wptc_load_files();
        }
        $information = array();

        $options_helper    = new \Wptc_Options_Helper();
        $options           = \WPTC_Factory::get( 'config' );
        $is_user_logged_in = $options->get_option( 'is_user_logged_in' );
        $privileges_wptc   = $options_helper->get_unserialized_privileges();

        $mwp_action = MainWP_System::instance()->validate_params( 'mwp_action' );
        if ( ! empty( $mwp_action ) ) {
            if ( ( 'save_settings' === $mwp_action || 'get_staging_details_wptc' === $mwp_action || 'progress_wptc' === $mwp_action ) && ( ! $is_user_logged_in || ! $privileges_wptc ) ) {
                MainWP_Helper::write( array( 'error' => 'You are not login to your WP Time Capsule account.' ) );
            }
            switch ( $mwp_action ) { // NOSONAR - multi case.
                case 'set_showhide':
                    $information = $this->set_showhide();
                    break;
                case 'get_root_files':
                    $this->get_root_files();
                    break;
                case 'get_tables':
                    $this->get_tables();
                    break;
                case 'exclude_file_list':
                    $this->exclude_file_list();
                    break;
                case 'exclude_table_list':
                    $this->exclude_table_list();
                    break;
                case 'include_table_list':
                    $this->include_table_list();
                    break;
                case 'include_table_structure_only':
                    $this->include_table_structure_only();
                    break;
                case 'include_file_list':
                    $this->include_file_list();
                    break;
                case 'get_files_by_key':
                    $this->get_files_by_key();
                    break;
                case 'wptc_login':
                    $information = $this->process_wptc_login();
                    break;
                case 'get_installed_plugins':
                    $information = $this->get_installed_plugins();
                    break;
                case 'get_installed_themes':
                    $information = $this->get_installed_themes();
                    break;
                case 'is_staging_need_request':
                    $this->is_staging_need_request();
                    break;
                case 'get_staging_details_wptc':
                    $this->get_staging_details_wptc();
                    break;
                case 'start_fresh_staging_wptc':
                    $this->start_fresh_staging_wptc();
                    break;
                case 'get_staging_url_wptc':
                    $this->get_staging_url_wptc();
                    break;
                case 'stop_staging_wptc':
                    $this->stop_staging_wptc();
                    break;
                case 'continue_staging_wptc':
                    $this->continue_staging_wptc();
                    break;
                case 'delete_staging_wptc':
                    $this->delete_staging_wptc();
                    break;
                case 'copy_staging_wptc':
                    $this->copy_staging_wptc();
                    break;
                case 'get_staging_current_status_key':
                    $this->get_staging_current_status_key();
                    break;
                case 'wptc_sync_purchase':
                    $this->wptc_sync_purchase();
                    break;
                case 'init_restore':
                    $this->init_restore();
                    break;
                case 'save_settings':
                    $information = $this->save_settings_wptc();
                    break;
                case 'analyze_inc_exc':
                    $this->analyze_inc_exc();
                    break;
                case 'get_enabled_plugins':
                    $information = $this->get_enabled_plugins();
                    break;
                case 'get_enabled_themes':
                    $information = $this->get_enabled_themes();
                    break;
                case 'get_system_info':
                    $information = $this->get_system_info();
                    break;
                case 'update_vulns_settings':
                    $information = $this->update_vulns_settings();
                    break;
                case 'start_fresh_backup':
                    $information = $this->start_fresh_backup_tc_callback_wptc();
                    break;
                case 'save_manual_backup_name':
                    $this->save_manual_backup_name_wptc();
                    break;
                case 'progress_wptc':
                    $information = $this->progress_wptc();
                    break;
                case 'stop_fresh_backup':
                    $information = $this->stop_fresh_backup_tc_callback_wptc();
                    break;
                case 'wptc_cron_status':
                    $information = $this->wptc_cron_status();
                    break;
                case 'get_this_backups_html':
                    $information = $this->get_this_backups_html();
                    break;
                case 'start_restore_tc_wptc':
                    $this->start_restore_tc_callback_wptc();
                    break;
                case 'get_sibling_files':
                    $this->get_sibling_files_callback_wptc();
                    break;
                case 'get_logs_rows':
                    $information = $this->get_logs_rows();
                    break;
                case 'clear_logs':
                    $information = $this->clear_wptc_logs();
                    break;
                case 'send_issue_report':
                    $this->send_issue_report();
                    break;
                case 'lazy_load_activity_log':
                    $information = $this->lazy_load_activity_log_wptc();
                    break;
                default:
                    break;
            }
        }
        MainWP_Helper::write( $information );
    }

    /**
     * Check if required files exist.
     *
     * @uses \MainWP\Child\MainWP_Helper::check_files_exists() Check if requested files exist.
     */
    public function require_files() {

        // to fix for some case.
        if ( function_exists( '\wptc_load_files' ) ) {
            if ( ! defined( 'WP_ADMIN' ) ) {
                define( 'WP_ADMIN', true );
            }
            \wptc_load_files();
        }

        if ( ! class_exists( '\WPTC_Base_Factory' ) && defined( 'WPTC_PLUGIN_DIR' ) && MainWP_Helper::check_files_exists( WPTC_PLUGIN_DIR . 'Base/Factory.php' ) ) {
            include_once WPTC_PLUGIN_DIR . 'Base/Factory.php'; // NOSONAR -- WP compatible.
        }
        if ( ! class_exists( '\Wptc_Options_Helper' ) && defined( 'WPTC_PLUGIN_DIR' ) && MainWP_Helper::check_files_exists( WPTC_PLUGIN_DIR . 'Views/wptc-options-helper.php' ) ) {
            include_once WPTC_PLUGIN_DIR . 'Views/wptc-options-helper.php'; // NOSONAR -- WP compatible.
        }
    }

    /**
     * Hide or unhide the WP Time Capsule plugin.
     *
     * @return array Action result.
     *
     * @uses \MainWP\Child\MainWP_Helper::update_option() Update database option by option name.
     *
     * @used-by \MainWP\Child\MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     */
    public function set_showhide() {
        $hide = MainWP_System::instance()->validate_params( 'showhide' );
        MainWP_Helper::update_option( 'mainwp_time_capsule_hide_plugin', $hide, 'yes' );
        $information['result'] = 'SUCCESS';
        return $information;
    }

    /**
     * Sync the WP Time Capsule plugin settings.
     *
     * @param array $information Array containing the sync information.
     * @param array $data        Array containing the WP Time Capsule plugin data to be synced.
     *
     * @return array $information Array containing the sync information.
     *
     * @uses \MainWP\Child\MainWP_Child_Timecapsule::get_sync_data() Get synced WP Time Capsule data.
     * @uses \MainWP\Child\MainWP_Helper::update_option() Update database option by option name.
     * @uses get_option() Retrieves an option value based on an option name.
     * @see https://developer.wordpress.org/reference/functions/get_option/
     */
    public function sync_others_data( $information, $data = array() ) {
        if ( isset( $data['syncWPTimeCapsule'] ) && $data['syncWPTimeCapsule'] ) {
            $information['syncWPTimeCapsule'] = $this->get_sync_data();
            if ( get_option( 'mainwp_time_capsule_ext_enabled' ) !== 'Y' ) {
                MainWP_Helper::update_option( 'mainwp_time_capsule_ext_enabled', 'Y', 'yes' );
            }
        }
        return $information;
    }

    /**
     * Get synced WP Time Capsule data.
     *
     * @return array|bool Return an array containing the synced data, or false on failure.
     *
     * @uses \MainWP\Child\MainWP_Helper::instance()->check_classes_exists() Check if requested class exists.
     * @uses \MainWP\Child\MainWP_Helper::instance()->check_methods() Check if requested method exists.
     *
     * @used-by MainWP_Child_Timecapsule::sync_others_data() Sync the WP Time Capsule plugin settings.
     */
    public function get_sync_data() {
        try {
            $this->require_files();
            MainWP_Helper::instance()->check_classes_exists( array( '\Wptc_Options_Helper', '\WPTC_Base_Factory', '\WPTC_Factory' ) );

            $config = \WPTC_Factory::get( 'config' );
            MainWP_Helper::instance()->check_methods( $config, 'get_option' );

            $main_account_email_var = $config->get_option( 'main_account_email' );
            $last_backup_time       = $config->get_option( 'last_backup_time' );
            $wptc_settings          = \WPTC_Base_Factory::get( 'Wptc_Settings' );

            $options_helper = new \Wptc_Options_Helper();

            MainWP_Helper::instance()->check_methods( $options_helper, array( 'get_plan_interval_from_subs_info', 'get_is_user_logged_in' ) );
            MainWP_Helper::instance()->check_methods( $wptc_settings, array( 'get_connected_cloud_info' ) );

            $all_backups   = $this->get_backups();
            $backups_count = 0;
            if ( is_array( $all_backups ) ) {
                $formatted_backups = array();
                foreach ( $all_backups as $value ) {
                    $value_array                                     = (array) $value;
                    $formatted_backups[ $value_array['backupID'] ][] = $value_array;
                }
                $backups_count = count( $formatted_backups );
            }

            return array(
                'main_account_email' => $main_account_email_var,
                'signed_in_repos'    => $wptc_settings->get_connected_cloud_info(),
                'plan_name'          => $options_helper->get_plan_interval_from_subs_info(),
                'plan_interval'      => $options_helper->get_plan_interval_from_subs_info(),
                'lastbackup_time'    => ! empty( $last_backup_time ) ? $last_backup_time : 0,
                'is_user_logged_in'  => $options_helper->get_is_user_logged_in(),
                'backups_count'      => $backups_count,
            );
        } catch ( MainWP_Exception $e ) {
            // do not exit here!
        }
        return false;
    }

    /**
     * Get WP Time Capsule backups.
     *
     * @param string $last_time Last completed backup timestamp.
     *
     * @uses wpdb::get_results() Retrieve an entire SQL result set from the database (i.e., many rows).
     * @see https://developer.wordpress.org/reference/classes/wpdb/get_results/
     *
     * @uses wpdb::prepare() Prepares a SQL query for safe execution. Uses sprintf()-like syntax.
     * @see https://developer.wordpress.org/reference/classes/wpdb/prepare/
     *
     * @return array Returns array of all completed backups.
     */
    protected function get_backups( $last_time = false ) {
        if ( empty( $last_time ) ) {
            $last_time = strtotime( date( 'Y-m-d', strtotime( date( 'Y-m-01' ) ) ) ); // phpcs:ignore --  required to achieve desired results, pull request solutions appreciated.
        }

        /**
         * Object, providing access to the WordPress database.
         *
         * @global $wpdb WordPress Database instance.
         */
        global $wpdb;

        // Direct query for dynamic backup data; caching would return stale backup progress.
        return $wpdb->get_results( //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $wpdb->prepare(
                "SELECT backupID
                FROM {$wpdb->base_prefix}wptc_processed_files
                WHERE backupID > %s ",
                $last_time
            )
        );
    }

    /**
     * Get the WP Time Capsule tables.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     */
    public function get_tables() {
         // phpcs:disable WordPress.Security.NonceVerification
        $category = isset( $_POST['category'] ) ? wp_unslash( $_POST['category'] ) : ''; //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
         // phpcs:enable WordPress.Security.NonceVerification
        $exclude_class_obj = new \Wptc_ExcludeOption( $category );
        $exclude_class_obj->get_tables();
        die();
    }

    /**
     * Exlude files from the backup process.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     */
    public function exclude_file_list() {
        // phpcs:disable WordPress.Security.NonceVerification
        if ( ! isset( $_POST['data'] ) ) {
            wptc_die_with_json_encode( array( 'status' => 'no data found' ) );
        }
        $category          = isset( $_POST['category'] ) ? wp_unslash( $_POST['category'] ) : ''; //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        $exclude_class_obj = new \Wptc_ExcludeOption( $category );
        $data              = isset( $_POST['data'] ) ? wp_unslash( $_POST['data'] ) : ''; //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        // phpcs:enable WordPress.Security.NonceVerification
        $exclude_class_obj->exclude_file_list( $data );
        die();
    }

    /**
     * Get backup process progress.
     *
     * @uses spawn_cron() Sends a request to run cron through HTTP request that doesn’t halt page loading.
     * @see https://developer.wordpress.org/reference/functions/spawn_cron/
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     *
     * @return array Action result.
     */
    public function progress_wptc() {

        $config = \WPTC_Factory::get( 'config' );

        /**
         * Object, providing access to the WordPress database.
         *
         * @global $wpdb WordPress Database instance.
         */
        global $wpdb;

        if ( ! $config->get_option( 'in_progress' ) ) {
            spawn_cron();
        }

        $processed_files = \WPTC_Factory::get( 'processed-files' );

        $return_array                                  = array();
        $return_array['stored_backups']                = $processed_files->get_stored_backups();
        $return_array['backup_progress']               = array();
        $return_array['starting_first_backup']         = $config->get_option( 'starting_first_backup' );
        $return_array['meta_data_backup_process']      = $config->get_option( 'meta_data_backup_process' );
        $return_array['backup_before_update_progress'] = $config->get_option( 'backup_before_update_progress' );
        $return_array['is_staging_running']            = apply_filters( 'is_any_staging_process_going_on', '' );
        $cron_status                                   = $config->get_option( 'wptc_own_cron_status' );

        if ( ! empty( $cron_status ) ) {
            $return_array['wptc_own_cron_status']          = unserialize( $cron_status ); // phpcs:ignore -- safe internal value, third party.
            $return_array['wptc_own_cron_status_notified'] = (int) $config->get_option( 'wptc_own_cron_status_notified' );
        }

        $start_backups_failed_server = $config->get_option( 'start_backups_failed_server' );
        if ( ! empty( $start_backups_failed_server ) ) {
            $return_array['start_backups_failed_server'] = unserialize( $start_backups_failed_server ); // phpcs:ignore -- safe internal value, third party.
            $config->set_option( 'start_backups_failed_server', false );
        }

        $processed_files->get_current_backup_progress( $return_array );

        $return_array['user_came_from_existing_ver'] = (int) $config->get_option( 'user_came_from_existing_ver' );
        $return_array['show_user_php_error']         = $config->get_option( 'show_user_php_error' );
        $return_array['bbu_setting_status']          = apply_filters( 'get_backup_before_update_setting_wptc', '' );
        $return_array['bbu_note_view']               = apply_filters( 'get_bbu_note_view', '' );
        $return_array['staging_status']              = apply_filters( 'staging_status_wptc', '' );

        $processed_files  = \WPTC_Factory::get( 'processed-files' );
        $last_backup_time = $config->get_option( 'last_backup_time' );

        if ( ! empty( $last_backup_time ) ) {
            $user_time = $config->cnvt_UTC_to_usrTime( $last_backup_time );
            $processed_files->modify_schedule_backup_time( $user_time );
            $formatted_date                   = date( 'M d @ g:i a', $user_time ); // phpcs:ignore -- required to achieve desired results, pull request solutions appreciated.
            $return_array['last_backup_time'] = $formatted_date;
        } else {
            $return_array['last_backup_time'] = 'No Backup Taken';
        }

        return array( 'result' => $return_array );
    }

    /**
     * Get the WP Cron status.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     *
     * @return array Action result.
     */
    public function wptc_cron_status() {
        $config = \WPTC_Factory::get( 'config' );
        wptc_own_cron_status();
        $status      = array();
        $cron_status = $config->get_option( 'wptc_own_cron_status' );
        if ( ! empty( $cron_status ) ) {
            $cron_status = unserialize( $cron_status ); // phpcs:ignore -- safe internal value, third party.

            if ( 'success' === $cron_status['status'] ) {
                $status['status'] = 'success';
            } else {
                $status['status']      = 'failed';
                $status['status_code'] = $cron_status['statusCode'];
                $status['err_msg']     = $cron_status['body'];
                $status['cron_url']    = $cron_status['cron_url'];
                $status['ips']         = $cron_status['ips'];
            }
            return array( 'result' => $status );
        }
        return false;
    }

    /**
     * Get the backups HTML markup.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     *
     * @return array Action result.
     */
    public function get_this_backups_html() {
        // phpcs:disable WordPress.Security.NonceVerification
        $this_backup_ids    = isset( $_POST['this_backup_ids'] ) ? wp_unslash( $_POST['this_backup_ids'] ) : ''; //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        $specific_dir       = isset( $_POST['specific_dir'] ) ? wp_unslash( $_POST['specific_dir'] ) : ''; //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        $type               = isset( $_POST['type'] ) ? sanitize_text_field( wp_unslash( $_POST['type'] ) ) : '';
        $treeRecursiveCount = isset( $_POST['treeRecursiveCount'] ) ? sanitize_text_field( wp_unslash( $_POST['treeRecursiveCount'] ) ) : '';
        $processed_files    = \WPTC_Factory::get( 'processed-files' );
        // phpcs:enable WordPress.Security.NonceVerification
        $result = $processed_files->get_this_backups_html( $this_backup_ids, $specific_dir, $type, $treeRecursiveCount );
        return array( 'result' => $result );
    }

    /**
     * Start the restore process.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     */
    public function start_restore_tc_callback_wptc() {

        if ( apply_filters( 'is_restore_to_staging_wptc', '' ) ) {
            $request = apply_filters( 'get_restore_to_staging_request_wptc', '' );
        } else {
            // phpcs:disable WordPress.Security.NonceVerification
            $request = isset( $_POST['data'] ) ? wp_unslash( $_POST['data'] ) : ''; //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
            // phpcs:enable WordPress.Security.NonceVerification
        }

        include_once WPTC_CLASSES_DIR . 'class-prepare-restore-bridge.php'; // NOSONAR -- WP compatible.

        new \WPTC_Prepare_Restore_Bridge( $request ); // NOSONAR - 3rd compatible.
    }

    /**
     * Get sibling files.
     *
     * @uses wp_normalize_path() Normalize a filesystem path.
     * @see https://developer.wordpress.org/reference/functions/wp_normalize_path/
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     */
    public function get_sibling_files_callback_wptc() {
        // phpcs:disable WordPress.Security.NonceVerification
        // note that we are getting the ajax function data via $_POST.
        $file_name = isset( $_POST['data']['file_name'] ) ? sanitize_text_field( wp_unslash( $_POST['data']['file_name'] ) ) : '';
        if ( ! empty( $file_name ) ) {
            $file_name = wp_normalize_path( $file_name );
        }
        $backup_id       = isset( $_POST['data']['backup_id'] ) ? sanitize_text_field( wp_unslash( $_POST['data']['backup_id'] ) ) : '';
        $recursive_count = isset( $_POST['data']['recursive_count'] ) ? sanitize_text_field( wp_unslash( $_POST['data']['recursive_count'] ) ) : '';
        // phpcs:enable WordPress.Security.NonceVerification
        $processed_files = \WPTC_Factory::get( 'processed-files' );
        echo $processed_files->get_this_backups_html( $backup_id, $file_name, 'sibling', (int) $recursive_count ); // phpcs:ignore WordPress.Security.EscapeOutput
        die();
    }

    /**
     * Send issue report.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     */
    public function send_issue_report() {
        \WPTC_Base_Factory::get( 'Wptc_App_Functions' )->send_report();
        die();
    }

    /**
     * Get logs rows.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     *
     * @return array Action result.
     */
    public function get_logs_rows() {
        $result                 = $this->prepare_items();
        $result['display_rows'] = base64_encode( wp_json_encode( $this->get_display_rows( $result['items'] ) ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode required for the backwards compatibility.
        return $result;
    }

    /**
     * Prepare items for logs.
     *
     * @used-by MainWP_Child_Timecapsule::get_logs_rows() Get logs rows.
     *
     * @return array Action result.
     *
     * @uses \MainWP\Child\MainWP_Child_DB::real_escape_string()
     */
    public function prepare_items() { //phpcs:ignore -- NOSONAR - complex.

        /**
         * Object, providing access to the WordPress database.
         *
         * @global $wpdb WordPress Database instance.
         */
        global $wpdb;
        // phpcs:disable WordPress.Security.NonceVerification
        if ( isset( $_POST['type'] ) ) {
            $type = ! empty( $_POST['type'] ) ? sanitize_text_field( wp_unslash( $_POST['type'] ) ) : '';
            switch ( $type ) {
                case 'backups':
                    $query = 'SELECT * FROM ' . $wpdb->base_prefix . "wptc_activity_log WHERE type LIKE '%backup%' AND show_user = 1 GROUP BY action_id";
                    break;
                case 'restores':
                    $query = 'SELECT * FROM ' . $wpdb->base_prefix . "wptc_activity_log WHERE type LIKE 'restore%' GROUP BY action_id";
                    break;
                case 'staging':
                    $query = 'SELECT * FROM ' . $wpdb->base_prefix . "wptc_activity_log WHERE type LIKE 'staging%' GROUP BY action_id";
                    break;
                case 'backup_and_update':
                    $query = 'SELECT * FROM ' . $wpdb->base_prefix . "wptc_activity_log WHERE type LIKE 'backup_and_update%' GROUP BY action_id";
                    break;
                case 'auto_update':
                    $query = 'SELECT * FROM ' . $wpdb->base_prefix . "wptc_activity_log WHERE type LIKE 'auto_update%' GROUP BY action_id";
                    break;
                case 'others':
                    $query = 'SELECT * FROM ' . $wpdb->base_prefix . "wptc_activity_log WHERE type NOT LIKE 'restore%' AND type NOT LIKE 'backup%' AND show_user = 1";
                    break;
                default:
                    $query = 'SELECT * FROM ' . $wpdb->base_prefix . 'wptc_activity_log GROUP BY action_id UNION SELECT * FROM ' . $wpdb->base_prefix . "wptc_activity_log WHERE action_id='' AND show_user = 1";
                    break;
            }
        } else {
            $query = 'SELECT * FROM ' . $wpdb->base_prefix . 'wptc_activity_log WHERE show_user = 1   GROUP BY action_id ';
        }

        $orderby = ! empty( $_POST['orderby'] ) ? sanitize_sql_orderby( wp_unslash( $_POST['orderby'] ) ) : 'id';
        $order   = ! empty( $_POST['order'] ) ? sanitize_sql_orderby( wp_unslash( $_POST['order'] ) ) : 'DESC';
        if ( ! empty( $orderby ) & ! empty( $order ) ) {
            $query .= ' ORDER BY ' . $orderby . ' ' . $order;
        }

        $totalitems = $wpdb->query( $query ); // phpcs:ignore -- safe query.
        $perpage    = 20;
        $paged      = ! empty( $_POST['paged'] ) ? intval( $_POST['paged'] ) : '';
        if ( empty( $paged ) || ! is_numeric( $paged ) || $paged <= 0 ) {
            $paged = 1;
        }
        if ( ! empty( $paged ) && ! empty( $perpage ) ) {
            $offset = ( $paged - 1 ) * $perpage;
            $query .= ' LIMIT ' . (int) $offset . ',' . (int) $perpage;
        }
        // phpcs:enable WordPress.Security.NonceVerification

        return array(
            'items'      => $wpdb->get_results( $query ), // phpcs:ignore -- safe query required to achieve desired results, pull request solutions appreciated.
            'totalitems' => $totalitems,
            'perpage'    => $perpage,
        );
    }

    /**
     * Lazy load activity log.
     *
     * @uses MainWP_Child_Timecapsule::get_activity_log() Get the WP Time Capsule activity log.
     *
     * @uses wpdb::get_results() Retrieve an entire SQL result set from the database (i.e., many rows).
     * @see https://developer.wordpress.org/reference/classes/wpdb/get_results/
     *
     * @uses wpdb::prepare() Prepares a SQL query for safe execution. Uses sprintf()-like syntax.
     * @see https://developer.wordpress.org/reference/classes/wpdb/prepare/
     *
     * @return array Action result.
     */
    public function lazy_load_activity_log_wptc() {
        // phpcs:disable WordPress.Security.NonceVerification
        if ( ! isset( $_POST['data'] ) ) {
            return false;
        }

        $data = isset( $_POST['data'] ) ? wp_unslash( $_POST['data'] ) : array(); //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized

        if ( ! isset( $data['action_id'] ) || ! isset( $data['limit'] ) ) {
            return false;
        }
        // phpcs:enable WordPress.Security.NonceVerification

        /**
         * Object, providing access to the WordPress database.
         *
         * @global $wpdb WordPress Database instance.
         */
        global $wpdb;

        $action_id     = $data['action_id'];
        $from_limit    = $data['limit'];
        $detailed      = '';
        $load_more     = false;
        $current_limit = \WPTC_Factory::get( 'config' )->get_option( 'activity_log_lazy_load_limit' );
        $to_limit      = $from_limit + $current_limit;

        // Direct query for transient activity log data with dynamic pagination; caching not appropriate.
        $sub_records = $wpdb->get_results( $wpdb->prepare( 'SELECT * FROM ' . $wpdb->base_prefix . 'wptc_activity_log WHERE action_id = %s AND show_user = 1 ORDER BY id DESC LIMIT %d, %d', $action_id, $from_limit, $current_limit ) ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching

        $row_count = count( $sub_records );

        if ( $row_count === (int) $current_limit ) {
            $load_more = true;
        }

        $detailed = $this->get_activity_log( $sub_records );

        if ( isset( $load_more ) && $load_more ) {
            $detailed .= '<tr><td></td><td><a style="cursor:pointer; position:relative" class="wptc_activity_log_load_more" action_id="' . esc_attr( $action_id ) . '" limit="' . esc_attr( $to_limit ) . '">Load more</a></td><td></td></tr>';
        }

        return array( 'result' => $detailed );
    }

    /**
     * Display the log rows.
     *
     * @param array $records An array of log records.
     *
     * @used-by MainWP_Child_Timecapsule::get_logs_rows() Get logs rows.
     *
     * @return string Log rows.
     */
    public function get_display_rows( $records ) { //phpcs:ignore -- NOSONAR - complex.

        /**
         * Object, providing access to the WordPress database.
         *
         * @global $wpdb WordPress Database instance.
         */
        global $wpdb;

        // Get the records registered in the prepare_items method.
        if ( ! is_array( $records ) ) {
            return '';
        }

        $limit = \WPTC_Factory::get( 'config' )->get_option( 'activity_log_lazy_load_limit' );
        // Get the columns registered in the get_columns and get_sortable_columns methods.
        if ( count( $records ) > 0 ) {

            foreach ( $records as $key => $rec ) {
                $html = '';

                $more_logs = false;
                $load_more = false;
                if ( ! empty( $rec->action_id ) ) {
                    // Direct query for real-time activity logs; caching would prevent display of current backup progress.
                    $sub_records = $wpdb->get_results( $wpdb->prepare( 'SELECT * FROM ' . $wpdb->base_prefix . 'wptc_activity_log WHERE action_id= %s AND show_user = 1 ORDER BY id DESC LIMIT 0, %d', $rec->action_id, $limit ) ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
                    $row_count   = count( $sub_records );
                    if ( $row_count === (int) $limit ) {
                        $load_more = true;
                    }

                    if ( $row_count > 0 ) {
                        $more_logs = true;
                        $detailed  = '<table>';
                        $detailed .= $this->get_activity_log( $sub_records );
                        if ( isset( $load_more ) && $load_more ) {
                            $detailed .= '<tr><td></td><td><a style="cursor:pointer; position:relative" class="mainwp_wptc_activity_log_load_more" action_id="' . $rec->action_id . '" limit="' . $limit . '">Load more</a></td><td></td></tr>';
                        }
                        $detailed .= '</table>';

                    }
                }
                $html     .= '<tr class="act-tr">';
                $Ldata     = unserialize( $rec->log_data ); // phpcs:ignore -- safe internal value, third party.
                $user_time = \WPTC_Factory::get( 'config' )->cnvt_UTC_to_usrTime( $Ldata['log_time'] );
                \WPTC_Factory::get( 'processed-files' )->modify_schedule_backup_time( $user_time );
                $user_tz_now = date( 'M d, Y @ g:i:s a', $user_time ); // phpcs:ignore -- required to achieve desired results, pull request solutions appreciated.
                $msg         = '';
                if ( false !== strpos( $rec->type, 'backup' ) ) {
                    // Backup process.
                    $msg = 'Backup Process';
                } elseif ( false !== strpos( $rec->type, 'restore' ) ) {
                    // Restore Process.
                    $msg = 'Restore Process';
                } elseif ( false !== strpos( $rec->type, 'staging' ) ) {
                    // Restore Process.
                    $msg = 'Staging Process';
                } else {
                    if ( $row_count < 2 ) {
                        $more_logs = false;
                    }
                    $msg = $Ldata['msg'];
                }
                $html .= '<td class="wptc-act-td">' . $user_tz_now . '</td><td class="wptc-act-td">' . $msg;
                if ( $more_logs ) {
                    $html .= "&nbsp&nbsp&nbsp&nbsp<a class='wptc-show-more' action_id='" . round( $rec->action_id ) . "'>View details</a></td>";
                } else {
                    $html .= '</td>';
                }
                $html .= '<td class="wptc-act-td"><a class="report_issue_wptc" id="' . $rec->id . '" href="#">Send report to plugin developer</a></td>';
                if ( $more_logs ) {

                    $html .= "</tr><tr id='" . round( $rec->action_id ) . "' class='wptc-more-logs'><td colspan=3>" . $detailed . '</td>';
                } else {
                    $html .= '</td>';
                }

                $html .= '</tr>';

                $display_rows[ $key ] = $html;
            }
        }
        return $display_rows;
    }

    /**
     * Get the WP Time Capsule activity log.
     *
     * @param array $sub_records Activity log sub-records.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     *
     * @return string Activity log HTML.
     */
    public function get_activity_log( $sub_records ) {
        if ( count( $sub_records ) < 1 ) {
            return false;
        }
        $detailed = '';
        $timezone = \WPTC_Factory::get( 'config' )->get_option( 'wptc_timezone' );
        foreach ( $sub_records as $srec ) {
            $Moredata = unserialize( $srec->log_data ); // phpcs:ignore -- safe internal value, third party.
            $user_tmz = new \DateTime( '@' . $Moredata['log_time'], new \DateTimeZone( date_default_timezone_get() ) );
            $user_tmz->setTimeZone( new \DateTimeZone( $timezone ) );
            $user_tmz_now = $user_tmz->format( 'M d @ g:i:s a' );
            $detailed    .= '<tr><td>' . $user_tmz_now . '</td><td>' . $Moredata['msg'] . '</td><td></td></tr>';
        }
        return $detailed;
    }

    /**
     * Clear the WP Time Capsule logs.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     *
     * @return array Action result.
     */
    public function clear_wptc_logs() {

        /**
         * Object, providing access to the WordPress database.
         *
         * @global $wpdb WordPress Database instance.
         */
        global $wpdb;

        if ( $wpdb->query( 'TRUNCATE TABLE `' . $wpdb->base_prefix . 'wptc_activity_log`' ) ) {
            $result = 'yes';
        } else {
            $result = 'no';
        }
        return array( 'result' => $result );
    }

    /**
     * Stop the WP Time Capsule backup process.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     *
     * @return array Action result.
     */
    public function stop_fresh_backup_tc_callback_wptc() {
        $deactivated_plugin = null;
        $backup             = new \WPTC_BackupController();
        $backup->stop( $deactivated_plugin );
        return array( 'result' => 'ok' );
    }

    /**
     * Get the site root files.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     */
    public function get_root_files() {
        // phpcs:disable WordPress.Security.NonceVerification
        $category = isset( $_POST['category'] ) ? wp_unslash( $_POST['category'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        // phpcs:enable WordPress.Security.NonceVerification
        $exclude_class_obj = new \Wptc_ExcludeOption( $category );
        $exclude_class_obj->get_root_files();
        die();
    }

    /**
     * Exclude database tables.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     */
    public function exclude_table_list() {
        // phpcs:disable WordPress.Security.NonceVerification
        if ( ! isset( $_POST['data'] ) ) {
            wptc_die_with_json_encode( array( 'status' => 'no data found' ) );
        }
        $category          = isset( $_POST['data']['category'] ) ? wp_unslash( $_POST['data']['category'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        $exclude_class_obj = new \Wptc_ExcludeOption( $category );
        $data              = isset( $_POST['data'] ) ? wp_unslash( $_POST['data'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        $exclude_class_obj->exclude_table_list( $data );
        // phpcs:enable WordPress.Security.NonceVerification
        die();
    }

    /**
     * Add support for the reporting system.
     *
     * @uses has_action() Check if any action has been registered for a hook.
     * @see https://developer.wordpress.org/reference/functions/has_action/
     *
     * @uses MainWP_Child_Timecapsule::do_reports_log() Add WP Time Capsule data to the reports database table.
     */
    public function do_site_stats() {
        if ( has_action( 'mainwp_child_reports_log' ) ) {
            do_action( 'mainwp_child_reports_log', 'wptimecapsule' );
        } else {
            $this->do_reports_log( 'wptimecapsule' );
        }
    }

    /**
     * Add WP Time Capsule data to the reports database table.
     *
     * @param string $ext Current extension.
     *
     * @uses \MainWP\Child\MainWP_Helper::instance()->check_classes_exists() Check if the requested class exists.
     * @uses \MainWP\Child\MainWP_Helper::instance()->check_methods() Check if the requested method exists.
     * @uses \MainWP\Child\MainWP_Utility::update_lasttime_backup() Get the last backup timestamp.
     * @uses \MainWP\Child\MainWP_Utility::get_lasttime_backup()
     *
     * @used-by \MainWP\Child\MainWP_Child_Timecapsule::do_site_stats() Add support for the reporting system.
     */
    public function do_reports_log( $ext = '' ) {

        if ( 'wptimecapsule' !== $ext ) {
            return;
        }

        if ( ! $this->is_plugin_installed ) {
            return;
        }

        try {
            MainWP_Helper::instance()->check_classes_exists( array( '\WPTC_Factory' ) );

            $config = \WPTC_Factory::get( 'config' );

            MainWP_Helper::instance()->check_methods( $config, 'get_option' );

            $backup_time = $config->get_option( 'last_backup_time' );

            if ( ! empty( $backup_time ) ) {
                MainWP_Utility::update_lasttime_backup( 'wptimecapsule', $backup_time );
            }

            $last_time       = time() - 24 * 7 * 2 * 60 * 60;
            $lasttime_logged = MainWP_Utility::get_lasttime_backup( 'wptimecapsule' );
            if ( empty( $lasttime_logged ) ) {
                $last_time = time() - 24 * 7 * 8 * 60 * 60;
            }

            $all_last_backups = $this->get_backups( $last_time );

            if ( is_array( $all_last_backups ) ) {
                $formatted_backups = array();
                foreach ( $all_last_backups as $key => $value ) {
                    $value_array                                     = (array) $value;
                    $formatted_backups[ $value_array['backupID'] ][] = $value_array;
                }
                $message     = 'WP Time Capsule backup finished';
                $backup_type = 'WP Time Capsule backup';
                if ( ! empty( $formatted_backups ) ) {
                    foreach ( $formatted_backups as $key => $value ) {
                        $backup_time = $key;
                        do_action( 'mainwp_reports_wptimecapsule_backup', $message, $backup_type, $backup_time );
                    }
                }
            }
        } catch ( MainWP_Exception $e ) {
            // ok.
        }
    }

    /**
     * Include database tables.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     */
    public function include_table_list() {
        // phpcs:disable WordPress.Security.NonceVerification
        if ( ! isset( $_POST['data'] ) ) {
            wptc_die_with_json_encode( array( 'status' => 'no data found' ) );
        }
        $category          = isset( $_POST['data']['category'] ) ? wp_unslash( $_POST['data']['category'] ) : array(); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        $exclude_class_obj = new \Wptc_ExcludeOption( $category );
        $data              = isset( $_POST['data'] ) ? wp_unslash( $_POST['data'] ) : array(); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        // phpcs:enable WordPress.Security.NonceVerification
        $exclude_class_obj->include_table_list( $data );
        die();
    }

    /**
     * Include database table structure only.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     */
    public function include_table_structure_only() {
        // phpcs:disable WordPress.Security.NonceVerification
        if ( ! isset( $_POST['data'] ) ) {
            wptc_die_with_json_encode( array( 'status' => 'no data found' ) );
        }

        $category          = isset( $_POST['data']['category'] ) ? wp_unslash( $_POST['data']['category'] ) : array(); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        $exclude_class_obj = new \Wptc_ExcludeOption( $category );
        $data              = isset( $_POST['data'] ) ? wp_unslash( $_POST['data'] ) : array(); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        // phpcs:enable WordPress.Security.NonceVerification
        $exclude_class_obj->include_table_structure_only( $data );
        die();
    }

    /**
     * Include files list.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     */
    public function include_file_list() {
        // phpcs:disable WordPress.Security.NonceVerification
        if ( ! isset( $_POST['data'] ) ) {
            wptc_die_with_json_encode( array( 'status' => 'no data found' ) );
        }
        $category          = isset( $_POST['category'] ) ? wp_unslash( $_POST['category'] ) : array(); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        $exclude_class_obj = new \Wptc_ExcludeOption( $category );
        $data              = isset( $_POST['data'] ) ? wp_unslash( $_POST['data'] ) : array(); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        // phpcs:enable WordPress.Security.NonceVerification
        $exclude_class_obj->include_file_list( wp_unslash( $data ) );
        die();
    }

    /**
     * Get files by key.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     */
    public function get_files_by_key() {
        // phpcs:disable WordPress.Security.NonceVerification
        $key      = isset( $_POST['key'] ) ? wp_unslash( $_POST['key'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        $category = isset( $_POST['category'] ) ? wp_unslash( $_POST['category'] ) : array(); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        // phpcs:enable WordPress.Security.NonceVerification
        $exclude_class_obj = new \Wptc_ExcludeOption( $category );
        $exclude_class_obj->get_files_by_key( $key );
        die();
    }

    /**
     * Process the WP Time Capsule login process.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     *
     * @return array Action result.
     */
    private function process_wptc_login() { // phpcs:ignore -- NOSONAR - 3rd compatible, multi return.
        $options_helper = new \Wptc_Options_Helper();

        if ( $options_helper->get_is_user_logged_in() ) {
            return array(
                'result'    => 'is_user_logged_in',
                'sync_data' => $this->get_sync_data(),
            );
        }
        // phpcs:disable WordPress.Security.NonceVerification
        $email = isset( $_POST['acc_email'] ) ? sanitize_text_field( wp_unslash( $_POST['acc_email'] ) ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        $pwd   = isset( $_POST['acc_pwd'] ) ? wp_unslash( $_POST['acc_pwd'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        // phpcs:enable WordPress.Security.NonceVerification
        if ( empty( $email ) || empty( $pwd ) ) {
            return array( 'error' => 'Username and password cannot be empty' );
        }

        $config  = \WPTC_Base_Factory::get( 'Wptc_InitialSetup_Config' );
        $options = \WPTC_Factory::get( 'config' );

        $config->set_option( 'wptc_main_acc_email_temp', base64_encode( $email ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode function is used for http encode compatible..
        $config->set_option( 'wptc_main_acc_pwd_temp', base64_encode( md5( trim( wp_unslash( $pwd ) ) ) ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- NOSONAR - compatible, base64_encode function is used for http encode compatible..
        $config->set_option( 'wptc_token', false );

        $cust_info = $options->request_service(
            array(
                'email'                 => $email,
                'pwd'                   => trim( wp_unslash( $pwd ) ),
                'return_response'       => true,
                'sub_action'            => false,
                'login_request'         => true,
                'reset_login_if_failed' => true,
            )
        );

        if ( ! empty( $cust_info->error ) ) {
            if ( ! empty( $cust_info->true_err_msg ) ) {
                return array( 'error' => $cust_info->true_err_msg );
            }

            return array( 'error' => $cust_info->error );
        }

        $options->reset_plans();

        $main_account_email = $email;
        $main_account_pwd   = $pwd;

        $options->set_option( 'main_account_email', strtolower( $main_account_email ) );
        $options->set_option( 'main_account_pwd', $this->hash_pwd( $main_account_pwd ) );

        $result = $this->proccess_cust_info( $options, $cust_info );

        if ( is_array( $result ) && ! empty( $result['error'] ) ) {
            return array( 'error' => $result['error'] );
        }

        $is_user_logged_in = $options->get_option( 'is_user_logged_in' );

        if ( ! $is_user_logged_in ) {
            return array( 'error' => 'Login failed.' );
        }
        return array(
            'result'    => 'ok',
            'sync_data' => $this->get_sync_data(),
        );
    }

    /**
     * Hash password.
     *
     * @param string $str String to hash.
     *
     * @return string Hashed password.
     */
    public function hash_pwd( $str ) {
        return md5( $str ); // NOSONAR - 3rd compatible.
    }

    /**
     * Process the sigin response info.
     *
     * @param object $options   Options object.
     * @param object $cust_info Custon info.
     *
     * @return bool Action result.
     */
    public function proccess_cust_info( $options, $cust_info ) {

        if ( $this->process_service_info( $options, $cust_info ) ) {

            if ( empty( $cust_info->success ) ) {
                return false;
            }

            $cust_req_info = $cust_info->success[0];
            $this_d_name   = $cust_req_info->cust_display_name;
            $this_token    = $cust_req_info->wptc_token;

            $options->set_option( 'uuid', $cust_req_info->uuid );
            $options->set_option( 'wptc_token', $this_token );
            $options->set_option( 'main_account_name', $this_d_name );

            do_action( 'update_white_labling_settings_wptc', $cust_req_info );

            if ( isset( $cust_req_info->connected_sites_count ) ) {
                $options->set_option( 'connected_sites_count', $cust_req_info->connected_sites_count );
            } else {
                $options->set_option( 'connected_sites_count', 1 );
            }

            if ( ! empty( $cust_info->logged_in_but_no_plans_yet ) ) {
                $options->do_options_for_no_plans_yet( $cust_info );
                return false;
            }

            $options->process_subs_info_wptc( $cust_req_info );
            $this->process_privilege_wptc( $options, $cust_req_info );
            $this->save_plan_info_limited( $options, $cust_req_info );

            $is_cron_service = $this->check_if_cron_service_exists( $options );
            wptc_log( $is_cron_service, '--------$is_cron_service--------' );

            if ( $is_cron_service ) {
                $options->set_option( 'is_user_logged_in', true );
                return true;
            }
        }
    }


    /**
     * Save the plan info.
     *
     * @param object $options   Options object.
     * @param object $cust_info Custon info.
     *
     * @return bool Action result.
     */
    private function save_plan_info_limited( $options, &$cust_info ) {
        wptc_log( func_get_args(), '--------' . __FUNCTION__ . '--------' );
        if ( empty( $cust_info ) || empty( $cust_info->plan_info_limited ) ) {
            return $options->set_option( 'plan_info_limited', false );
        } else {
            $plans = json_decode( wp_json_encode( $cust_info->plan_info_limited ), true );
            wptc_log( $plans, '----------$plans----------------' );
            return $options->set_option( 'plan_info_limited', serialize( $plans ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- Required for backwards compatibility.
        }
    }

    /**
     * Process privilege wptc.
     *
     * @param object $options       Options object.
     * @param object $cust_req_info Custon info.
     *
     * @return bool Returns false on failure.
     */
    private function process_privilege_wptc( $options, $cust_req_info = null ) {

        if ( empty( $cust_req_info->subscription_features ) ) {
            $options->reset_privileges();
            return false;
        }

        $sub_features = (array) $cust_req_info->subscription_features;

        $privileged_feature = array();
        $privileges_args    = array();

        foreach ( $sub_features as $single_sub ) {
            foreach ( $single_sub as $v ) {
                $privileged_feature[ $v->type ][]                    = 'Wptc_' . ucfirst( $v->feature );
                $privileges_args[ 'Wptc_' . ucfirst( $v->feature ) ] = ( ! empty( $v->args ) ) ? $v->args : array();
            }
        }

        // Remove on production!
        array_push( $privileges_args, 'Wptc_Rollback' );
        array_push( $privileged_feature['pro'], 'Wptc_Rollback' );

        $options->set_option( 'privileges_wptc', wp_json_encode( $privileged_feature ) );
        $options->set_option( 'privileges_args', wp_json_encode( $privileges_args ) );
        $revision_limit = new \Wptc_Revision_Limit();
        $revision_limit->update_eligible_revision_limit( $privileges_args );
    }

    /**
     * Process service info.
     *
     * @param object $options   Options object.
     * @param object $cust_info Custon info.
     *
     * @return bool result.
     */
    private function process_service_info( $options, &$cust_info ) {
        if ( empty( $cust_info ) || ! empty( $cust_info->error ) ) {
            $err_msg = $options->process_wptc_error_msg_then_take_action( $cust_info );

            $options->set_option( 'card_added', false );

            if ( 'logged_in_but_no_plans_yet' === $err_msg ) {
                $options->do_options_for_no_plans_yet( $cust_info );

                return true;
            }
            return false;
        } else {
            return true;
        }
    }

    /**
     * Process service info.
     *
     * @param object $options Options object.
     *
     * @return bool Result.
     */
    public function check_if_cron_service_exists( $options ) {
        if ( ( ! $options->get_option( 'wptc_server_connected' ) || ! $options->get_option( 'appID' ) || $options->get_option( 'signup' ) !== 'done' ) && $options->get_option( 'main_account_email' ) ) {
            $this->signup_wptc_server_wptc();
        }
        return true;
    }


    /**
     * Function for wptc cron service signup
     *
     * @return bool result.
     */
    public function signup_wptc_server_wptc() {

        $config = \WPTC_Factory::get( 'config' );

        $email         = trim( $config->get_option( 'main_account_email', true ) );
        $emailhash     = md5( $email ); // NOSONAR - 3rd compatible.
        $email_encoded = base64_encode( $email ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- Required for backwards compatibility.

        $pwd         = trim( $config->get_option( 'main_account_pwd', true ) );
        $pwd_encoded = base64_encode( $pwd ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- Required for backwards compatibility.

        if ( empty( $email ) || empty( $pwd ) ) {
            return false;
        }

        wptc_log( $email, '--------email--------' );

        $name = trim( $config->get_option( 'main_account_name' ) );

        $cron_url = get_wptc_cron_url();

        $app_id = 0;
        if ( $config->get_option( 'appID' ) ) {
            $app_id = $config->get_option( 'appID' );
        }

        $post_arr = array(
            'email'     => $email_encoded,
            'pwd'       => $pwd_encoded,
            'cron_url'  => $cron_url,
            'site_url'  => home_url(),
            'name'      => $name,
            'emailhash' => $emailhash,
            'app_id'    => $app_id,
        );

        $result = do_cron_call_wptc( 'signup', $post_arr );

        $resarr = json_decode( $result );

        wptc_log( $resarr, '--------resarr-node reply--------' );

        if ( ! empty( $resarr ) && 'success' === $resarr->status ) {
            $config->set_option( 'wptc_server_connected', true );
            $config->set_option( 'signup', 'done' );
            $config->set_option( 'appID', $resarr->appID );

            init_auto_backup_settings_wptc( $config );
            return true;
        } else {
            $config->set_option( 'last_service_error', $result );
            $config->set_option( 'appID', false );

            if ( 'production' !== WPTC_ENV ) {
                echo 'Creating Cron service failed';
            }

            return false;
        }
    }

    /**
     * Get the list of installed plugins.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     *
     * @return array Action result.
     */
    public function get_installed_plugins() {

        $backup_before_auto_update_settings = \WPTC_Pro_Factory::get( 'Wptc_Backup_Before_Auto_Update_Settings' );
        $plugins                            = $backup_before_auto_update_settings->get_installed_plugins();

        if ( $plugins ) {
            return array( 'results' => $plugins );
        }
        return array( 'results' => array() );
    }

    /**
     * Get the list of installed themes.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     *
     * @return array Action result.
     */
    public function get_installed_themes() {

        $backup_before_auto_update_settings = \WPTC_Pro_Factory::get( 'Wptc_Backup_Before_Auto_Update_Settings' );

        $plugins = $backup_before_auto_update_settings->get_installed_themes();
        if ( $plugins ) {
            return array( 'results' => $plugins );
        }
        return array( 'results' => array() );
    }

    /**
     * Check if staging request needed.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     */
    public function is_staging_need_request() {
        $staging = \WPTC_Pro_Factory::get( 'Wptc_Staging' );
        $staging->is_staging_need_request();
        die();
    }

    /**
     * Get the staging details.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     */
    public function get_staging_details_wptc() {
        $staging               = \WPTC_Pro_Factory::get( 'Wptc_Staging' );
        $details               = $staging->get_staging_details();
        $details['is_running'] = $staging->is_any_staging_process_going_on();
        wptc_die_with_json_encode( $details, 1 );
    }

    /**
     * Create a fresh staging site.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     */
    public function start_fresh_staging_wptc() {
        $staging = \WPTC_Pro_Factory::get( 'Wptc_Staging' );
        // phpcs:disable WordPress.Security.NonceVerification
        if ( empty( $_POST['path'] ) ) {
            wptc_die_with_json_encode(
                array(
                    'status' => 'error',
                    'msg'    => 'path is missing',
                )
            );
        }

        $staging->choose_action( wp_unslash( $_POST['path'] ), 'fresh' ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        // phpcs:enable WordPress.Security.NonceVerification
        die();
    }

    /**
     * Get the staging site URL.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     */
    public function get_staging_url_wptc() {
        $staging = \WPTC_Pro_Factory::get( 'Wptc_Staging' );
        $staging->get_staging_url_wptc();
        die();
    }

    /**
     * Stop the staging site creation process.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     */
    public function stop_staging_wptc() {
        $staging = \WPTC_Pro_Factory::get( 'Wptc_Staging' );
        $staging->stop_staging_wptc();
        die();
    }

    /**
     * Continue the staging site creation process.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     */
    public function continue_staging_wptc() {
        $staging = \WPTC_Pro_Factory::get( 'Wptc_Staging' );
        $staging->choose_action();
        die();
    }

    /**
     * Delete the staging site.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     */
    public function delete_staging_wptc() {
        $staging = \WPTC_Pro_Factory::get( 'Wptc_Staging' );
        $staging->delete_staging_wptc();
        die();
    }

    /**
     * Copy the staging site.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     */
    public function copy_staging_wptc() {
        $staging = \WPTC_Pro_Factory::get( 'Wptc_Staging' );
        $staging->choose_action( false, 'copy' );
        die();
    }

    /**
     * Get the current staging site status key.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     */
    public function get_staging_current_status_key() {
        $staging = \WPTC_Pro_Factory::get( 'Wptc_Staging' );
        $staging->get_staging_current_status_key();
        die();
    }

    /**
     * Sync the WP Time Capsule purchase.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     */
    public function wptc_sync_purchase() {
        $config = \WPTC_Factory::get( 'config' );

        $config->request_service(
            array(
                'email'           => false,
                'pwd'             => false,
                'return_response' => false,
                'sub_action'      => 'sync_all_settings_to_node',
                'login_request'   => true,
            )
        );
        die();
    }

    /**
     * Initiate the restore process.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     */
    public function init_restore() {
        // phpcs:disable WordPress.Security.NonceVerification
        if ( empty( $_POST ) ) {
            wptc_die_with_json_encode( array( 'error' => 'Backup id is empty !' ) );
        }
        $restore_to_staging = \WPTC_Base_Factory::get( 'Wptc_Restore_To_Staging' );
        $restore_to_staging->init_restore( $_POST );
        // phpcs:enable WordPress.Security.NonceVerification
        die();
    }

    /**
     * Save the WP Time Capsule settings.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     */
    public function save_settings_wptc() {

        $options_helper = new \Wptc_Options_Helper();

        if ( ! $options_helper->get_is_user_logged_in() ) {
            return array(
                'sync_data' => $this->get_sync_data(),
                'error'     => 'Login to your WP Time Capsule account first',
            );
        }

        // phpcs:disable WordPress.Security.NonceVerification
        $data = isset( $_POST['data'] ) ? json_decode( base64_decode( wp_unslash( $_POST['data'] ) ), true ) : array(); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized,WordPress.PHP.DiscouragedPHPFunctions -- base64_encode required for the backwards compatibility.

        $tabName    = isset( $_POST['tabname'] ) ? sanitize_text_field( wp_unslash( $_POST['tabname'] ) ) : '';
        $is_general = isset( $_POST['is_general'] ) ? sanitize_text_field( wp_unslash( $_POST['is_general'] ) ) : '';
        // phpcs:enable WordPress.Security.NonceVerification

        $saved  = false;
        $config = \WPTC_Factory::get( 'config' );
        if ( 'backup' === $tabName ) {
            $this->save_settings_backup_tab( $config, $data );
            $saved = true;
        } elseif ( 'backup_auto' === $tabName ) {
            $this->save_settings_backup_auto_tab( $config, $data, $is_general );
            $saved = true;
        } elseif ( 'vulns_update' === $tabName ) {
            $this->save_settings_vulns_update_tab( $config, $data, $is_general );
            $saved = true;
        } elseif ( 'staging_opts' === $tabName ) {
            $this->save_settings_staging_opts_tab( $config, $data, $is_general );
            $saved = true;
        }
        if ( ! $saved ) {
            return array( 'error' => 'Error: Not saved settings' );
        }
        return array( 'result' => 'ok' );
    }

    /**
     * Save the WP Time Capsule settings - backups section.
     *
     * @param object $config Save config class.
     * @param array  $data   Data to save.
     */
    private function save_settings_backup_tab( $config, $data ) {

        $config->set_option( 'user_excluded_extenstions', $data['user_excluded_extenstions'] );
        $config->set_option( 'user_excluded_files_more_than_size_settings', $data['user_excluded_files_more_than_size_settings'] );

        if ( ! empty( $data['backup_slot'] ) ) {
            $config->set_option( 'old_backup_slot', $config->get_option( 'backup_slot' ) );
            $config->set_option( 'backup_slot', $data['backup_slot'] );
        }

        $config->set_option( 'backup_db_query_limit', $data['backup_db_query_limit'] );
        $config->set_option( 'database_encrypt_settings', $data['database_encrypt_settings'] );
        $config->set_option( 'wptc_timezone', $data['wptc_timezone'] );
        $config->set_option( 'schedule_time_str', $data['schedule_time_str'] );

        if ( ! empty( $data['schedule_time_str'] ) && ! empty( $data['wptc_timezone'] ) && function_exists( 'wptc_modify_schedule_backup' ) ) {
            wptc_modify_schedule_backup();
        }

        $notice = apply_filters( 'check_requirements_auto_backup_wptc', '' );

        if ( ! empty( $data['revision_limit'] ) && ! $notice ) {
            $notice = apply_filters( 'save_settings_revision_limit_wptc', $data['revision_limit'] ); // NOSONAR - apply 3rd filter.
        }
    }

    /**
     * Save the WP Time Capsule settings - backups auto section.
     *
     * @param object $config     Save config class.
     * @param array  $data       Data to save.
     * @param bool   $is_general Is general settings check.
     */
    private function save_settings_backup_auto_tab( $config, $data, $is_general ) {
        $config->set_option( 'backup_before_update_setting', $data['backup_before_update_setting'] );
        $current                              = $config->get_option( 'wptc_auto_update_settings' );
        $current = unserialize( $current ); // phpcs:ignore -- safe internal value, third party.
        $new     = unserialize( $data['wptc_auto_update_settings'] ); // phpcs:ignore -- compatible third party // NOSONARR .
        $current['update_settings']['status'] = $new['update_settings']['status'];
        $current['update_settings']['schedule']['enabled']     = $new['update_settings']['schedule']['enabled'];
        $current['update_settings']['schedule']['time']        = $new['update_settings']['schedule']['time'];
        $current['update_settings']['core']['major']['status'] = $new['update_settings']['core']['major']['status'];
        $current['update_settings']['core']['minor']['status'] = $new['update_settings']['core']['minor']['status'];
        $current['update_settings']['themes']['status']        = $new['update_settings']['themes']['status'];
        $current['update_settings']['plugins']['status']       = $new['update_settings']['plugins']['status'];

        if ( ! $is_general ) {
            if ( isset( $new['update_settings']['plugins']['included'] ) ) {
                $current['update_settings']['plugins']['included'] = $new['update_settings']['plugins']['included'];
            } else {
                $current['update_settings']['plugins']['included'] = array();
            }

            if ( isset( $new['update_settings']['themes']['included'] ) ) {
                $current['update_settings']['themes']['included'] = $new['update_settings']['themes']['included'];
            } else {
                $current['update_settings']['themes']['included'] = array();
            }
        }
        $config->set_option( 'wptc_auto_update_settings', serialize( $current ) ); // phpcs:ignore -- safe internal value.
    }

    /**
     * Save the WP Time Capsule settings - vulnerable updates section.
     *
     * @param object $config     Save config class.
     * @param array  $data       Data to save.
     * @param bool   $is_general Is general settings check.
     */
    private function save_settings_vulns_update_tab( $config, $data, $is_general ) {
        $current = $config->get_option( 'vulns_settings' );
        $current = unserialize( $current ); // phpcs:ignore -- safe internal value, third party.
        $new     = unserialize( $data['vulns_settings'] ); // phpcs:ignore -- third party compatible // NOSONARR .

        $current['status']            = $new['status'];
        $current['core']['status']    = $new['core']['status'];
        $current['themes']['status']  = $new['themes']['status'];
        $current['plugins']['status'] = $new['plugins']['status'];

        if ( ! $is_general ) {
            $vulns_plugins_included = ! empty( $new['plugins']['vulns_plugins_included'] ) ? $new['plugins']['vulns_plugins_included'] : array();

            $plugin_include_array = array();

            if ( ! empty( $vulns_plugins_included ) ) {
                $plugin_include_array = explode( ',', $vulns_plugins_included );
                $plugin_include_array = ! empty( $plugin_include_array ) ? $plugin_include_array : array();
            }

            wptc_log( $plugin_include_array, '--------$plugin_include_array--------' );

            $included_plugins = $this->filter_plugins( $plugin_include_array );

            wptc_log( $included_plugins, '--------$included_plugins--------' );

            $current['plugins']['excluded'] = serialize( $included_plugins ); // phpcs:ignore -- safe internal value, third party.

            $vulns_themes_included = ! empty( $new['themes']['vulns_themes_included'] ) ? $new['themes']['vulns_themes_included'] : array();

            $themes_include_array = array();

            if ( ! empty( $vulns_themes_included ) ) {
                $themes_include_array = explode( ',', $vulns_themes_included );
            }

            $included_themes               = $this->filter_themes( $themes_include_array );
            $current['themes']['excluded'] = serialize( $included_themes ); // phpcs:ignore -- safe internal value, third party.
        }
        $config->set_option( 'vulns_settings', serialize( $current ) ); // phpcs:ignore -- safe internal value, third party.
    }

    /**
     * Save the WP Time Capsule settings - staging section.
     *
     * @param object $config     Save config class.
     * @param array  $data       Data to save.
     * @param bool   $is_general Is general settings check.
     */
    private function save_settings_staging_opts_tab( $config, $data, $is_general ) {
        $config->set_option( 'user_excluded_extenstions_staging', $data['user_excluded_extenstions_staging'] );
        $config->set_option( 'internal_staging_db_rows_copy_limit', $data['internal_staging_db_rows_copy_limit'] );
        $config->set_option( 'internal_staging_file_copy_limit', $data['internal_staging_file_copy_limit'] );
        $config->set_option( 'internal_staging_deep_link_limit', $data['internal_staging_deep_link_limit'] );
        $config->set_option( 'internal_staging_enable_admin_login', $data['internal_staging_enable_admin_login'] );
        $config->set_option( 'staging_is_reset_permalink', $data['staging_is_reset_permalink'] );
        if ( ! $is_general ) {
            $config->set_option( 'staging_login_custom_link', $data['staging_login_custom_link'] );
        }
    }

    /**
     * Filter plugins.
     *
     * @param array $included_plugins List of included plugins.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     *
     * @return array Filtered list of plugins.
     */
    private function filter_plugins( $included_plugins ) {
        $app_functions       = \WPTC_Base_Factory::get( 'Wptc_App_Functions' );
        $specific            = true;
        $attr                = 'slug';
        $plugins_data        = $app_functions->get_all_plugins_data( $specific, $attr );
        $not_included_plugin = array_diff( $plugins_data, $included_plugins );
        wptc_log( $plugins_data, '--------$plugins_data--------' );
        wptc_log( $not_included_plugin, '--------$not_included_plugin--------' );
        return $not_included_plugin;
    }

    /**
     * Filter themes.
     *
     * @param array $included_themes List of included themes.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     *
     * @return array Filtered list of themes.
     */
    private function filter_themes( $included_themes ) {
        $app_functions      = \WPTC_Base_Factory::get( 'Wptc_App_Functions' );
        $specific           = true;
        $attr               = 'slug';
        $themes_data        = $app_functions->get_all_themes_data( $specific, $attr );
        $not_included_theme = array_diff( $themes_data, $included_themes );
        wptc_log( $themes_data, '--------$themes_data--------' );
        wptc_log( $not_included_theme, '--------$not_included_theme--------' );
        return $not_included_theme;
    }

    /**
     * Analyze database tables.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     */
    public function analyze_inc_exc() {
        $exclude_opts_obj = \WPTC_Base_Factory::get( 'Wptc_ExcludeOption' );
        $exclude_opts_obj = $exclude_opts_obj->analyze_inc_exc();
        die();
    }

    /**
     * Get enabled plugins.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     *
     * @return array Action result.
     */
    public function get_enabled_plugins() {
        $vulns_obj = \WPTC_Base_Factory::get( 'Wptc_Vulns' );

        $plugins = $vulns_obj->get_enabled_plugins();
        $plugins = \WPTC_Base_Factory::get( 'Wptc_App_Functions' )->fancytree_format( $plugins, 'plugins' );

        return array( 'results' => $plugins );
    }

    /**
     * Get enabled themes.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     *
     * @return array Action result.
     */
    public function get_enabled_themes() {
        $vulns_obj = \WPTC_Base_Factory::get( 'Wptc_Vulns' );
        $themes    = $vulns_obj->get_enabled_themes();
        $themes    = \WPTC_Base_Factory::get( 'Wptc_App_Functions' )->fancytree_format( $themes, 'themes' );
        return array( 'results' => $themes );
    }

    /**
     * Get the system info.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     *
     * @return array Action result.
     */
    public function get_system_info() {

        /**
         * Object, providing access to the WordPress database.
         *
         * @global $wpdb WordPress Database instance.
         */
        global $wpdb;

        $wptc_settings = \WPTC_Base_Factory::get( 'Wptc_Settings' );

        ob_start();

        echo '<table class="wp-list-table widefat fixed" style="border-spacing:0;">';
        echo '<thead><tr><th width="35%">' . esc_html__( 'Setting', 'wp-time-capsule' ) . '</th><th>' . esc_html__( 'Value', 'wp-time-capsule' ) . '</th></tr></thead>';
        echo '<tr title="&gt;=3.9.14"><td>' . esc_html__( 'WordPress version', 'wp-time-capsule' ) . '</td><td>' . esc_html( $wptc_settings->get_plugin_data( 'wp_version' ) ) . '</td></tr>';
        echo '<tr title=""><td>' . esc_html__( 'WP Time Capsule version', 'wp-time-capsule' ) . '</td><td>' . esc_html( $wptc_settings->get_plugin_data( 'Version' ) ) . '</td></tr>';

        $bit = '';
        if ( PHP_INT_SIZE === 4 ) {
            $bit = ' (32bit)';
        }
        if ( PHP_INT_SIZE === 8 ) {
            $bit = ' (64bit)';
        }

        echo '<tr title="&gt;=5.3.1"><td>' . esc_html__( 'PHP version', 'wp-time-capsule' ) . '</td><td>' . esc_html( PHP_VERSION . ' ' . $bit ) . '</td></tr>';

        // Retrieve MySQL version with caching (static server metadata).
        $mysql_version = wp_cache_get( 'mainwp_timecapsule_mysql_version', 'mainwp_timecapsule' );
        if ( false === $mysql_version ) {
            $mysql_version = $wpdb->get_var( 'SELECT VERSION() AS version' ); //phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- Static server metadata, cached for 1 hour.
            wp_cache_set( 'mainwp_timecapsule_mysql_version', $mysql_version, 'mainwp_timecapsule', 3600 );
        }
        echo '<tr title="&gt;=5.0.15"><td>' . esc_html__( 'MySQL version', 'wp-time-capsule' ) . '</td><td>' . esc_html( $mysql_version ) . '</td></tr>';

        if ( function_exists( 'curl_version' ) ) {
            $curlversion = curl_version();
            echo '<tr title=""><td>' . esc_html__( 'cURL version', 'wp-time-capsule' ) . '</td><td>' . esc_html( $curlversion['version'] ) . '</td></tr>';
            echo '<tr title=""><td>' . esc_html__( 'cURL SSL version', 'wp-time-capsule' ) . '</td><td>' . esc_html( $curlversion['ssl_version'] ) . '</td></tr>';
        } else {
            echo '<tr title=""><td>' . esc_html__( 'cURL version', 'wp-time-capsule' ) . '</td><td>' . esc_html__( 'unavailable', 'wp-time-capsule' ) . '</td></tr>';
        }

        echo '</td></tr>';
        echo '<tr title=""><td>' . esc_html__( 'Server', 'wp-time-capsule' ) . '</td><td>' . ( isset( $_SERVER['SERVER_SOFTWARE'] ) ? esc_html( sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ) ) : '' ) . '</td></tr>';
        echo '<tr title=""><td>' . esc_html__( 'Operating System', 'wp-time-capsule' ) . '</td><td>' . esc_html( PHP_OS ) . '</td></tr>';
        echo '<tr title=""><td>' . esc_html__( 'PHP SAPI', 'wp-time-capsule' ) . '</td><td>' . esc_html( PHP_SAPI ) . '</td></tr>';

        $php_user = esc_html__( 'Function Disabled', 'wp-time-capsule' );
        if ( function_exists( 'get_current_user' ) ) {
            $php_user = get_current_user();
        }

        echo '<tr title=""><td>' . esc_html__( 'Current PHP user', 'wp-time-capsule' ) . '</td><td>' . esc_html( $php_user ) . '</td></tr>';
        echo '<tr title="&gt;=30"><td>' . esc_html__( 'Maximum execution time', 'wp-time-capsule' ) . '</td><td>' . esc_html( ini_get( 'max_execution_time' ) ) . ' ' . esc_html__( 'seconds', 'wp-time-capsule' ) . '</td></tr>';

        if ( defined( 'FS_CHMOD_DIR' ) ) {
            echo '<tr title="FS_CHMOD_DIR"><td>' . esc_html__( 'CHMOD Dir', 'wp-time-capsule' ) . '</td><td>' . esc_html( FS_CHMOD_DIR ) . '</td></tr>';
        } else {
            echo '<tr title="FS_CHMOD_DIR"><td>' . esc_html__( 'CHMOD Dir', 'wp-time-capsule' ) . '</td><td>0755</td></tr>';
        }

        $now = localtime( time(), true );
        echo '<tr title=""><td>' . esc_html__( 'Server Time', 'wp-time-capsule' ) . '</td><td>' . esc_html( $now['tm_hour'] . ':' . $now['tm_min'] ) . '</td></tr>';
        echo '<tr title=""><td>' . esc_html__( 'Blog Time', 'wp-time-capsule' ) . '</td><td>' . esc_html( date( 'H:i', current_time( 'timestamp' ) ) ) . '</td></tr>'; // phpcs:ignore -- local time.
        echo '<tr title="WPLANG"><td>' . esc_html__( 'Blog language', 'wp-time-capsule' ) . '</td><td>' . esc_html( get_bloginfo( 'language' ) ) . '</td></tr>';
        echo '<tr title="utf8"><td>' . esc_html__( 'MySQL Client encoding', 'wp-time-capsule' ) . '</td><td>';
        echo defined( 'DB_CHARSET' ) ? esc_html( DB_CHARSET ) : '';
        echo '</td></tr>';
        echo '<tr title="URF-8"><td>' . esc_html__( 'Blog charset', 'wp-time-capsule' ) . '</td><td>' . esc_html( get_bloginfo( 'charset' ) ) . '</td></tr>';
        echo '<tr title="&gt;=128M"><td>' . esc_html__( 'PHP Memory limit', 'wp-time-capsule' ) . '</td><td>' . esc_html( ini_get( 'memory_limit' ) ) . '</td></tr>';
        echo '<tr title="WP_MEMORY_LIMIT"><td>' . esc_html__( 'WP memory limit', 'wp-time-capsule' ) . '</td><td>' . esc_html( WP_MEMORY_LIMIT ) . '</td></tr>';
        echo '<tr title="WP_MAX_MEMORY_LIMIT"><td>' . esc_html__( 'WP maximum memory limit', 'wp-time-capsule' ) . '</td><td>' . esc_html( WP_MAX_MEMORY_LIMIT ) . '</td></tr>';
        echo '<tr title=""><td>' . esc_html__( 'Memory in use', 'wp-time-capsule' ) . '</td><td>' . esc_html( size_format( memory_get_usage( true ), 2 ) ) . '</td></tr>';

        // disabled PHP functions.
        $disabled = esc_html( ini_get( 'disable_functions' ) );
        if ( ! empty( $disabled ) ) {
            $disabledarry = explode( ',', $disabled );
            echo '<tr title=""><td>' . esc_html__( 'Disabled PHP Functions:', 'wp-time-capsule' ) . '</td><td>';
            echo esc_html( implode( ', ', $disabledarry ) );
            echo '</td></tr>';
        }

        // Loaded PHP Extensions.
        echo '<tr title=""><td>' . esc_html__( 'Loaded PHP Extensions:', 'wp-time-capsule' ) . '</td><td>';
        $extensions = get_loaded_extensions();
        sort( $extensions );
        echo esc_html( implode( ', ', $extensions ) );
        echo '</td></tr>';
        echo '</table>';

        $html = ob_get_clean();
        return array( 'result' => $html );
    }

    /**
     * Update vulnerable updates settings.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     *
     * @return array Action result.
     */
    public function update_vulns_settings() {

        $vulns_obj = \WPTC_Base_Factory::get( 'Wptc_Vulns' );
        // phpcs:disable WordPress.Security.NonceVerification
        $data = isset( $_POST['data'] ) ? wp_unslash( $_POST['data'] ) : array(); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        // phpcs:enable WordPress.Security.NonceVerification
        $vulns_obj->update_vulns_settings( $data );

        return array( 'success' => 1 );
    }

    /**
     * Start a fresh backup.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     *
     * @return array Action result.
     */
    public function start_fresh_backup_tc_callback_wptc() {
        $type            = '';
        $args            = null;
        $test_connection = true;
        $ajax_check      = false;
        start_fresh_backup_tc_callback_wptc( $type, $args, $test_connection, $ajax_check );
        return array( 'result' => 'success' );
    }

    /**
     * Save manual backup name.
     *
     * @used-by MainWP_Child_Timecapsule::action() Fire off certain WP Time Capsule plugin actions.
     */
    public function save_manual_backup_name_wptc() {
        // phpcs:disable WordPress.Security.NonceVerification
        $backup_name = isset( $_POST['backup_name'] ) ? sanitize_text_field( wp_unslash( $_POST['backup_name'] ) ) : '';
        // phpcs:enable WordPress.Security.NonceVerification
        $processed_files = \WPTC_Factory::get( 'processed-files' );
        $processed_files->save_manual_backup_name_wptc( $backup_name );
        die();
    }

    /**
     * Remove the WP Time Capsule plugin from the list of all plugins when the plugin is hidden.
     *
     * @param array $plugins Array containing all installed plugins.
     *
     * @return array $plugins Array containing all installed plugins without the WP Time Capsule.
     */
    public function all_plugins( $plugins ) {
        foreach ( $plugins as $key => $value ) {
            $plugin_slug = basename( $key, '.php' );
            if ( 'wp-time-capsule' === $plugin_slug ) {
                unset( $plugins[ $key ] );
            }
        }

        return $plugins;
    }

    /**
     * Remove the WP Time Capsule menu item when the plugin is hidden.
     */
    public function remove_menu() {
        remove_menu_page( 'wp-time-capsule-monitor' );
        $pos = isset( $_SERVER['REQUEST_URI'] ) ? stripos( esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ), 'admin.php?page=wp-time-capsule-monitor' ) : false;
        if ( false !== $pos ) {
            wp_safe_redirect( get_option( 'siteurl' ) . '/wp-admin/index.php' );
            exit();
        }
    }

    /**
     * Remove the WP Time Capsule plugin update notice when the plugin is hidden.
     *
     * @param array $slugs Array containing installed plugins slugs.
     *
     * @return array $slugs Array containing installed plugins slugs.
     */
    public function hide_update_notice( $slugs ) {
        $slugs[] = 'wp-time-capsule/wp-time-capsule.php';
        return $slugs;
    }

    /**
     * Remove the WP Time Capsule plugin update notice when the plugin is hidden.
     *
     * @param object $value Object containing update information.
     *
     * @return object $value Object containing update information.
     *
     * @uses \MainWP\Child\MainWP_Helper::is_updates_screen()
     */
    public function remove_update_nag( $value ) {
        if ( MainWP_Helper::is_dashboard_request() ) {
            return $value;
        }
        if ( ! MainWP_Helper::is_updates_screen() ) {
            return $value;
        }
        if ( isset( $value->response['wp-time-capsule/wp-time-capsule.php'] ) ) {
            unset( $value->response['wp-time-capsule/wp-time-capsule.php'] );
        }

        return $value;
    }
}
