PluginProbe
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages / 3.4.3
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages v3.4.3
3.4.3 3.4.2 3.4.1 3.4.0 3.3.9 3.3.8 3.3.7 3.3.6 3.3.5 3.3.4 3.3.3 3.3.2 3.3.1 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.2.7 2.2.8 2.2.9 2.3.0 2.3.1 All 196 releases
convertkit / admin / setup-wizard / class-convertkit-admin-setup-wizard-plugin.php

class-convertkit-admin-setup-wizard-plugin.php in Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages 3.4.3, at admin/setup-wizard/class-convertkit-admin-setup-wizard-plugin.php

433 lines 12.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * ConvertKit Admin Setup Wizard class.
4 *
5 * @package ConvertKit
6 * @author ConvertKit
7 */
8
9 /**
10 * Provides a UI for setting up the ConvertKit Plugin when activated for the
11 * first time.
12 *
13 * If the Plugin has previously been configured (i.e. settings exist in the database),
14 * this UI isn't triggered on activation.
15 *
16 * @package ConvertKit
17 * @author ConvertKit
18 */
19 class ConvertKit_Admin_Setup_Wizard_Plugin extends ConvertKit_Admin_Setup_Wizard {
20
21 /**
22 * Holds the ConvertKit Forms resource class.
23 *
24 * @since 1.9.8.4
25 *
26 * @var bool|ConvertKit_Resource_Forms
27 */
28 public $forms = false;
29
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 /**
40 * Holds the ConvertKit Settings class.
41 *
42 * @since 1.9.8.4
43 *
44 * @var bool|ConvertKit_Settings
45 */
46 public $settings = false;
47
48 /**
49 * Holds the URL to the most recent WordPress Post, used when previewing a Form below a Post
50 * on the frontend site.
51 *
52 * @since 1.9.8.4
53 *
54 * @var bool|string
55 */
56 public $preview_post_url = false;
57
58 /**
59 * Holds the URL to the most recent WordPress Page, used when previewing a Form below a Page
60 * on the frontend site.
61 *
62 * @since 1.9.8.4
63 *
64 * @var bool|string
65 */
66 public $preview_page_url = false;
67
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 /**
78 * The programmatic name for this wizard.
79 *
80 * @since 1.9.8.4
81 *
82 * @var string
83 */
84 public $page_name = 'convertkit-setup';
85
86 /**
87 * The URL to take the user to when they click the Exit link.
88 *
89 * @since 1.9.8.4
90 *
91 * @var string
92 */
93 public $exit_url = 'options-general.php?page=_wp_convertkit_settings';
94
95 /**
96 * Holds the form importers.
97 *
98 * @since 3.1.7
99 *
100 * @var array
101 */
102 public $form_importers = array();
103
104 /**
105 * Registers action and filter hooks.
106 *
107 * @since 1.9.8.4
108 */
109 public function __construct() {
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
142 // Define details for each step in the setup process.
143 $steps = array(
144 'start' => array(
145 'name' => __( 'Connect', 'convertkit' ),
146 'next_button' => array(
147 'label' => __( 'Connect', 'convertkit' ),
148 'link' => $this->api->get_oauth_url( admin_url( 'options.php?page=convertkit-setup&step=configuration' ), get_site_url() ),
149 ),
150 ),
151 'configuration' => array(
152 'name' => __( 'Configuration', 'convertkit' ),
153 'next_button' => array(
154 'label' => $show_form_importer_step ? __( 'Next', 'convertkit' ) : __( 'Finish Setup', 'convertkit' ),
155 ),
156 ),
157 );
158
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 }
168
169 // Add the finish step.
170 $steps['finish'] = array(
171 'name' => __( 'Done', 'convertkit' ),
172 );
173
174 return $steps;
175
176 }
177
178 /**
179 * Add a link to the Setup Wizard below the Plugin Name on the WP_List_Table at Plugins > Installed Plugins.
180 *
181 * @since 2.1.2
182 *
183 * @param array $links HTML Links.
184 * @return array HTML Links
185 */
186 public function add_setup_wizard_link_on_plugins_screen( $links ) {
187
188 return array_merge(
189 $links,
190 array(
191 'setup_wizard' => sprintf(
192 '<a href="%s">%s</a>',
193 add_query_arg(
194 array(
195 'page' => $this->page_name,
196 ),
197 admin_url( 'options.php' )
198 ),
199 __( 'Setup Wizard', 'convertkit' )
200 ),
201 )
202 );
203
204 }
205
206 /**
207 * Redirects to the setup screen if a transient was created on Plugin activation,
208 * and the Plugin has no API Key and Secret configured.
209 *
210 * @since 1.9.8.4
211 */
212 public function maybe_redirect_to_setup_screen() {
213
214 // If no transient was set by the Plugin's activation routine, don't redirect to the setup screen.
215 // This transient will only exist for 30 seconds by design, so we don't hijack a later WordPress
216 // Admin screen request.
217 if ( ! get_transient( $this->page_name ) ) {
218 return;
219 }
220
221 // Delete the transient, so we don't redirect again.
222 delete_transient( $this->page_name );
223
224 // Bail if the user doesn't have access.
225 if ( ! $this->user_has_access() ) {
226 return;
227 }
228
229 // Check if any settings exist.
230 // If they do, the Plugin has already been setup, so no need to show the setup screen.
231 $settings = new ConvertKit_Settings();
232 if ( $settings->has_access_and_refresh_token() ) {
233 return;
234 }
235
236 // Show the setup screen.
237 wp_safe_redirect( admin_url( 'options.php?page=' . $this->page_name ) );
238 exit;
239
240 }
241
242 /**
243 * Process posted data from the submitted form.
244 *
245 * @since 1.9.8.4
246 *
247 * @param int $step Current step.
248 */
249 public function process_form( $step ) {
250
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 }
256
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 }
267
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 }
280
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 ) );
287
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 }
291
292 return;
293 }
294
295 }
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
338 }
339
340 /**
341 * Load any data into class variables for the given setup wizard name and current step.
342 *
343 * @since 1.9.8.4
344 *
345 * @param int $step Current step.
346 */
347 public function load_screen_data( $step ) {
348
349 // If this wizard is being served in a modal window, change the flow.
350 if ( $this->is_modal() ) {
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 }
380 }
381
382 switch ( $step ) {
383 case 'configuration':
384 // Re-load settings class now that the Access and Refresh Tokens have been defined.
385 $this->settings = new ConvertKit_Settings();
386
387 // Fetch Forms.
388 $this->forms = new ConvertKit_Resource_Forms( 'setup_wizard' );
389 $result = $this->forms->refresh();
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
405 // If no Forms exist in ConvertKit, change the next button label and make it a link to reload
406 // the screen.
407 if ( ! $this->forms->exist() ) {
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(
410 array(
411 'page' => $this->page_name,
412 'step' => 'configuration',
413 ),
414 admin_url( 'options.php' )
415 );
416 }
417
418 // Fetch a Post and a Page, appending the preview nonce to their URLs.
419 $this->preview_post_url = WP_ConvertKit()->get_class( 'preview_output' )->get_preview_form_url( 'post' );
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' );
427 break;
428 }
429
430 }
431
432 }
433