| @@ -1,35 +1,309 @@ | ||
| 1 | 1 | <?php |
| 2 | 2 | |
| 3 | 3 | namespace Hostinger\Admin; |
| 4 | 4 | |
| 5 | +use Hostinger\Amplitude\Amplitude; | |
| 6 | +use Hostinger\Config; | |
| 7 | +use Hostinger\Settings; | |
| 8 | +use Hostinger\Helper; | |
| 9 | +use Hostinger\Admin\Onboarding\Onboarding; | |
| 10 | +use Hostinger\Requests\Client; | |
| 11 | +use Hostinger\Surveys\Rest\Rest as Surveys_Rest; | |
| 12 | +use Hostinger\Surveys\Surveys as Hostinger_Surveys; | |
| 13 | +use Hostinger\Surveys\Questions as Surveys_Questions; | |
| 14 | +use Hostinger\Admin\Actions as Admin_Actions; | |
| 15 | + | |
| 5 | 16 | defined( 'ABSPATH' ) || exit; |
| 6 | 17 | |
| 7 | 18 | class Ajax { |
| 8 | - private const TWO_DAYS = 86400 * 2; | |
| 9 | - public const AJAX_METHOD_PREFIX = 'wp_ajax_hostinger_'; | |
| 10 | - public const HIDE_PLUGIN_SPLIT_NOTICE = 'hts_plugin_split_notice_hidden'; | |
| 19 | + private const PROMOTIONAL_BANNER_TRANSIENT = 'hts_hide_promotional_banner_transient'; | |
| 20 | + private const HIDE_SURVEY_TRANSIENT = 'hts_hide_survey'; | |
| 21 | + private const HIDE_OMNISEND_NOTICE = 'hts_omnisend_notice_hidden'; | |
| 22 | + private const TWO_DAYS = 86400 * 2; | |
| 23 | + private const SIX_MONTHS = 15780000; | |
| 24 | + private const THIRTY_DAYS = 86400 * 30; | |
| 11 | 25 | |
| 12 | - public const AJAX_EVENTS = array( | |
| 13 | - 'dismiss_plugin_split_notice', | |
| 14 | - ); | |
| 26 | + private Config $config_handler; | |
| 27 | + private Settings $settings; | |
| 28 | + private Helper $helper; | |
| 29 | + private Surveys_Questions $survey_questions; | |
| 30 | + private Surveys_Rest $surveys_rest; | |
| 15 | 31 | |
| 16 | - public function __construct() { | |
| 17 | - add_action( 'admin_init', array( $this, 'define_ajax_events' ), 0 ); | |
| 18 | - } | |
| 32 | + public function __construct() { | |
| 33 | + $this->settings = new Settings(); | |
| 34 | + $this->helper = new Helper(); | |
| 35 | + $this->config_handler = new Config(); | |
| 19 | 36 | |
| 20 | - public function define_ajax_events(): void { | |
| 21 | - foreach ( self::AJAX_EVENTS as $event ) { | |
| 22 | - add_action( self::AJAX_METHOD_PREFIX . $event, array( $this, $event ) ); | |
| 23 | - } | |
| 24 | - } | |
| 37 | + if ( ! empty( Helper::get_api_token() ) ) { | |
| 38 | + $this->survey_questions = new Surveys_Questions(); | |
| 39 | + $client = new Client( | |
| 40 | + $this->config_handler->get_config_value( 'base_rest_uri', HOSTINGER_REST_URI ), | |
| 41 | + array( | |
| 42 | + Config::TOKEN_HEADER => $this->helper::get_api_token(), | |
| 43 | + Config::DOMAIN_HEADER => $this->helper->get_host_info(), | |
| 44 | + ) | |
| 45 | + ); | |
| 25 | 46 | |
| 26 | - public function dismiss_plugin_split_notice(): void { | |
| 27 | - $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( $_POST['nonce'] ) : ''; | |
| 28 | - // @codeCoverageIgnoreStart | |
| 29 | - if ( ! wp_verify_nonce( $nonce, 'hts_close_plugin_split' ) ) { | |
| 30 | - wp_send_json_error( 'Invalid nonce' ); | |
| 31 | - } | |
| 32 | - // @codeCoverageIgnoreEnd | |
| 33 | - update_option( self::HIDE_PLUGIN_SPLIT_NOTICE, true ); | |
| 34 | - } | |
| 47 | + $this->surveys_rest = new Surveys_Rest( $client ); | |
| 48 | + } | |
| 49 | + | |
| 50 | + add_action( 'init', array( $this, 'define_ajax_events' ), 0 ); | |
| 51 | + } | |
| 52 | + | |
| 53 | + public function define_ajax_events(): void { | |
| 54 | + $events = array( | |
| 55 | + 'complete_onboarding_step', | |
| 56 | + 'publish_website', | |
| 57 | + 'identify_action', | |
| 58 | + 'menu_action', | |
| 59 | + 'woocommerce_setup_store', | |
| 60 | + 'hide_promotional_banner', | |
| 61 | + 'get_survey', | |
| 62 | + 'submit_survey', | |
| 63 | + 'hide_survey', | |
| 64 | + 'dismiss_omnisend_notice', | |
| 65 | + ); | |
| 66 | + | |
| 67 | + foreach ( $events as $event ) { | |
| 68 | + add_action( 'wp_ajax_hostinger_' . $event, array( $this, $event ) ); | |
| 69 | + } | |
| 70 | + | |
| 71 | + if ( Helper::is_woocommerce_site() ) { | |
| 72 | + add_action( 'wp_ajax_hostinger_woo_onboarding_choice', array( $this, 'woo_onboarding_choice' ) ); | |
| 73 | + } | |
| 74 | + } | |
| 75 | + | |
| 76 | + public function get_survey(): void { | |
| 77 | + $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( $_POST['nonce'] ) : ''; | |
| 78 | + $type = isset( $_POST['type'] ) ? sanitize_text_field( $_POST['type'] ) : 'ai_survey'; | |
| 79 | + $security_check = $this->request_security_check( $nonce ); | |
| 80 | + | |
| 81 | + if ( ! empty( $security_check ) ) { | |
| 82 | + wp_send_json_error( $security_check ); | |
| 83 | + } | |
| 84 | + | |
| 85 | + if ( get_transient( self::HIDE_SURVEY_TRANSIENT ) ) { | |
| 86 | + wp_send_json_error( 'Survey hidden' ); | |
| 87 | + } | |
| 88 | + | |
| 89 | + $surveys = new Hostinger_Surveys( $this->settings, $this->helper, $this->config_handler, $this->survey_questions, $this->surveys_rest ); | |
| 90 | + | |
| 91 | + $survey_questions = $surveys->get_wp_survey_questions(); | |
| 92 | + $questions_json = $surveys->get_specified_survey_questions( $survey_questions, $type ); | |
| 93 | + | |
| 94 | + wp_send_json( $questions_json ); | |
| 95 | + } | |
| 96 | + | |
| 97 | + public function submit_survey(): void { | |
| 98 | + $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( $_POST['nonce'] ) : ''; | |
| 99 | + $survey_type = isset( $_POST['type'] ) ? sanitize_text_field( $_POST['type'] ) : ''; | |
| 100 | + $survey_results = isset( $_POST['survey_results'] ) ? sanitize_text_field( $_POST['survey_results'] ) : ''; | |
| 101 | + $surveys = new Hostinger_Surveys( $this->settings, $this->helper, $this->config_handler, $this->survey_questions, $this->surveys_rest ); | |
| 102 | + | |
| 103 | + $security_check = $this->request_security_check( $nonce ); | |
| 104 | + | |
| 105 | + if ( ! empty( $security_check ) ) { | |
| 106 | + wp_send_json_error( $security_check ); | |
| 107 | + } | |
| 108 | + | |
| 109 | + $decoded_json = json_decode( stripslashes( $survey_results ), true ); | |
| 110 | + $surveys->submit_survey_answers( $decoded_json, $survey_type ); | |
| 111 | + } | |
| 112 | + | |
| 113 | + public function hide_survey(): void { | |
| 114 | + $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( $_POST['nonce'] ) : ''; | |
| 115 | + $transient_key = self::HIDE_SURVEY_TRANSIENT; | |
| 116 | + $security_check = $this->request_security_check( $nonce ); | |
| 117 | + | |
| 118 | + if ( ! empty( $security_check ) ) { | |
| 119 | + wp_send_json_error( $security_check ); | |
| 120 | + } | |
| 121 | + | |
| 122 | + if ( false === get_transient( $transient_key ) ) { | |
| 123 | + set_transient( $transient_key, time(), self::THIRTY_DAYS ); | |
| 124 | + } | |
| 125 | + | |
| 126 | + wp_send_json_success( array() ); | |
| 127 | + } | |
| 128 | + | |
| 129 | + public function hide_promotional_banner(): void { | |
| 130 | + $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( $_POST['nonce'] ) : ''; | |
| 131 | + $transient_key = self::PROMOTIONAL_BANNER_TRANSIENT; | |
| 132 | + $security_check = $this->request_security_check( $nonce ); | |
| 133 | + | |
| 134 | + if ( ! empty( $security_check ) ) { | |
| 135 | + wp_send_json_error( $security_check ); | |
| 136 | + } | |
| 137 | + | |
| 138 | + if ( false === get_transient( $transient_key ) ) { | |
| 139 | + set_transient( $transient_key, time(), self::TWO_DAYS ); | |
| 140 | + } | |
| 141 | + | |
| 142 | + wp_send_json_success( array() ); | |
| 143 | + } | |
| 144 | + | |
| 145 | + public function woocommerce_setup_store(): void { | |
| 146 | + $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( $_POST['nonce'] ) : ''; | |
| 147 | + $event_action = isset( $_POST['event_action'] ) ? sanitize_text_field( $_POST['event_action'] ) : ''; | |
| 148 | + | |
| 149 | + $security_check = $this->request_security_check( $nonce ); | |
| 150 | + | |
| 151 | + if ( ! empty( $security_check ) ) { | |
| 152 | + wp_send_json_error( $security_check ); | |
| 153 | + } | |
| 154 | + | |
| 155 | + $amplitude = new Amplitude(); | |
| 156 | + $amplitude->setup_store( $event_action ); | |
| 157 | + | |
| 158 | + wp_send_json_success( array() ); | |
| 159 | + } | |
| 160 | + | |
| 161 | + public function publish_website(): void { | |
| 162 | + $publish = (bool) $_POST['maintenance']; | |
| 163 | + $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( $_POST['nonce'] ) : ''; | |
| 164 | + $security_check = $this->request_security_check( $nonce ); | |
| 165 | + | |
| 166 | + if ( ! empty( $security_check ) ) { | |
| 167 | + wp_send_json_error( $security_check ); | |
| 168 | + } | |
| 169 | + | |
| 170 | + Settings::update_setting( 'maintenance_mode', $publish ? 1 : 0 ); | |
| 171 | + $content = new Onboarding(); | |
| 172 | + | |
| 173 | + if ( has_action( 'litespeed_purge_all' ) ) { | |
| 174 | + do_action( 'litespeed_purge_all' ); | |
| 175 | + } | |
| 176 | + | |
| 177 | + wp_send_json_success( | |
| 178 | + array( | |
| 179 | + 'published' => $publish, | |
| 180 | + 'title' => __( 'Website is published', 'hostinger' ), | |
| 181 | + 'description' => __( 'Congratulations! Your website is online.', 'hostinger' ), | |
| 182 | + 'content' => $content->get_content(), | |
| 183 | + 'preview_url' => home_url(), | |
| 184 | + ) | |
| 185 | + ); | |
| 186 | + } | |
| 187 | + | |
| 188 | + public function complete_onboarding_step(): void { | |
| 189 | + $step = isset( $_POST['step'] ) ? sanitize_text_field( $_POST['step'] ) : ''; | |
| 190 | + $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( $_POST['nonce'] ) : ''; | |
| 191 | + | |
| 192 | + $security_check = $this->request_security_check( $nonce ); | |
| 193 | + | |
| 194 | + if ( ! empty( $security_check ) ) { | |
| 195 | + wp_send_json_error( $security_check ); | |
| 196 | + } | |
| 197 | + | |
| 198 | + $completed_steps = get_option( 'hostinger_onboarding_steps', array() ); | |
| 199 | + if ( ! in_array( $step, array_column( $completed_steps, 'action' ), true ) ) { | |
| 200 | + $completed_steps[] = array( | |
| 201 | + 'action' => $step, | |
| 202 | + 'date' => gmdate( 'Y-m-d H:i:s' ), | |
| 203 | + ); | |
| 204 | + } | |
| 205 | + Settings::update_setting( 'onboarding_steps', $completed_steps ); | |
| 206 | + | |
| 207 | + wp_send_json_success( array() ); | |
| 208 | + } | |
| 209 | + | |
| 210 | + public function identify_action(): void { | |
| 211 | + $action = sanitize_text_field( $_POST['action_name'] ) ?? ''; | |
| 212 | + | |
| 213 | + if ( in_array( $action, Admin_Actions::ACTIONS_LIST, true ) ) { | |
| 214 | + setcookie( $action, $action, time() + ( 86400 ), '/' ); | |
| 215 | + wp_send_json_success( $action ); | |
| 216 | + } else { | |
| 217 | + wp_send_json_error( 'Invalid action' ); | |
| 218 | + } | |
| 219 | + } | |
| 220 | + | |
| 221 | + public function menu_action(): void { | |
| 222 | + $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( $_POST['nonce'] ) : ''; | |
| 223 | + $location = sanitize_text_field( $_POST['location'] ) ?? ''; | |
| 224 | + $event_action = sanitize_text_field( $_POST['event_action'] ) ?? ''; | |
| 225 | + | |
| 226 | + $security_check = $this->request_security_check( $nonce ); | |
| 227 | + | |
| 228 | + if ( ! empty( $security_check ) ) { | |
| 229 | + wp_send_json_error( $security_check ); | |
| 230 | + } | |
| 231 | + | |
| 232 | + $amplitude = new Amplitude(); | |
| 233 | + $amplitude->track_menu_action( $event_action, $location ); | |
| 234 | + | |
| 235 | + wp_send_json_success( array() ); | |
| 236 | + } | |
| 237 | + | |
| 238 | + public function request_security_check( $nonce ) { | |
| 239 | + if ( ! wp_verify_nonce( $nonce, 'hts-ajax-nonce' ) ) { | |
| 240 | + return 'Invalid nonce'; | |
| 241 | + } | |
| 242 | + | |
| 243 | + if ( ! current_user_can( 'manage_options' ) ) { | |
| 244 | + return 'Lack of permissions'; | |
| 245 | + } | |
| 246 | + | |
| 247 | + return false; | |
| 248 | + } | |
| 249 | + | |
| 250 | + public function woo_onboarding_choice(): void { | |
| 251 | + $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( $_POST['nonce'] ) : ''; | |
| 252 | + $choice = isset( $_POST['choice'] ) ? sanitize_text_field( $_POST['choice'] ) : ''; | |
| 253 | + $security_check = $this->request_security_check( $nonce ); | |
| 254 | + | |
| 255 | + if ( ! empty( $security_check ) ) { | |
| 256 | + wp_send_json_error( $security_check ); | |
| 257 | + } | |
| 258 | + | |
| 259 | + $allowed_choices = array( | |
| 260 | + 'woocommerce', | |
| 261 | + 'hostinger', | |
| 262 | + ); | |
| 263 | + | |
| 264 | + if ( ! in_array( $choice, $allowed_choices, true ) || empty( $choice ) ) { | |
| 265 | + wp_send_json_error( __( 'Something went wrong. Try again.', 'hostinger' ) ); | |
| 266 | + } | |
| 267 | + | |
| 268 | + $base_url = 'https://' . $this->helper->get_host_info() . '/'; | |
| 269 | + | |
| 270 | + $redirect_url = ''; | |
| 271 | + | |
| 272 | + switch ( $choice ) { | |
| 273 | + case 'woocommerce': | |
| 274 | + $redirect_url = $base_url . 'wp-admin/admin.php?page=wc-admin&path=' . rawurlencode( '/setup-wizard' ); | |
| 275 | + | |
| 276 | + add_option( 'hostinger_woo_ready_message_shown', 0 ); | |
| 277 | + | |
| 278 | + break; | |
| 279 | + case 'hostinger': | |
| 280 | + $redirect_url = $base_url . 'wp-admin/admin.php?page=hostinger'; | |
| 281 | + break; | |
| 282 | + } | |
| 283 | + | |
| 284 | + update_option( 'hostinger_woo_onboarding_choice_value', $choice, false ); | |
| 285 | + update_option( 'hostinger_woo_onboarding_choice', true, false ); | |
| 286 | + | |
| 287 | + if ( has_action( 'litespeed_purge_all' ) ) { | |
| 288 | + do_action( 'litespeed_purge_all' ); | |
| 289 | + } | |
| 290 | + | |
| 291 | + $response = array( | |
| 292 | + 'redirect_url' => $redirect_url, | |
| 293 | + ); | |
| 294 | + | |
| 295 | + wp_send_json_success( $response ); | |
| 296 | + } | |
| 297 | + | |
| 298 | + public function dismiss_omnisend_notice(): void { | |
| 299 | + $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( $_POST['nonce'] ) : ''; | |
| 300 | + | |
| 301 | + if ( ! wp_verify_nonce( $nonce, 'hts_close_omnisend' ) ) { | |
| 302 | + wp_send_json_error( 'Invalid nonce' ); | |
| 303 | + } | |
| 304 | + | |
| 305 | + set_transient( self::HIDE_OMNISEND_NOTICE, true, self::SIX_MONTHS ); | |
| 306 | + | |
| 307 | + } | |
| 308 | + | |
| 35 | 309 | } |