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-restrict-content.php

class-convertkit-admin-setup-wizard-restrict-content.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-restrict-content.php

683 lines 18.6 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 for Restrict Content class.
4 *
5 * @package ConvertKit
6 * @author ConvertKit
7 */
8
9 /**
10 * Provides a UI for setting up Member's Only Content.
11 *
12 * @package ConvertKit
13 * @author ConvertKit
14 */
15 class ConvertKit_Admin_Setup_Wizard_Restrict_Content extends ConvertKit_Admin_Setup_Wizard {
16
17 /**
18 * Holds the type of Member's Content to generate (course|download).
19 *
20 * @since 2.1.0
21 *
22 * @var string
23 */
24 public $type = 'download';
25
26 /**
27 * Holds the label for the type of Member's Content to generate.
28 *
29 * @since 2.1.0
30 *
31 * @var string
32 */
33 public $type_label = '';
34
35 /**
36 * Holds the ConvertKit Forms resource class.
37 *
38 * @since 2.8.3
39 *
40 * @var bool|ConvertKit_Resource_Forms
41 */
42 public $forms = false;
43
44 /**
45 * Holds the ConvertKit Products resource class.
46 *
47 * @since 2.1.0
48 *
49 * @var bool|ConvertKit_Resource_Products
50 */
51 public $products = false;
52
53 /**
54 * Holds the ConvertKit Tags resource class.
55 *
56 * @since 2.3.3
57 *
58 * @var bool|ConvertKit_Resource_Tags
59 */
60 public $tags = false;
61
62 /**
63 * Holds the Pages created by this setup wizard.
64 *
65 * @since 2.1.0
66 *
67 * @var bool|array
68 */
69 public $pages = false;
70
71 /**
72 * Holds the URL to the setup wizard screen for the Download type of content.
73 *
74 * @since 2.1.0
75 *
76 * @var bool|string
77 */
78 public $download_url = false;
79
80 /**
81 * Holds the URL to the setup wizard screen for the Course type of content.
82 *
83 * @since 2.1.0
84 *
85 * @var bool|string
86 */
87 public $course_url = false;
88
89 /**
90 * Holds the URL to the current setup wizard screen.
91 *
92 * @since 2.3.3
93 *
94 * @var bool|string
95 */
96 public $current_url = false;
97
98 /**
99 * The required user capability to access the setup wizard.
100 *
101 * @since 2.1.0
102 *
103 * @var string
104 */
105 public $required_capability = 'edit_posts';
106
107 /**
108 * The programmatic name for this wizard.
109 *
110 * @since 2.1.0
111 *
112 * @var string
113 */
114 public $page_name = 'convertkit-restrict-content-setup';
115
116 /**
117 * The URL to take the user to when they click the Exit link.
118 *
119 * @since 2.1.0
120 *
121 * @var string
122 */
123 public $exit_url = 'edit.php?post_type=page';
124
125 /**
126 * Registers action and filter hooks.
127 *
128 * @since 2.1.0
129 */
130 public function __construct() {
131
132 // Define the steps for the setup wizard.
133 add_filter( 'convertkit_admin_setup_wizard_steps_convertkit-restrict-content-setup', array( $this, 'define_steps' ) );
134
135 add_action( 'convertkit_admin_setup_wizard_process_form_convertkit-restrict-content-setup', array( $this, 'process_form' ) );
136 add_action( 'convertkit_admin_setup_wizard_load_screen_data_convertkit-restrict-content-setup', array( $this, 'load_screen_data' ) );
137
138 // Call parent class constructor.
139 parent::__construct();
140
141 }
142
143 /**
144 * Define the steps for the setup wizard.
145 *
146 * @since 3.1.8
147 *
148 * @param array $steps The steps for the setup wizard.
149 * @return array
150 */
151 public function define_steps( $steps ) {
152
153 return array(
154 'start' => array(
155 'name' => __( 'Setup', 'convertkit' ),
156 ),
157 'configuration' => array(
158 'name' => __( 'Configure', 'convertkit' ),
159 'next_button' => array(
160 'label' => __( 'Submit', 'convertkit' ),
161 ),
162 ),
163 'finish' => array(
164 'name' => __( 'Done', 'convertkit' ),
165 ),
166 );
167
168 }
169
170 /**
171 * Process posted data from the submitted form.
172 *
173 * @since 2.1.0
174 *
175 * @param string $step Current step.
176 */
177 public function process_form( $step ) {
178
179 // Set and authorize the Post Type before processing data.
180 $this->set_post_type();
181 if ( ! convertkit_user_can_create_published_post_type( $this->post_type ) ) {
182 $this->error = __( 'You are not allowed to create and publish this type of content.', 'convertkit' );
183 return;
184 }
185
186 // Run security checks.
187 if ( ! isset( $_REQUEST['_wpnonce'] ) ) {
188 return;
189 }
190 if ( ! wp_verify_nonce( sanitize_key( $_REQUEST['_wpnonce'] ), $this->page_name ) ) {
191 $this->error = __( 'Invalid nonce specified.', 'convertkit' );
192 return;
193 }
194
195 // Depending on the step, process the form data.
196 switch ( $step ) {
197 case 'finish':
198 // Sanitize configuration.
199 $configuration = array(
200 'type' => ( isset( $_POST['type'] ) ? sanitize_text_field( wp_unslash( $_POST['type'] ) ) : 'download' ),
201 'title' => ( isset( $_POST['title'] ) ? sanitize_text_field( wp_unslash( $_POST['title'] ) ) : '' ),
202 'description' => ( isset( $_POST['description'] ) ? sanitize_textarea_field( wp_unslash( $_POST['description'] ) ) : '' ),
203 'number_of_pages' => ( isset( $_POST['number_of_pages'] ) ? absint( $_POST['number_of_pages'] ) : 0 ),
204 'restrict_content' => ( isset( $_POST['restrict_content'] ) ? sanitize_text_field( wp_unslash( $_POST['restrict_content'] ) ) : '' ),
205 'post_type' => $this->post_type,
206 );
207
208 // Depending on the type of content selected, create WordPress Page(s) now.
209 switch ( $configuration['type'] ) {
210 /**
211 * Download
212 * - Single page with a link to a downloadable product.
213 */
214 case 'download':
215 $result = $this->create_download( $configuration );
216 break;
217
218 /**
219 * Course
220 */
221 case 'course':
222 default:
223 $result = $this->create_course( $configuration );
224 break;
225 }
226
227 // If here, an error occured as create_download() and create_course() perform a redirect on success.
228 // Show an error message if Account Details could not be fetched e.g. API credentials supplied are invalid.
229 // Decrement the step.
230 $this->step = $this->get_step_key_by_number( $this->get_current_step_number() - 1 );
231 $this->error = $result->get_error_message();
232 return;
233
234 }
235
236 // phpcs:enable
237
238 }
239
240 /**
241 * Load any data into class variables for the given setup wizard name and current step.
242 *
243 * @since 2.1.0
244 *
245 * @param string $step Current step.
246 */
247 public function load_screen_data( $step ) {
248
249 // Show an error screen if API credentials have not been specified.
250 // This shouldn't happen, because the 'Add New Member Content' button is only displayed
251 // if valid credentials have been specified.
252 $settings = new ConvertKit_Settings();
253 if ( ! $settings->has_access_and_refresh_token() ) {
254 wp_die( esc_html__( 'Connect your ConvertKit account in the ConvertKit Plugin\'s settings to get started', 'convertkit' ) );
255 }
256
257 // Set and authorize the Post Type.
258 $this->set_post_type();
259 if ( ! convertkit_user_can_create_published_post_type( $this->post_type ) ) {
260 wp_die( esc_html__( 'Sorry, you are not allowed to create and publish this type of content.', 'convertkit' ) );
261 }
262
263 // Define Exit URL to take the user back to the WP_List_Table for the Post Type they were viewing.
264 $this->exit_url = add_query_arg(
265 array(
266 'post_type' => $this->post_type,
267 ),
268 admin_url( 'edit.php' )
269 );
270
271 // Load data depending on the current step.
272 switch ( $step ) {
273 case 'start':
274 // Fetch Forms, Products and Tags.
275 $this->forms = new ConvertKit_Resource_Forms( 'restrict_content_wizard' );
276 $this->products = new ConvertKit_Resource_Products( 'restrict_content_wizard' );
277 $this->tags = new ConvertKit_Resource_Tags( 'restrict_content_wizard' );
278
279 // Refresh Forms, Products and Tags resources, in case the user just created their first Form, Product or Tag
280 // in ConvertKit.
281 $result = $this->forms->refresh();
282
283 // Bail if an error occured.
284 if ( is_wp_error( $result ) ) {
285 // Change the next label and make it a link to reload the screen.
286 unset( $this->steps['start']['next_button'] );
287 $this->current_url = add_query_arg(
288 array(
289 'page' => $this->page_name,
290 'ck_post_type' => $this->post_type,
291 'step' => 'start',
292 ),
293 admin_url( 'options.php' )
294 );
295 return;
296 }
297
298 // Refresh Products.
299 $result = $this->products->refresh();
300
301 // Bail if an error occured.
302 if ( is_wp_error( $result ) ) {
303 // Change the next label and make it a link to reload the screen.
304 unset( $this->steps['start']['next_button'] );
305 $this->current_url = add_query_arg(
306 array(
307 'page' => $this->page_name,
308 'ck_post_type' => $this->post_type,
309 'step' => 'start',
310 ),
311 admin_url( 'options.php' )
312 );
313 return;
314 }
315
316 // Refresh Tags.
317 $result = $this->tags->refresh();
318
319 // Bail if an error occured.
320 if ( is_wp_error( $result ) ) {
321 // Change the next label and make it a link to reload the screen.
322 unset( $this->steps['start']['next_button'] );
323 $this->current_url = add_query_arg(
324 array(
325 'page' => $this->page_name,
326 'ck_post_type' => $this->post_type,
327 'step' => 'start',
328 ),
329 admin_url( 'options.php' )
330 );
331 return;
332 }
333
334 // If no Forms, Products and Tags exist in ConvertKit, change the next button label and make it a link to reload
335 // the screen.
336 if ( ! $this->forms->exist() && ! $this->products->exist() && ! $this->tags->exist() ) {
337 unset( $this->steps['start']['next_button'] );
338 $this->current_url = add_query_arg(
339 array(
340 'page' => $this->page_name,
341 'ck_post_type' => $this->post_type,
342 'step' => 'start',
343 ),
344 admin_url( 'options.php' )
345 );
346 } else {
347 // Define Download and Course button links.
348 $this->download_url = add_query_arg(
349 array(
350 'type' => 'download',
351 'ck_post_type' => $this->post_type,
352 ),
353 $this->next_step_url
354 );
355
356 $this->course_url = add_query_arg(
357 array(
358 'type' => 'course',
359 'ck_post_type' => $this->post_type,
360 ),
361 $this->next_step_url
362 );
363 }
364 break;
365
366 case 'configuration':
367 // Define Member Content Type.
368 if ( filter_has_var( INPUT_GET, 'type' ) ) {
369 $this->type = filter_input( INPUT_GET, 'type', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
370 } else {
371 $this->type = 'download';
372 }
373
374 // Define Label for Title.
375 switch ( $this->type ) {
376 case 'download':
377 $this->type_label = __( 'Download', 'convertkit' );
378 break;
379 case 'course':
380 $this->type_label = __( 'Course', 'convertkit' );
381 break;
382 }
383
384 // Fetch Forms, Products and Tags.
385 $this->forms = new ConvertKit_Resource_Forms( 'restrict_content_wizard' );
386 $this->products = new ConvertKit_Resource_Products( 'restrict_content_wizard' );
387 $this->tags = new ConvertKit_Resource_Tags( 'restrict_content_wizard' );
388 break;
389 }
390
391 }
392
393 /**
394 * Creates a single WordPress Page for a downloadable product, restricted by
395 * a ConvertKit Form, Tag or Product, based on the supplied configuration.
396 *
397 * @since 2.1.0
398 *
399 * @param array $configuration Configuration.
400 * @return WP_Error WP_Error or Page ID
401 */
402 private function create_download( $configuration ) {
403
404 // Create Page.
405 $page_id = $this->create_page(
406 $configuration['title'],
407 $configuration['description'],
408 $configuration['post_type'],
409 __( 'The downloadable member-only content goes here.', 'convertkit' ),
410 $configuration['restrict_content']
411 );
412
413 // Bail if an error occured.
414 if ( is_wp_error( $page_id ) ) {
415 return $page_id;
416 }
417
418 // Redirect to the Pages WP_List_Table screen, showing the generated page.
419 wp_safe_redirect(
420 add_query_arg(
421 array(
422 's' => rawurlencode( $configuration['title'] ),
423 'post_type' => $configuration['post_type'],
424 ),
425 'edit.php'
426 )
427 );
428 die();
429
430 }
431
432 /**
433 * Creates multiple WordPress Pages for a course, restricted by
434 * a ConvertKit Form, Tag or Product, based on the supplied configuration.
435 *
436 * @since 2.1.0
437 *
438 * @param array $configuration Configuration.
439 * @return WP_Error WP_Error on error, wp_safe_redirect() on success.
440 */
441 private function create_course( $configuration ) {
442
443 // If here, we need to generate multiple pages.
444 // Build top level Page, which pages will be children of.
445 $parent_page_id = $this->create_page(
446 $configuration['title'],
447 $configuration['description'],
448 $configuration['post_type']
449 );
450
451 // Bail if an error occured.
452 if ( is_wp_error( $parent_page_id ) ) {
453 return $parent_page_id;
454 }
455
456 // Build child Pages.
457 $page_ids = array();
458 for ( $i = 1; $i <= $configuration['number_of_pages']; $i++ ) {
459 $result = $this->create_page(
460 sprintf(
461 '%s: %s/%s',
462 $configuration['title'],
463 $i,
464 $configuration['number_of_pages']
465 ), // e.g. Title: 1/10.
466 sprintf(
467 '%s %s',
468 esc_html__( 'Some introductory text about lesson', 'convertkit' ),
469 $i
470 ),
471 $configuration['post_type'],
472 sprintf(
473 '%s %s %s',
474 esc_html__( 'Lesson', 'convertkit' ),
475 $i,
476 esc_html__( 'member-only content goes here.', 'convertkit' )
477 ),
478 $configuration['restrict_content'],
479 $i,
480 $configuration['number_of_pages'],
481 $parent_page_id
482 );
483
484 // Bail if an error occured.
485 if ( is_wp_error( $result ) ) {
486 return $result;
487 }
488
489 // Add Page ID to array.
490 $page_ids[] = $result;
491 }
492
493 // Add a link from the parent page to the first child page.
494 $this->add_link_from_parent_to_child_page( $parent_page_id, $page_ids[0] );
495
496 // Redirect to the Pages WP_List_Table screen, showing the generated pages.
497 wp_safe_redirect(
498 add_query_arg(
499 array(
500 's' => rawurlencode( $configuration['title'] ),
501 'post_type' => $configuration['post_type'],
502 ),
503 'edit.php'
504 )
505 );
506 die();
507
508 }
509
510 /**
511 * Creates a WordPress Page for the given title, restricted to the given restrict content setting.
512 *
513 * @since 2.1.0
514 *
515 * @param string $title Page Title.
516 * @param string $content Non-restricted Content.
517 * @param string $post_type Post Type.
518 * @param bool|string $restricted_content Restricted Content.
519 * @param bool|string $restrict_content_setting ConvertKit Form, Tag or Product to restrict content to.
520 * @param int $page_number Page Number.
521 * @param int $total_pages Total Pages that will be created.
522 * @param bool|int $parent_page_id Parent Page ID (false if none).
523 * @return WP_Error|int Error or Page ID
524 */
525 private function create_page( $title, $content, $post_type = 'page', $restricted_content = false, $restrict_content_setting = false, $page_number = 0, $total_pages = 0, $parent_page_id = false ) {
526
527 // Build content.
528 $content = $this->element_paragraph( $content );
529
530 // If restricted content is defined, append it to the post content using a more block.
531 if ( $restricted_content && $restrict_content_setting ) {
532 $content .= $this->element_more_tag();
533 $content .= $this->element_paragraph( $restricted_content );
534 }
535
536 // Define previous / next links, depending on the page number and total pages.
537 $content .= $this->element_navigation( $page_number, $total_pages );
538
539 // Build arguments to create Page.
540 $args = array(
541 'post_type' => $post_type,
542 'post_status' => 'publish',
543 'post_author' => get_current_user_id(),
544 'post_title' => $title,
545 'post_content' => $content,
546 'menu_order' => $page_number,
547 );
548
549 // If a parent page is specified, apply it to the arguments.
550 if ( $parent_page_id !== false ) {
551 $args['post_parent'] = $parent_page_id;
552 }
553
554 // Create Page.
555 $page_id = wp_insert_post( $args, true );
556
557 // Bail if an error occured.
558 if ( is_wp_error( $page_id ) ) {
559 return $page_id;
560 }
561
562 // Define Page's settings, ensuring no default Form displays.
563 // If a restrict content setting was supplied, it's set to the Page now.
564 WP_ConvertKit()->get_class( 'admin_post' )->save_post_settings(
565 $page_id,
566 array(
567 'form' => '0', // Don't display a Form.
568 'restrict_content' => ( $restrict_content_setting !== false ? $restrict_content_setting : '0' ),
569 )
570 );
571
572 // Return.
573 return $page_id;
574
575 }
576
577 /**
578 * Returns a paragraph for the given text, depending on if the Classic Editor or Block Editor is used.
579 *
580 * @since 2.1.0
581 *
582 * @param string $text Text.
583 * @return string Text
584 */
585 private function element_paragraph( $text ) {
586
587 return '<!-- wp:paragraph --><p>' . $text . '</p><!-- /wp:paragraph -->';
588
589 }
590
591 /**
592 * Returns the more tag, depending on if the Classic Editor or Block Editor is used.
593 *
594 * @since 2.1.0
595 *
596 * @return string More Tag
597 */
598 private function element_more_tag() {
599
600 return '<!-- wp:more --><!--more--><!-- /wp:more -->';
601
602 }
603
604 /**
605 * Returns previous/next links, depending on if the Classic Editor or Block Editor is used.
606 *
607 * @since 2.1.0
608 *
609 * @param int $page_number Page Number.
610 * @param int $total_pages Total Pages.
611 * @return string Previous / Next Links
612 */
613 private function element_navigation( $page_number, $total_pages ) {
614
615 // Assume no previous or next link required.
616 $previous_link = '';
617 $next_link = '';
618
619 // If the page number is greater than zero, a previous link is required.
620 if ( $page_number > 0 ) {
621 $previous_link = '<!-- wp:post-navigation-link {"type":"previous","label":"Previous Lesson"} /-->';
622 }
623
624 // If the page number is less than the total pages, a next link is required.
625 if ( $page_number < $total_pages ) {
626 $next_link = '<!-- wp:post-navigation-link {"textAlign":"right","label":"Next Lesson"} /-->';
627 }
628
629 // Return a blank string if no previous or next links required.
630 if ( empty( $previous_link ) && empty( $next_link ) ) {
631 return '';
632 }
633
634 // Return links.
635 return '<!-- wp:columns -->
636 <div class="wp-block-columns"><!-- wp:column -->
637 <div class="wp-block-column">' . $previous_link . '</div>
638 <!-- /wp:column -->
639
640 <!-- wp:column -->
641 <div class="wp-block-column">' . $next_link . '</div>
642 <!-- /wp:column --></div>
643 <!-- /wp:columns -->';
644
645 }
646
647 /**
648 * Adds a link from the parent page to the child page.
649 *
650 * @since 2.1.0
651 *
652 * @param int $parent_page_id Parent Page ID.
653 * @param int $child_page_id Child Page ID.
654 */
655 private function add_link_from_parent_to_child_page( $parent_page_id, $child_page_id ) {
656
657 // Define button block linking to first child page.
658 $button_block = '<!-- wp:buttons -->
659 <div class="wp-block-buttons">
660 <!-- wp:button -->
661 <div class="wp-block-button">
662 <a class="wp-block-button__link" href="' . get_permalink( $child_page_id ) . '">' . __( 'Start Course', 'convertkit' ) . '</a>
663 </div>
664 <!-- /wp:button -->
665 </div>
666 <!-- /wp:buttons -->';
667
668 // Fetch parent page's content.
669 $parent_page = get_post( $parent_page_id );
670
671 // Update parent page's content to include a link to the first child page.
672 return wp_update_post(
673 array(
674 'ID' => $parent_page_id,
675 'post_content' => $parent_page->post_content .= $button_block,
676 ),
677 true
678 );
679
680 }
681
682 }
683