← All changes
|
admin/setup-wizard/class-convertkit-admin-setup-wizard-plugin.php
+219
-77
2.3.1
→
3.4.3
View file →
| @@ -27,8 +27,17 @@ | ||
| 27 | 27 | */ |
| 28 | 28 | public $forms = false; |
| 29 | 29 | |
| 30 | 30 | /** |
| 31 | + * Holds the ConvertKit API class. | |
| 32 | + * | |
| 33 | + * @since 2.5.0 | |
| 34 | + * | |
| 35 | + * @var bool|ConvertKit_API_V4 | |
| 36 | + */ | |
| 37 | + public $api = false; | |
| 38 | + | |
| 39 | + /** | |
| 31 | 40 | * Holds the ConvertKit Settings class. |
| 32 | 41 | * |
| 33 | 42 | * @since 1.9.8.4 |
| 34 | 43 | * |
| @@ -56,8 +65,17 @@ | ||
| 56 | 65 | */ |
| 57 | 66 | public $preview_page_url = false; |
| 58 | 67 | |
| 59 | 68 | /** |
| 69 | + * The required user capability to access the setup wizard. | |
| 70 | + * | |
| 71 | + * @since 2.3.2 | |
| 72 | + * | |
| 73 | + * @var string | |
| 74 | + */ | |
| 75 | + public $required_capability = 'manage_options'; | |
| 76 | + | |
| 77 | + /** | |
| 60 | 78 | * The programmatic name for this wizard. |
| 61 | 79 | * |
| 62 | 80 | * @since 1.9.8.4 |
| 63 | 81 | * |
| @@ -74,8 +92,17 @@ | ||
| 74 | 92 | */ |
| 75 | 93 | public $exit_url = 'options-general.php?page=_wp_convertkit_settings'; |
| 76 | 94 | |
| 77 | 95 | /** |
| 96 | + * Holds the form importers. | |
| 97 | + * | |
| 98 | + * @since 3.1.7 | |
| 99 | + * | |
| 100 | + * @var array | |
| 101 | + */ | |
| 102 | + public $form_importers = array(); | |
| 103 | + | |
| 104 | + /** | |
| 78 | 105 | * Registers action and filter hooks. |
| 79 | 106 | * |
| 80 | 107 | * @since 1.9.8.4 |
| 81 | 108 | */ |
| @@ -80,39 +107,72 @@ | ||
| 80 | 107 | * @since 1.9.8.4 |
| 81 | 108 | */ |
| 82 | 109 | public function __construct() { |
| 83 | 110 | |
| 111 | + // Setup API and settings classes. | |
| 112 | + $this->api = new ConvertKit_API_V4( CONVERTKIT_OAUTH_CLIENT_ID, CONVERTKIT_OAUTH_CLIENT_REDIRECT_URI, false, false, false, 'setup_wizard' ); | |
| 113 | + $this->settings = new ConvertKit_Settings(); | |
| 114 | + | |
| 115 | + // Define the steps for the setup wizard. | |
| 116 | + add_filter( 'convertkit_admin_setup_wizard_steps_convertkit-setup', array( $this, 'define_steps' ) ); | |
| 117 | + | |
| 118 | + // Register link to Setup Wizard below Plugin Name at Plugins > Installed Plugins. | |
| 119 | + add_filter( 'convertkit_plugin_screen_action_links', array( $this, 'add_setup_wizard_link_on_plugins_screen' ) ); | |
| 120 | + | |
| 121 | + add_action( 'admin_init', array( $this, 'maybe_redirect_to_setup_screen' ), 9999 ); | |
| 122 | + add_action( 'convertkit_admin_setup_wizard_process_form_convertkit-setup', array( $this, 'process_form' ) ); | |
| 123 | + add_action( 'convertkit_admin_setup_wizard_load_screen_data_convertkit-setup', array( $this, 'load_screen_data' ) ); | |
| 124 | + | |
| 125 | + // Call parent class constructor. | |
| 126 | + parent::__construct(); | |
| 127 | + | |
| 128 | + } | |
| 129 | + | |
| 130 | + /** | |
| 131 | + * Define the steps for the setup wizard. | |
| 132 | + * | |
| 133 | + * @since 3.1.8 | |
| 134 | + * | |
| 135 | + * @param array $steps The steps for the setup wizard. | |
| 136 | + * @return array | |
| 137 | + */ | |
| 138 | + public function define_steps( $steps ) { | |
| 139 | + | |
| 140 | + $show_form_importer_step = count( convertkit_get_form_importers() ) > 0 ? true : false; | |
| 141 | + | |
| 84 | 142 | // Define details for each step in the setup process. |
| 85 | - $this->steps = array( | |
| 86 | - 1 => array( | |
| 87 | - 'name' => __( 'Setup', 'convertkit' ), | |
| 88 | - ), | |
| 89 | - 2 => array( | |
| 90 | - 'name' => __( 'Connect Account', 'convertkit' ), | |
| 143 | + $steps = array( | |
| 144 | + 'start' => array( | |
| 145 | + 'name' => __( 'Connect', 'convertkit' ), | |
| 91 | 146 | 'next_button' => array( |
| 92 | 147 | 'label' => __( 'Connect', 'convertkit' ), |
| 148 | + 'link' => $this->api->get_oauth_url( admin_url( 'options.php?page=convertkit-setup&step=configuration' ), get_site_url() ), | |
| 93 | 149 | ), |
| 94 | 150 | ), |
| 95 | - 3 => array( | |
| 96 | - 'name' => __( 'Form Configuration', 'convertkit' ), | |
| 151 | + 'configuration' => array( | |
| 152 | + 'name' => __( 'Configuration', 'convertkit' ), | |
| 97 | 153 | 'next_button' => array( |
| 98 | - 'label' => __( 'Finish Setup', 'convertkit' ), | |
| 154 | + 'label' => $show_form_importer_step ? __( 'Next', 'convertkit' ) : __( 'Finish Setup', 'convertkit' ), | |
| 99 | 155 | ), |
| 100 | 156 | ), |
| 101 | - 4 => array( | |
| 102 | - 'name' => __( 'Done', 'convertkit' ), | |
| 103 | - ), | |
| 104 | 157 | ); |
| 105 | 158 | |
| 106 | - // Register link to Setup Wizard below Plugin Name at Plugins > Installed Plugins. | |
| 107 | - add_filter( 'convertkit_plugin_screen_action_links', array( $this, 'add_setup_wizard_link_on_plugins_screen' ) ); | |
| 159 | + // If the Form Importer step will be displayed, add it to the steps. | |
| 160 | + if ( $show_form_importer_step ) { | |
| 161 | + $steps['form-importer'] = array( | |
| 162 | + 'name' => __( 'Form Importer', 'convertkit' ), | |
| 163 | + 'next_button' => array( | |
| 164 | + 'label' => __( 'Finish Setup', 'convertkit' ), | |
| 165 | + ), | |
| 166 | + ); | |
| 167 | + } | |
| 108 | 168 | |
| 109 | - add_action( 'admin_init', array( $this, 'maybe_redirect_to_setup_screen' ), 9999 ); | |
| 110 | - add_action( 'convertkit_admin_setup_wizard_process_form_convertkit-setup', array( $this, 'process_form' ) ); | |
| 111 | - add_action( 'convertkit_admin_setup_wizard_load_screen_data_convertkit-setup', array( $this, 'load_screen_data' ) ); | |
| 169 | + // Add the finish step. | |
| 170 | + $steps['finish'] = array( | |
| 171 | + 'name' => __( 'Done', 'convertkit' ), | |
| 172 | + ); | |
| 112 | 173 | |
| 113 | - // Call parent class constructor. | |
| 114 | - parent::__construct(); | |
| 174 | + return $steps; | |
| 115 | 175 | |
| 116 | 176 | } |
| 117 | 177 | |
| 118 | 178 | /** |
| @@ -133,9 +193,9 @@ | ||
| 133 | 193 | add_query_arg( |
| 134 | 194 | array( |
| 135 | 195 | 'page' => $this->page_name, |
| 136 | 196 | ), |
| 137 | - admin_url( 'index.php' ) | |
| 197 | + admin_url( 'options.php' ) | |
| 138 | 198 | ), |
| 139 | 199 | __( 'Setup Wizard', 'convertkit' ) |
| 140 | 200 | ), |
| 141 | 201 | ) |
| @@ -168,14 +228,14 @@ | ||
| 168 | 228 | |
| 169 | 229 | // Check if any settings exist. |
| 170 | 230 | // If they do, the Plugin has already been setup, so no need to show the setup screen. |
| 171 | 231 | $settings = new ConvertKit_Settings(); |
| 172 | - if ( $settings->has_api_key_and_secret() ) { | |
| 232 | + if ( $settings->has_access_and_refresh_token() ) { | |
| 173 | 233 | return; |
| 174 | 234 | } |
| 175 | 235 | |
| 176 | 236 | // Show the setup screen. |
| 177 | - wp_safe_redirect( admin_url( 'index.php?page=' . $this->page_name ) ); | |
| 237 | + wp_safe_redirect( admin_url( 'options.php?page=' . $this->page_name ) ); | |
| 178 | 238 | exit; |
| 179 | 239 | |
| 180 | 240 | } |
| 181 | 241 | |
| @@ -187,54 +247,95 @@ | ||
| 187 | 247 | * @param int $step Current step. |
| 188 | 248 | */ |
| 189 | 249 | public function process_form( $step ) { |
| 190 | 250 | |
| 191 | - // phpcs:disable WordPress.Security.NonceVerification.Missing | |
| 192 | - // Nonce verification has been performed in ConvertKit_Admin_Setup_Wizard:process_form(), prior to calling this function. | |
| 251 | + // Depending on the step, process the form data. | |
| 252 | + if ( array_key_exists( 'code', $_REQUEST ) || array_key_exists( 'error', $_REQUEST ) || array_key_exists( 'error_description', $_REQUEST ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended - no nonce is sent back from OAuth. | |
| 253 | + $this->save_oauth( map_deep( wp_unslash( $_REQUEST ), 'sanitize_text_field' ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended - no nonce is sent back from OAuth. | |
| 254 | + return; | |
| 255 | + } | |
| 193 | 256 | |
| 194 | - // Depending on the step, process the form data. | |
| 195 | - switch ( $step ) { | |
| 196 | - case 3: | |
| 197 | - // Check that the API Key and Secret work. | |
| 198 | - $api_key = sanitize_text_field( wp_unslash( $_POST['api_key'] ) ); | |
| 199 | - $api_secret = sanitize_text_field( wp_unslash( $_POST['api_secret'] ) ); | |
| 257 | + // Run security checks. | |
| 258 | + if ( ! isset( $_REQUEST['_wpnonce'] ) ) { | |
| 259 | + return; | |
| 260 | + } | |
| 261 | + if ( ! wp_verify_nonce( sanitize_key( $_REQUEST['_wpnonce'] ), $this->page_name ) ) { | |
| 262 | + // Decrement the step. | |
| 263 | + $this->step = 'configuration'; | |
| 264 | + $this->error = __( 'Invalid nonce specified.', 'convertkit' ); | |
| 265 | + return; | |
| 266 | + } | |
| 200 | 267 | |
| 201 | - $api = new ConvertKit_API( $api_key, $api_secret, false, 'setup_wizard' ); | |
| 202 | - $result = $api->account(); | |
| 268 | + // Configuration. | |
| 269 | + if ( array_key_exists( 'post_form', $_REQUEST ) || array_key_exists( 'page_form', $_REQUEST ) || array_key_exists( 'usage_tracking', $_REQUEST ) ) { | |
| 270 | + $settings = new ConvertKit_Settings(); | |
| 271 | + $settings->save( | |
| 272 | + array( | |
| 273 | + 'post_form' => isset( $_REQUEST['post_form'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['post_form'] ) ) : '0', | |
| 274 | + 'page_form' => isset( $_REQUEST['page_form'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['page_form'] ) ) : '0', | |
| 275 | + 'usage_tracking' => isset( $_REQUEST['usage_tracking'] ) ? 'on' : '', | |
| 276 | + ) | |
| 277 | + ); | |
| 278 | + return; | |
| 279 | + } | |
| 203 | 280 | |
| 204 | - // Show an error message if Account Details could not be fetched e.g. API credentials supplied are invalid. | |
| 205 | - if ( is_wp_error( $result ) ) { | |
| 206 | - // Decrement the step. | |
| 207 | - $this->step = ( $this->step - 1 ); | |
| 208 | - $this->error = $result->get_error_message(); | |
| 209 | - return; | |
| 210 | - } | |
| 281 | + // Form Importer. | |
| 282 | + if ( array_key_exists( 'form_importer', $_REQUEST ) ) { | |
| 283 | + // Replace third party form shortcodes and blocks with Kit form shortcodes and blocks. | |
| 284 | + foreach ( map_deep( wp_unslash( $_REQUEST['form_importer'] ), 'sanitize_text_field' ) as $form_importer_name => $mappings ) { | |
| 285 | + // Sanitize mappings. | |
| 286 | + $mappings = array_map( 'sanitize_text_field', wp_unslash( $mappings ) ); | |
| 211 | 287 | |
| 212 | - // If here, API credentials are valid. | |
| 213 | - // Save them. | |
| 214 | - $settings = new ConvertKit_Settings(); | |
| 215 | - $settings->save( | |
| 216 | - array( | |
| 217 | - 'api_key' => $api_key, | |
| 218 | - 'api_secret' => $api_secret, | |
| 219 | - ) | |
| 220 | - ); | |
| 221 | - break; | |
| 288 | + // Replace third party form shortcodes and blocks with Kit form shortcodes and blocks. | |
| 289 | + WP_ConvertKit()->get_class( 'admin_importer_' . $form_importer_name )->import( $mappings ); | |
| 290 | + } | |
| 222 | 291 | |
| 223 | - case 4: | |
| 224 | - // Save Default Page and Post Form settings. | |
| 225 | - $settings = new ConvertKit_Settings(); | |
| 226 | - $settings->save( | |
| 227 | - array( | |
| 228 | - 'post_form' => sanitize_text_field( $_POST['post_form'] ), | |
| 229 | - 'page_form' => sanitize_text_field( $_POST['page_form'] ), | |
| 230 | - ) | |
| 231 | - ); | |
| 232 | - break; | |
| 292 | + return; | |
| 233 | 293 | } |
| 234 | 294 | |
| 235 | - // phpcs:enable | |
| 295 | + } | |
| 236 | 296 | |
| 297 | + /** | |
| 298 | + * Save the OAuth credentials. | |
| 299 | + * | |
| 300 | + * @since 3.1.7 | |
| 301 | + * | |
| 302 | + * @param array $request Request. | |
| 303 | + * @return void | |
| 304 | + */ | |
| 305 | + private function save_oauth( $request ) { | |
| 306 | + | |
| 307 | + // If an error occured from OAuth i.e. the user did not authorize, show it now. | |
| 308 | + if ( array_key_exists( 'error', $request ) || array_key_exists( 'error_description', $request ) ) { | |
| 309 | + // Decrement the step. | |
| 310 | + $this->step = 'start'; | |
| 311 | + $this->error = sanitize_text_field( wp_unslash( $request['error_description'] ) ); | |
| 312 | + return; | |
| 313 | + } | |
| 314 | + | |
| 315 | + // Sanitize token. | |
| 316 | + $authorization_code = sanitize_text_field( wp_unslash( $request['code'] ) ); | |
| 317 | + | |
| 318 | + // Exchange the authorization code and verifier for an access token. | |
| 319 | + $result = $this->api->get_access_token( $authorization_code ); | |
| 320 | + | |
| 321 | + // Show an error message if we could not fetch the access token. | |
| 322 | + if ( is_wp_error( $result ) ) { | |
| 323 | + // Decrement the step. | |
| 324 | + $this->step = 'start'; | |
| 325 | + $this->error = $result->get_error_message(); | |
| 326 | + return; | |
| 327 | + } | |
| 328 | + | |
| 329 | + // Store Access Token, Refresh Token and expiry. | |
| 330 | + $this->settings->save( | |
| 331 | + array( | |
| 332 | + 'access_token' => $result['access_token'], | |
| 333 | + 'refresh_token' => $result['refresh_token'], | |
| 334 | + 'token_expires' => ( time() + $result['expires_in'] ), | |
| 335 | + ) | |
| 336 | + ); | |
| 337 | + | |
| 237 | 338 | } |
| 238 | 339 | |
| 239 | 340 | /** |
| 240 | 341 | * Load any data into class variables for the given setup wizard name and current step. |
| @@ -244,39 +345,74 @@ | ||
| 244 | 345 | * @param int $step Current step. |
| 245 | 346 | */ |
| 246 | 347 | public function load_screen_data( $step ) { |
| 247 | 348 | |
| 248 | - // If this wizard is being served in a modal window, adjust the steps. | |
| 349 | + // If this wizard is being served in a modal window, change the flow. | |
| 249 | 350 | if ( $this->is_modal() ) { |
| 250 | - unset( $this->steps[3], $this->steps[4] ); | |
| 351 | + switch ( $step ) { | |
| 352 | + case 'start': | |
| 353 | + // Setup API. | |
| 354 | + $api = new ConvertKit_API_V4( CONVERTKIT_OAUTH_CLIENT_ID, CONVERTKIT_OAUTH_CLIENT_REDIRECT_URI ); | |
| 355 | + | |
| 356 | + // Permit wp_safe_redirect to redirect to app.kit.com. | |
| 357 | + add_filter( | |
| 358 | + 'allowed_redirect_hosts', | |
| 359 | + function ( $hosts ) { | |
| 360 | + | |
| 361 | + return array_merge( | |
| 362 | + $hosts, | |
| 363 | + array( | |
| 364 | + 'app.kit.com', | |
| 365 | + ) | |
| 366 | + ); | |
| 367 | + | |
| 368 | + } | |
| 369 | + ); | |
| 370 | + | |
| 371 | + // Redirect to OAuth. | |
| 372 | + wp_safe_redirect( $api->get_oauth_url( admin_url( 'options.php?page=convertkit-setup&step=configuration&convertkit-modal=1' ), get_site_url() ) ); | |
| 373 | + die(); | |
| 374 | + | |
| 375 | + case 'configuration': | |
| 376 | + // Close modal. | |
| 377 | + $this->maybe_close_modal(); | |
| 378 | + break; | |
| 379 | + } | |
| 251 | 380 | } |
| 381 | + | |
| 252 | 382 | switch ( $step ) { |
| 253 | - case 2: | |
| 254 | - // Load settings class. | |
| 383 | + case 'configuration': | |
| 384 | + // Re-load settings class now that the Access and Refresh Tokens have been defined. | |
| 255 | 385 | $this->settings = new ConvertKit_Settings(); |
| 256 | - break; | |
| 257 | 386 | |
| 258 | - case 3: | |
| 259 | - // If this wizard is being served in a modal window, we can exit after obtaining valid API credentials. | |
| 260 | - $this->maybe_close_modal(); | |
| 261 | - | |
| 262 | - // Re-load settings class now that the API Key and Secret has been defined. | |
| 263 | - $this->settings = new ConvertKit_Settings(); | |
| 264 | - | |
| 265 | 387 | // Fetch Forms. |
| 266 | 388 | $this->forms = new ConvertKit_Resource_Forms( 'setup_wizard' ); |
| 267 | - $this->forms->refresh(); | |
| 389 | + $result = $this->forms->refresh(); | |
| 268 | 390 | |
| 391 | + // Bail if an error occured. | |
| 392 | + if ( is_wp_error( $result ) ) { | |
| 393 | + // Change the next button label and make it a link to reload the screen. | |
| 394 | + $this->steps['configuration']['next_button']['label'] = __( 'I\'ve created a form in Kit', 'convertkit' ); | |
| 395 | + $this->steps['configuration']['next_button']['link'] = add_query_arg( | |
| 396 | + array( | |
| 397 | + 'page' => $this->page_name, | |
| 398 | + 'step' => 'configuration', | |
| 399 | + ), | |
| 400 | + admin_url( 'options.php' ) | |
| 401 | + ); | |
| 402 | + return; | |
| 403 | + } | |
| 404 | + | |
| 269 | 405 | // If no Forms exist in ConvertKit, change the next button label and make it a link to reload |
| 270 | 406 | // the screen. |
| 271 | 407 | if ( ! $this->forms->exist() ) { |
| 272 | - $this->steps[3]['next_button']['label'] = __( 'I\'ve created a form in ConvertKit', 'convertkit' ); | |
| 273 | - $this->steps[3]['next_button']['link'] = add_query_arg( | |
| 408 | + $this->steps['configuration']['next_button']['label'] = __( 'I\'ve created a form in Kit', 'convertkit' ); | |
| 409 | + $this->steps['configuration']['next_button']['link'] = add_query_arg( | |
| 274 | 410 | array( |
| 275 | 411 | 'page' => $this->page_name, |
| 276 | - 'step' => 3, | |
| 412 | + 'step' => 'configuration', | |
| 277 | 413 | ), |
| 278 | - admin_url( 'index.php' ) | |
| 414 | + admin_url( 'options.php' ) | |
| 279 | 415 | ); |
| 280 | 416 | } |
| 281 | 417 | |
| 282 | 418 | // Fetch a Post and a Page, appending the preview nonce to their URLs. |
| @@ -281,8 +417,14 @@ | ||
| 281 | 417 | |
| 282 | 418 | // Fetch a Post and a Page, appending the preview nonce to their URLs. |
| 283 | 419 | $this->preview_post_url = WP_ConvertKit()->get_class( 'preview_output' )->get_preview_form_url( 'post' ); |
| 284 | 420 | $this->preview_page_url = WP_ConvertKit()->get_class( 'preview_output' )->get_preview_form_url( 'page' ); |
| 421 | + break; | |
| 422 | + | |
| 423 | + case 'form-importer': | |
| 424 | + // Fetch form importers and Kit Forms. | |
| 425 | + $this->form_importers = convertkit_get_form_importers(); | |
| 426 | + $this->forms = new ConvertKit_Resource_Forms( 'setup_wizard' ); | |
| 285 | 427 | break; |
| 286 | 428 | } |
| 287 | 429 | |
| 288 | 430 | } |