PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.7
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.7
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
formidable / classes / models / FrmSolution.php

FrmSolution.php in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More 6.7, at classes/models/FrmSolution.php

895 lines 21.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Handles the installation of a solution and any dependencies.
4 * This page is shown when a Formidable plugin is activated.
5 *
6 * @since 4.06.02
7 */
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 die( 'You are not allowed to call this page directly.' );
11 }
12
13 class FrmSolution {
14
15 protected $plugin_slug = '';
16
17 protected $plugin_file = '';
18
19 /**
20 * Hidden welcome page slug.
21 *
22 * @since 4.06.02
23 */
24 protected $page = '';
25
26 protected $icon = 'frm_icon_font frm_settings_icon';
27
28 public function __construct( $atts = array() ) {
29 if ( empty( $this->plugin_slug ) ) {
30 return;
31 }
32
33 add_action( 'plugins_loaded', array( $this, 'load_hooks' ), 50 );
34 add_action( 'admin_init', array( $this, 'redirect' ), 9999 );
35
36 if ( empty( $this->plugin_file ) ) {
37 $this->plugin_file = $this->plugin_slug . '.php';
38 }
39 }
40
41 /**
42 * Register all WP hooks.
43 *
44 * @since 4.06.02
45 *
46 * @return void
47 */
48 public function load_hooks() {
49 // If user is in admin ajax or doing cron, return.
50 if ( wp_doing_cron() ) {
51 return;
52 }
53
54 add_filter( 'frm_add_settings_section', array( $this, 'add_settings' ) );
55
56 if ( wp_doing_ajax() ) {
57 return;
58 }
59
60 // If user cannot manage_options, return.
61 if ( ! current_user_can( 'frm_change_settings' ) && ! FrmAppHelper::is_formidable_admin() ) {
62 return;
63 }
64
65 add_filter( 'plugin_action_links_' . $this->plugin_slug . '/' . $this->plugin_file, array( $this, 'plugin_links' ) );
66 add_action( 'admin_menu', array( $this, 'register' ) );
67 add_action( 'admin_head', array( $this, 'hide_menu' ) );
68 }
69
70 public function plugin_links( $links ) {
71 if ( ! $this->is_complete() ) {
72 $settings = '<a href="' . esc_url( $this->settings_link() ) . '">' . __( 'Setup', 'formidable' ) . '</a>';
73 array_unshift( $links, $settings );
74 }
75
76 return $links;
77 }
78
79 /**
80 * Register the pages to be used for the Welcome screen (and tabs).
81 *
82 * These pages will be removed from the Dashboard menu, so they will
83 * not actually show. Sneaky, sneaky.
84 *
85 * @since 4.06.02
86 *
87 * @return void
88 */
89 public function register() {
90
91 // Getting started - shows after installation.
92 add_dashboard_page(
93 esc_html( $this->page_title() ),
94 esc_html( $this->page_title() ),
95 'frm_change_settings',
96 $this->page,
97 array( $this, 'output' )
98 );
99 }
100
101 /**
102 * Removed the dashboard pages from the admin menu.
103 *
104 * This means the pages are still available to us, but hidden.
105 *
106 * @since 4.06.02
107 *
108 * @return void
109 */
110 public function hide_menu() {
111 remove_submenu_page( 'index.php', $this->page );
112 }
113
114 /**
115 * @return string
116 *
117 * @psalm-return ''
118 */
119 protected function plugin_name() {
120 return '';
121 }
122
123 /**
124 * @return string
125 */
126 protected function page_title() {
127 return __( 'Welcome to Formidable Forms', 'formidable' );
128 }
129
130 /**
131 * @return string
132 */
133 protected function page_description() {
134 return __( 'Follow the steps below to get started.', 'formidable' );
135 }
136
137 /**
138 * Welcome screen redirect.
139 *
140 * This function checks if a new install or update has just occurred. If so,
141 * then we redirect the user to the appropriate page.
142 *
143 * @since 4.06.02
144 *
145 * @return void
146 */
147 public function redirect() {
148
149 $current_page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
150 if ( $current_page === $this->page ) {
151 // Prevent endless loop.
152 return;
153 }
154
155 // Only do this for single site installs.
156 if ( isset( $_GET['activate-multi'] ) || is_network_admin() ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
157 return;
158 }
159
160 // Check if we should consider redirection.
161 if ( ! $this->is_current_plugin() ) {
162 return;
163 }
164
165 delete_transient( 'frm_activation_redirect' );
166
167 // Initial install.
168 wp_safe_redirect( $this->settings_link() );
169 exit;
170 }
171
172 /**
173 * @return string
174 */
175 protected function settings_link() {
176 return admin_url( 'index.php?page=' . $this->page );
177 }
178
179 /*
180 * Add page to global settings.
181 */
182 public function add_settings( $sections ) {
183 wp_enqueue_style( 'formidable-pro-fields' );
184 $sections[ $this->plugin_slug ] = array(
185 'class' => $this,
186 'function' => 'settings_page',
187 'name' => $this->plugin_name(),
188 'icon' => $this->icon,
189 'ajax' => true,
190 );
191 return $sections;
192 }
193
194 /*
195 * Output for global settings.
196 */
197 /**
198 * @return void
199 */
200 public function settings_page() {
201 $steps = $this->get_steps_data();
202 if ( ! $steps['license']['complete'] || ( isset( $steps['plugin'] ) && ! $steps['plugin']['complete'] ) ) {
203 // Redirect to the welcome page if install hasn't been done.
204 $url = $this->settings_link();
205 echo '<script>window.location.replace("' . esc_url_raw( $url ) . '");</script>';
206 return;
207 }
208
209 $all_imported = $this->is_complete( 'all' );
210
211 $step = $steps['import'];
212 $step['label'] = '';
213 $step['nested'] = true;
214
215 if ( $steps['complete']['current'] ) {
216 // Always show this step in settings.
217 $step['current'] = true;
218
219 $new_class = $all_imported ? ' button frm_hidden' : '';
220 $step['button_class'] = str_replace( 'frm_grey disabled', $new_class, $step['button_class'] );
221 }
222 if ( $all_imported ) {
223 $step['description'] = __( 'The following form(s) have been created.', 'formidable' );
224 }
225 $this->show_app_install( $step );
226
227 if ( ! $all_imported ) {
228 $step = $steps['complete'];
229 $step['current'] = false;
230 $step['button_class'] .= ' frm_grey disabled';
231 $this->show_page_links( $step );
232 }
233 }
234
235 /**
236 * Getting Started screen. Shows after first install.
237 *
238 * @return void
239 */
240 public function output() {
241 FrmAppHelper::include_svg();
242 $this->css();
243 $class = FrmAppHelper::pro_is_installed() ? 'pro' : 'lite';
244
245 echo '<div id="frm-welcome" class="wrap frm-wrap frm-admin-plugin-landing upgrade_to_pro ' . sanitize_html_class( $class ) . '">';
246
247 $this->header();
248 $this->main_content();
249
250 echo '</div>';
251 }
252
253 /**
254 * Heading section.
255 *
256 * @return void
257 */
258 protected function header() {
259 $size = array(
260 'height' => 90,
261 'width' => 90,
262 );
263
264 ?>
265 <section class="top">
266 <div class="frm-smtp-logos">
267 <?php FrmAppHelper::show_logo( $size ); ?>
268 <?php
269 FrmAppHelper::icon_by_class(
270 'frmfont frm_arrow_right_icon',
271 array(
272 'aria-label' => 'Install',
273 'style' => 'width:30px;height:30px;margin:0 35px;',
274 )
275 );
276 FrmAppHelper::icon_by_class(
277 'frmfont frm_wordpress_icon',
278 array(
279 'aria-label' => 'WordPress',
280 'style' => 'width:90px;height:90px;',
281 )
282 );
283 ?>
284 </div>
285 <h1><?php echo esc_html( $this->page_title() ); ?></h1>
286 <p><?php echo esc_html( $this->page_description() ); ?></p>
287 </section>
288 <?php
289 }
290
291 /**
292 * This is the welcome page content.
293 * Override me to insert different content.
294 *
295 * @return void
296 */
297 protected function main_content() {
298 $steps = $this->get_steps_data();
299 $this->license_box( $steps['license'] );
300 if ( isset( $steps['plugin'] ) ) {
301 $this->show_plugin_install( $steps['plugin'] );
302 }
303 $this->show_app_install( $steps['import'] );
304 $this->show_page_links( $steps['complete'] );
305 }
306
307 protected function get_steps_data() {
308 $pro_installed = FrmAppHelper::pro_is_connected();
309
310 $steps = array(
311 'license' => array(
312 'label' => __( 'Connect to FormidableForms.com', 'formidable' ),
313 'description' => __( 'Create a connection to get plugin downloads.', 'formidable' ),
314 'button_label' => __( 'Connect an Account', 'formidable' ),
315 'current' => empty( $pro_installed ),
316 'complete' => $pro_installed,
317 'num' => 1,
318 ),
319 'plugin' => array(
320 'label' => __( 'Install and Activate Add-Ons', 'formidable' ),
321 'description' => __( 'Install any required add-ons from FormidableForms.com.', 'formidable' ),
322 'button_label' => __( 'Install & Activate', 'formidable' ),
323 'current' => false,
324 'complete' => false,
325 'num' => 2,
326 ),
327 'import' => array(
328 'label' => __( 'Setup Forms, Views, and Pages', 'formidable' ),
329 'description' => __( 'Build the forms, views, and pages automatically.', 'formidable' ),
330 'button_label' => __( 'Create Now', 'formidable' ),
331 'complete' => $this->is_complete(),
332 'num' => 3,
333 ),
334 'complete' => array(
335 'label' => __( 'Customize Your New Pages', 'formidable' ),
336 'description' => __( 'Make any required changes and publish the page.', 'formidable' ),
337 'button_label' => __( 'View Page', 'formidable' ),
338 'complete' => false,
339 'num' => 4,
340 ),
341 );
342
343 $this->adjust_plugin_install_step( $steps );
344
345 $has_current = false;
346 foreach ( $steps as $k => $step ) {
347 // Set the current step.
348 if ( ! isset( $step['current'] ) ) {
349 if ( $step['complete'] ) {
350 $steps[ $k ]['current'] = false;
351 } else {
352 $steps[ $k ]['current'] = ! $has_current;
353 $has_current = true;
354 }
355 } elseif ( $step['current'] ) {
356 $has_current = true;
357 }
358
359 // Set disabled buttons.
360 $class = isset( $step['button_class'] ) ? $step['button_class'] : '';
361 $class .= ' button-primary frm-button-primary';
362 if ( ! $steps[ $k ]['current'] ) {
363 $class .= ' frm_grey disabled';
364 }
365 $steps[ $k ]['button_class'] = $class;
366 }
367
368 return $steps;
369 }
370
371 /**
372 * @param array $steps
373 *
374 * @return void
375 */
376 protected function adjust_plugin_install_step( &$steps ) {
377 $plugins = $this->required_plugins();
378 if ( empty( $plugins ) ) {
379 unset( $steps['plugin'] );
380 $steps['import']['num'] = 2;
381 $steps['complete']['num'] = 3;
382 return;
383 }
384
385 $missing = array();
386 $rel = array();
387 foreach ( $plugins as $plugin_key ) {
388 $plugin = FrmAddonsController::install_link( $plugin_key );
389 if ( $plugin['status'] === 'active' ) {
390 continue;
391 }
392 $links[ $plugin_key ] = $plugin;
393 if ( isset( $plugin['url'] ) ) {
394 $rel[] = $plugin['url'];
395 } else {
396 // Add-on is required but not allowed.
397 $missing[] = $plugin_key;
398 }
399 }
400 if ( empty( $rel ) && empty( $missing ) ) {
401 $steps['plugin']['complete'] = true;
402 } elseif ( ! empty( $missing ) ) {
403 $steps['plugin']['error'] = sprintf(
404 /* translators: %1$s: Plugin name */
405 esc_html__( 'You need permission to download the Formidable %1$s plugin', 'formidable' ),
406 implode( ', ', $missing )
407 );
408 } else {
409 $steps['plugin']['links'] = $rel;
410 $steps['plugin']['button_class'] = 'frm-solution-multiple ';
411 }
412
413 if ( $steps['license']['complete'] && ! $steps['plugin']['complete'] ) {
414 $steps['plugin']['current'] = true;
415 }
416 }
417
418 /**
419 * @return void
420 */
421 protected function step_top( $step ) {
422 $section_class = ( ! isset( $step['current'] ) || ! $step['current'] ) ? 'frm_grey' : '';
423
424 ?>
425 <section class="step step-install <?php echo esc_attr( $section_class ); ?>">
426 <aside class="num">
427 <?php
428 if ( isset( $step['complete'] ) && $step['complete'] ) {
429 FrmAppHelper::icon_by_class(
430 'frmfont frm_step_complete_icon',
431 array(
432 /* translators: %1$s: Step number */
433 'aria-label' => sprintf( __( 'Step %1$d', 'formidable' ), $step['num'] ),
434 'style' => 'width:50px;height:50px;',
435 )
436 );
437 } else {
438 ?>
439 <svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="0 0 100 100"><circle cx="50" cy="50" r="50" fill="#ccc"/><text x="50%" y="50%" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="2px" dy=".3em" font-size="3.7em"><?php echo esc_html( $step['num'] ); ?></text></svg>
440 <?php
441 }
442 ?>
443 <i class="loader hidden"></i>
444 </aside>
445 <div>
446 <?php if ( $step['label'] ) { ?>
447 <h3 class="frm-step-heading"><?php echo esc_html( $step['label'] ); ?></h3>
448 <?php } ?>
449 <p><?php echo esc_html( $step['description'] ); ?></p>
450 <?php if ( isset( $step['error'] ) ) { ?>
451 <p class="frm_error"><?php echo esc_html( $step['error'] ); ?></p>
452 <?php } ?>
453 <?php
454 }
455
456 /**
457 * @return void
458 */
459 protected function step_bottom( $step ) {
460 ?>
461 </div>
462 </section>
463 <?php
464 }
465
466 /**
467 * Generate and output Connect step section HTML.
468 *
469 * @return void
470 */
471 protected function license_box( $step ) {
472 $this->step_top( $step );
473
474 if ( $step['complete'] ) {
475 ?>
476 <a href="#" class="<?php echo esc_attr( $step['button_class'] ); ?>">
477 <?php echo esc_html( $step['button_label'] ); ?>
478 </a>
479 <?php
480 } else {
481 FrmSettingsController::license_box();
482 }
483
484 $this->step_bottom( $step );
485 }
486
487 /**
488 * @return void
489 */
490 protected function show_plugin_install( $step ) {
491 $this->step_top( $step );
492
493 if ( ! isset( $step['error'] ) ) {
494 $rel = isset( $step['links'] ) ? $step['links'] : array();
495
496 ?>
497 <a rel="<?php echo esc_attr( implode( ',', $rel ) ); ?>" class="<?php echo esc_attr( $step['button_class'] ); ?>">
498 <?php echo esc_html( $step['button_label'] ); ?>
499 </a>
500 <?php
501 }
502
503 $this->step_bottom( $step );
504 }
505
506 /**
507 * @return void
508 */
509 protected function show_app_install( $step ) {
510 $is_complete = $step['complete'];
511 if ( ! empty( $this->form_options() ) && ! $is_complete ) {
512 $step['description'] = __( 'Select the form or view you would like to create.', 'formidable' );
513 }
514
515 $this->step_top( $step );
516
517 $api = new FrmFormApi();
518 $addons = $api->get_api_info();
519
520 $id = $this->download_id();
521 $has_file = isset( $addons[ $id ] ) && isset( $addons[ $id ]['beta'] );
522
523 if ( ! $step['current'] ) {
524 ?>
525 <a href="#" class="<?php echo esc_attr( $step['button_class'] ); ?>">
526 <?php echo esc_html( $step['button_label'] ); ?>
527 </a>
528 <?php
529
530 $this->step_bottom( $step );
531 return;
532 }
533
534 if ( ! $has_file ) {
535 echo '<p class="frm_error_style">' . esc_html__( 'We didn\'t find anything to import. Please contact our team.', 'formidable' ) . '</p>';
536 } elseif ( ! isset( $addons[ $id ]['beta']['package'] ) ) {
537 echo '<p class="frm_error_style">' . esc_html__( 'Looks like you may not have a current subscription for this solution. Please check your account.', 'formidable' ) . '</p>';
538 } else {
539 $xml = $addons[ $id ]['beta']['package'];
540 if ( is_array( $xml ) ) {
541 $xml = reset( $xml );
542 }
543
544 if ( isset( $step['nested'] ) ) {
545 echo '<fieldset id="frm-new-template" class="field-group">';
546 } else {
547 echo '<form name="frm-new-template" id="frm-new-template" method="post" class="field-group">';
548 }
549
550 ?>
551 <input type="hidden" name="link" id="frm_link" value="<?php echo esc_attr( $xml ); ?>" />
552 <input type="hidden" name="type" id="frm_action_type" value="frm_install_template" />
553 <input type="hidden" name="template_name" id="frm_template_name" value="" />
554 <input type="hidden" name="template_desc" id="frm_template_desc" value="" />
555 <input type="hidden" name="redirect" value="0" />
556 <input type="hidden" name="show_response" value="frm_install_error" />
557 <?php
558 $this->show_form_options( $xml );
559 $this->show_view_options();
560
561 if ( ! $this->is_complete( 'all' ) ) {
562 // Don't show on the settings page when complete.
563 $this->show_page_options();
564 }
565 ?>
566 <p>
567 <button <?php echo esc_html( isset( $step['nested'] ) ? '' : 'type="submit" ' ); ?>class="<?php echo esc_attr( $step['button_class'] ); ?>">
568 <?php echo esc_html( $step['button_label'] ); ?>
569 </button>
570 </p>
571 <p id="frm_install_error" class="frm_error_style frm_hidden"></p>
572 <?php
573 if ( isset( $step['nested'] ) ) {
574 echo '</fieldset>';
575 } else {
576 echo '</form>';
577 }
578 }
579
580 $this->step_bottom( $step );
581 }
582
583 /**
584 * @return void
585 */
586 protected function show_form_options( $xml ) {
587 $this->show_import_options( $this->form_options(), 'form', $xml );
588 }
589
590 /**
591 * @return void
592 */
593 protected function show_view_options() {
594 $this->show_import_options( $this->view_options(), 'view' );
595 }
596
597 /**
598 * @param string $importing
599 *
600 * @psalm-param 'form'|'view' $importing
601 *
602 * @return void
603 */
604 protected function show_import_options( $options, $importing, $xml = '' ) {
605 if ( empty( $options ) ) {
606 return;
607 }
608
609 $imported = $this->previously_imported_forms();
610 $count = count( $options );
611 foreach ( $options as $info ) {
612 // Count the number of options displayed for css.
613 if ( $count > 1 && ! isset( $info['img'] ) ) {
614 $count --;
615 }
616 }
617 $width = floor( ( 533 - ( ( $count - 1 ) * 20 ) ) / $count );
618 unset( $count );
619
620 $selected = false;
621
622 include( FrmAppHelper::plugin_path() . '/classes/views/solutions/_import.php' );
623 }
624
625 /**
626 * @return void
627 */
628 protected function show_page_options() {
629 $pages = $this->needed_pages();
630 if ( empty( $pages ) ) {
631 return;
632 }
633
634 echo '<h3>Choose New Page Title</h3>';
635 foreach ( $pages as $page ) {
636 ?>
637 <p>
638 <label for="pages_<?php echo esc_html( $page['type'] ); ?>">
639 <?php echo esc_html( $page['label'] ); ?>
640 </label>
641 <input type="text" name="pages[<?php echo esc_html( $page['type'] ); ?>]" value="<?php echo esc_attr( $page['name'] ); ?>" id="pages_<?php echo esc_html( $page['type'] ); ?>" required />
642 </p>
643 <?php
644 }
645 }
646
647 /**
648 * @return void
649 */
650 protected function show_page_links( $step ) {
651 if ( $step['current'] ) {
652 return;
653 }
654
655 $this->step_top( $step );
656
657 ?>
658 <a href="#" target="_blank" rel="noopener" id="frm-redirect-link" class="<?php echo esc_attr( $step['button_class'] ); ?>">
659 <?php echo esc_html( $step['button_label'] ); ?>
660 </a>
661 <?php
662
663 $this->step_bottom( $step );
664 }
665
666 /**
667 * Only show the content for the correct plugin.
668 *
669 * @return bool
670 */
671 protected function is_current_plugin() {
672 $to_redirect = get_transient( 'frm_activation_redirect' );
673 return $to_redirect === $this->plugin_slug && empty( $this->is_complete() );
674 }
675
676 /**
677 * Override this function to indicate when install is complete.
678 *
679 * @param int|string $count
680 *
681 * @psalm-param 'all'|1 $count
682 *
683 * @return bool
684 */
685 protected function is_complete( $count = 1 ) {
686 $imported = $this->previously_imported_forms();
687 if ( $count === 'all' ) {
688 return count( $imported ) >= count( $this->form_options() );
689 }
690 return ! empty( $imported );
691 }
692
693 /**
694 * Get an array of all of the forms that have been imported.
695 *
696 * @return array
697 */
698 protected function previously_imported_forms() {
699 $imported = array();
700 $forms = $this->form_options();
701 foreach ( $forms as $form ) {
702 $was_imported = isset( $form['form'] ) ? FrmForm::get_id_by_key( $form['form'] ) : false;
703 if ( $was_imported ) {
704 $imported[ $form['form'] ] = $was_imported;
705 }
706 }
707
708 return $imported;
709 }
710
711 /**
712 * In the new plugin has any dependencies, include them here.
713 *
714 * @return array
715 */
716 protected function required_plugins() {
717 return array();
718 }
719
720 /**
721 * This needs to be overridden.
722 *
723 * @return int
724 */
725 protected function download_id() {
726 return 0;
727 }
728
729 /**
730 * Give options for which forms to import.
731 *
732 * @return array
733 */
734 protected function form_options() {
735 /**
736 * Example:
737 * array(
738 * 'unique-key' => array(
739 * 'keys' => 'forms keys here',
740 * 'name' => 'displayed label here',
741 * 'img' => 'svg code',
742 * ),
743 * )
744 */
745 return array();
746 }
747
748 /**
749 * Give options for which view to use.
750 *
751 * @return array
752 */
753 protected function view_options() {
754 return array();
755 }
756
757 /**
758 * If the pages aren't imported automatically, set the page names.
759 *
760 * @return array
761 */
762 protected function needed_pages() {
763 /**
764 * Example:
765 * array(
766 * array(
767 * 'label' => 'Page Name',
768 * 'name' => 'Default name',
769 * 'type' => 'form' or 'view',
770 * ),
771 * )
772 */
773
774 return array();
775 }
776
777 /**
778 * @return void
779 */
780 private function css() {
781 wp_enqueue_style( 'formidable-pro-fields' );
782 ?>
783 <style>
784 #frm-welcome *, #frm-welcome *::before, #frm-welcome *::after {
785 -webkit-box-sizing: border-box;
786 -moz-box-sizing: border-box;
787 box-sizing: border-box;
788 }
789 #frm-welcome{
790 width: 700px;
791 margin: 0 auto;
792 }
793 #frm-welcome p {
794 font-size: 15px;
795 }
796 #frm-welcome section{
797 margin: 50px 0;
798 text-align: left;
799 clear: both;
800 }
801 #frm-welcome .top{
802 text-align: center;
803 }
804 .frm-smtp-logos {
805 margin-bottom: 38px;
806 }
807 .frm-smtp-logos svg {
808 vertical-align: middle;
809 }
810 #frm-welcome .top h1 {
811 font-size: 26px;
812 font-weight: 600;
813 margin-bottom: 0;
814 padding: 0;
815 }
816 #frm-welcome .top p {
817 font-size: 17px;
818 color: #777;
819 margin-top: .5em;
820 }
821 #frm-welcome .screenshot ul {
822 display: inline-block;
823 margin: 0 0 0 30px;
824 list-style-type: none;
825 max-width: calc(100% - 350px);
826 }
827 #frm-welcome .screenshot li {
828 margin: 16px 0;
829 padding: 0;
830 font-size: 15px;
831 color: #777;
832 }
833 #frm-welcome .screenshot .cont img {
834 max-width: 100%;
835 display: block;
836 }
837 #frm-welcome .screenshot .cont {
838 display: inline-block;
839 position: relative;
840 width: 315px;
841 padding: 5px;
842 background-color: #fff;
843 border-radius: 3px;
844 }
845 #frm-welcome .step,
846 #frm-welcome .screenshot .cont {
847 -webkit-box-shadow: 0px 2px 5px 0px rgba(0, 0, 0, 0.05);
848 -moz-box-shadow: 0px 2px 5px 0px rgba(0, 0, 0, 0.05);
849 box-shadow: 0px 2px 5px 0px rgba(0, 0, 0, 0.05);
850 }
851 #frm-welcome .step {
852 background-color: #F9F9F9;
853 border: 1px solid #E5E5E5;
854 margin: 0 0 25px;
855 }
856 #frm-welcome .screenshot > *,
857 #frm-welcome .step > * {
858 vertical-align: middle;
859 }
860 #frm-welcome .step p {
861 font-size: 16px;
862 color: #777777;
863 }
864 #frm-welcome .step .num {
865 display: inline-block;
866 position: relative;
867 width: 100px;
868 height: 50px;
869 text-align: center;
870 }
871 #frm-welcome .step > div {
872 display: inline-block;
873 width: calc(100% - 104px);
874 background-color: #fff;
875 padding: 30px;
876 border-left: 1px solid #eee;
877 }
878 #frm-welcome .step h3.frm-step-heading {
879 font-size: 24px;
880 line-height: 22px;
881 margin-top: 0;
882 margin-bottom: 15px;
883 }
884 #frm-welcome .button.disabled {
885 cursor: default;
886 }
887 #frm-welcome #frm-using-lite {
888 display: none;
889 }
890 </style>
891 <?php
892 }
893
894 }
895