Forms/Loader.php000066600000002776152141020640007564 0ustar00register_class( $class_name ); } } /** * Register a new class. * * @since 1.5.1 * * @param string $class_name Class name to register. */ public function register_class( $class_name ) { $class_name = \sanitize_text_field( $class_name ); // Load Lite class if exists. if ( ! \wpforms()->pro && \class_exists( 'WPForms\Lite\Forms\\' . $class_name ) ) { $class_name = 'WPForms\Lite\Forms\\' . $class_name; new $class_name(); return; } // Load Pro class if exists. if ( \wpforms()->pro && \class_exists( 'WPForms\Pro\Forms\\' . $class_name ) ) { $class_name = 'WPForms\Pro\Forms\\' . $class_name; new $class_name(); return; } // Load general class if neither Pro nor Lite class exists. if ( \class_exists( __NAMESPACE__ . '\\' . $class_name ) ) { $class_name = __NAMESPACE__ . '\\' . $class_name; new $class_name(); } } } Forms/Preview.php000066600000011761152141020640007771 0ustar00is_preview_page() ) { return; } $this->hooks(); } /** * Check if current page request meets requirements for form preview page. * * @since 1.5.1 * * @return bool */ public function is_preview_page() { // Only proceed for the form preview page. if ( empty( $_GET['wpforms_form_preview'] ) ) { // phpcs:ignore return false; } // Check for logged in user with correct capabilities. if ( ! \is_user_logged_in() ) { return false; } $form_id = \absint( $_GET['wpforms_form_preview'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended if ( ! \wpforms_current_user_can( 'view_form_single', $form_id ) ) { return false; } // Fetch form details for the entry. $this->form_data = \wpforms()->form->get( $form_id, array( 'content_only' => true, ) ); // Check valid form was found. if ( empty( $this->form_data ) ) { return false; } return true; } /** * Hooks. * * @since 1.5.1 */ public function hooks() { \add_action( 'pre_get_posts', array( $this, 'pre_get_posts' ) ); \add_filter( 'the_title', array( $this, 'the_title' ), 100, 1 ); \add_filter( 'the_content', array( $this, 'the_content' ), 999 ); \add_filter( 'get_the_excerpt', array( $this, 'the_content' ), 999 ); \add_filter( 'template_include', array( $this, 'template_include' ) ); \add_filter( 'post_thumbnail_html', '__return_empty_string' ); } /** * Modify query, limit to one post. * * @since 1.5.1 * * @param \WP_Query $query The WP_Query instance. */ public function pre_get_posts( $query ) { if ( ! is_admin() && $query->is_main_query() ) { $query->set( 'posts_per_page', 1 ); } } /** * Customize form preview page title. * * @since 1.5.1 * * @param string $title Page title. * * @return string */ public function the_title( $title ) { if ( in_the_loop() ) { $title = sprintf( /* translators: %s - form title. */ esc_html__( '%s Preview', 'wpforms-lite' ), ! empty( $this->form_data['settings']['form_title'] ) ? sanitize_text_field( $this->form_data['settings']['form_title'] ) : esc_html__( 'Form', 'wpforms-lite' ) ); } return $title; } /** * Customize form preview page content. * * @since 1.5.1 * * @return string */ public function the_content() { if ( ! isset( $this->form_data['id'] ) ) { return ''; } if ( ! wpforms_current_user_can( 'view_form_single', $this->form_data['id'] ) ) { return ''; } $links = []; if ( wpforms_current_user_can( 'edit_form_single', $this->form_data['id'] ) ) { $links[] = [ 'url' => esc_url( add_query_arg( [ 'page' => 'wpforms-builder', 'view' => 'fields', 'form_id' => absint( $this->form_data['id'] ), ], admin_url( 'admin.php' ) ) ), 'text' => esc_html__( 'Edit Form', 'wpforms-lite' ), ]; } if ( wpforms()->pro && wpforms_current_user_can( 'view_entries_form_single', $this->form_data['id'] ) ) { $links[] = [ 'url' => esc_url( add_query_arg( [ 'page' => 'wpforms-entries', 'view' => 'list', 'form_id' => absint( $this->form_data['id'] ), ], admin_url( 'admin.php' ) ) ), 'text' => esc_html__( 'View Entries', 'wpforms-lite' ), ]; } if ( ! empty( $_GET['new_window'] ) ) { // phpcs:ignore $links[] = [ 'url' => 'javascript:window.close();', 'text' => esc_html__( 'Close this window', 'wpforms-lite' ), ]; } $content = '

'; $content .= esc_html__( 'This is a preview of your form. This page is not publicly accessible.', 'wpforms-lite' ); if ( ! empty( $links ) ) { $content .= '
'; foreach ( $links as $key => $link ) { $content .= '' . $link['text'] . ''; $l = array_keys( $links ); if ( end( $l ) !== $key ) { $content .= ' | '; } } } $content .= '

'; $content .= '

'; $content .= sprintf( wp_kses( /* translators: %1$s - WPForms doc link. */ __( 'For form testing tips, check out our complete guide!', 'wpforms-lite' ), [ 'a' => [ 'href' => [], 'target' => [], 'rel' => [], ], ] ), 'https://wpforms.com/docs/how-to-properly-test-your-wordpress-forms-before-launching-checklist/' ); $content .= '

'; $content .= do_shortcode( '[wpforms id="' . absint( $this->form_data['id'] ) . '"]' ); return $content; } /** * Force page template types. * * @since 1.5.1 * * @return string */ public function template_include() { return locate_template( array( 'page.php', 'single.php', 'index.php' ) ); } } Admin/Pages/SMTP.php000066600000031542152141020640010133 0ustar00 'wp-mail-smtp/wp_mail_smtp.php', 'lite_download_url' => 'https://downloads.wordpress.org/plugin/wp-mail-smtp.zip', 'pro_plugin' => 'wp-mail-smtp-pro/wp_mail_smtp.php', 'smtp_settings' => 'admin.php?page=wp-mail-smtp', ); /** * Runtime data used for generating page HTML. * * @since 1.5.7 * * @var array */ private $output_data = array(); /** * Constructor. * * @since 1.5.7 */ public function __construct() { if ( ! \wpforms_current_user_can() ) { return; } $this->hooks(); } /** * Hooks. * * @since 1.5.7 */ public function hooks() { if ( wp_doing_ajax() ) { add_action( 'wp_ajax_wpforms_smtp_page_check_plugin_status', array( $this, 'ajax_check_plugin_status' ) ); } // Check what page we are on. $page = isset( $_GET['page'] ) ? \sanitize_key( \wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore WordPress.CSRF.NonceVerification // Only load if we are actually on the SMTP page. if ( self::SLUG !== $page ) { return; } add_action( 'admin_init', array( $this, 'redirect_to_smtp_settings' ) ); add_filter( 'wpforms_admin_header', '__return_false' ); add_action( 'wpforms_admin_page', array( $this, 'output' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) ); // Hook for addons. do_action( 'wpforms_admin_pages_smtp_hooks' ); } /** * Enqueue JS and CSS files. * * @since 1.5.7 */ public function enqueue_assets() { $min = \wpforms_get_min_suffix(); // Lity. wp_enqueue_style( 'wpforms-lity', WPFORMS_PLUGIN_URL . 'assets/css/lity.min.css', null, '3.0.0' ); wp_enqueue_script( 'wpforms-lity', WPFORMS_PLUGIN_URL . 'assets/js/lity.min.js', array( 'jquery' ), '3.0.0', true ); wp_enqueue_script( 'wpforms-admin-page-smtp', WPFORMS_PLUGIN_URL . "assets/js/components/admin/pages/smtp{$min}.js", array( 'jquery' ), WPFORMS_VERSION, true ); \wp_localize_script( 'wpforms-admin-page-smtp', 'wpforms_pluginlanding', $this->get_js_strings() ); } /** * JS Strings. * * @since 1.5.7 * * @return array Array of strings. */ protected function get_js_strings() { $error_could_not_install = sprintf( wp_kses( /* translators: %s - Lite plugin download URL. */ __( 'Could not install plugin. Please download and install manually.', 'wpforms-lite' ), array( 'a' => array( 'href' => true, ), ) ), esc_url( $this->config['lite_download_url'] ) ); $error_could_not_activate = sprintf( wp_kses( /* translators: %s - Lite plugin download URL. */ __( 'Could not activate plugin. Please activate from the Plugins page.', 'wpforms-lite' ), array( 'a' => array( 'href' => true, ), ) ), esc_url( admin_url( 'plugins.php' ) ) ); return array( 'installing' => esc_html__( 'Installing...', 'wpforms-lite' ), 'activating' => esc_html__( 'Activating...', 'wpforms-lite' ), 'activated' => esc_html__( 'WP Mail SMTP Installed & Activated', 'wpforms-lite' ), 'install_now' => esc_html__( 'Install Now', 'wpforms-lite' ), 'activate_now' => esc_html__( 'Activate Now', 'wpforms-lite' ), 'download_now' => esc_html__( 'Download Now', 'wpforms-lite' ), 'plugins_page' => esc_html__( 'Go to Plugins page', 'wpforms-lite' ), 'error_could_not_install' => $error_could_not_install, 'error_could_not_activate' => $error_could_not_activate, 'manual_install_url' => $this->config['lite_download_url'], 'manual_activate_url' => admin_url( 'plugins.php' ), 'smtp_settings_button' => esc_html__( 'Go to SMTP Settings', 'wpforms-lite' ), ); } /** * Generate and output page HTML. * * @since 1.5.7 */ public function output() { echo '
'; $this->output_section_heading(); $this->output_section_screenshot(); $this->output_section_step_install(); $this->output_section_step_setup(); echo '
'; } /** * Generate and output heading section HTML. * * @since 1.5.7 */ protected function output_section_heading() { // Heading section. printf( '
%3$s

%4$s

%5$s

', esc_url( WPFORMS_PLUGIN_URL . 'assets/images/smtp/wpforms-wpmailsmtp.png' ), esc_url( WPFORMS_PLUGIN_URL . 'assets/images/smtp/wpforms-wpmailsmtp@2x.png' ), esc_attr__( 'WPForms ♥ WP Mail SMTP', 'wpforms-lite' ), esc_html__( 'Making Email Deliverability Easy for WordPress', 'wpforms-lite' ), esc_html__( 'WP Mail SMTP allows you to easily set up WordPress to use a trusted provider to reliably send emails, including form notifications. Built by the same folks behind WPForms.', 'wpforms-lite' ) ); } /** * Generate and output screenshot section HTML. * * @since 1.5.7 */ protected function output_section_screenshot() { // Screenshot section. printf( '
%2$s
', esc_url( WPFORMS_PLUGIN_URL . 'assets/images/smtp/screenshot-tnail.png' ), esc_attr__( 'WP Mail SMTP screenshot', 'wpforms-lite' ), esc_url( WPFORMS_PLUGIN_URL . 'assets/images/smtp/screenshot-full.png' ), esc_html__( 'Over 1,000,000 websites use WP Mail SMTP.', 'wpforms-lite' ), esc_html__( 'Send emails authenticated via trusted parties.', 'wpforms-lite' ), esc_html__( 'Transactional Mailers: Pepipost, SendinBlue, Mailgun, SendGrid, Amazon SES.', 'wpforms-lite' ), esc_html__( 'Web Mailers: Gmail, G Suite, Office 365, Outlook.com.', 'wpforms-lite' ) ); } /** * Generate and output step 'Install' section HTML. * * @since 1.5.7 */ protected function output_section_step_install() { $step = $this->get_data_step_install(); if ( empty( $step ) ) { return; } printf( '

%3$s

%4$s

', esc_url( WPFORMS_PLUGIN_URL . 'assets/images/' . $step['icon'] ), esc_attr__( 'Step 1', 'wpforms-lite' ), esc_html__( 'Install and Activate WP Mail SMTP', 'wpforms-lite' ), esc_html__( 'Install WP Mail SMTP from the WordPress.org plugin repository.', 'wpforms-lite' ), esc_attr( $step['button_class'] ), esc_attr( $step['plugin'] ), esc_attr( $step['button_action'] ), esc_html( $step['button_text'] ) ); } /** * Generate and output step 'Setup' section HTML. * * @since 1.5.7 */ protected function output_section_step_setup() { $step = $this->get_data_step_setup(); if ( empty( $step ) ) { return; } printf( '

%4$s

%5$s

', esc_attr( $step['section_class'] ), esc_url( WPFORMS_PLUGIN_URL . 'assets/images/' . $step['icon'] ), esc_attr__( 'Step 2', 'wpforms-lite' ), esc_html__( 'Set Up WP Mail SMTP', 'wpforms-lite' ), esc_html__( 'Select and configure your mailer.', 'wpforms-lite' ), esc_attr( $step['button_class'] ), esc_url( admin_url( $this->config['smtp_settings'] ) ), esc_html( $step['button_text'] ) ); } /** * Step 'Install' data. * * @since 1.5.7 * * @return array Step data. */ protected function get_data_step_install() { $step = array(); $this->output_data['all_plugins'] = get_plugins(); $this->output_data['plugin_installed'] = array_key_exists( $this->config['lite_plugin'], $this->output_data['all_plugins'] ); $this->output_data['pro_plugin_installed'] = array_key_exists( $this->config['pro_plugin'], $this->output_data['all_plugins'] ); $this->output_data['plugin_activated'] = false; $this->output_data['plugin_setup'] = false; if ( ! $this->output_data['plugin_installed'] && ! $this->output_data['pro_plugin_installed'] ) { $step['icon'] = 'step-1.svg'; $step['button_text'] = esc_html__( 'Install WP Mail SMTP', 'wpforms-lite' ); $step['button_class'] = ''; $step['button_action'] = 'install'; $step['plugin'] = $this->config['lite_download_url']; } else { $this->output_data['plugin_activated'] = $this->is_smtp_activated(); $this->output_data['plugin_setup'] = $this->is_smtp_configured(); $step['icon'] = $this->output_data['plugin_activated'] ? 'step-complete.svg' : 'step-1.svg'; $step['button_text'] = $this->output_data['plugin_activated'] ? esc_html__( 'WP Mail SMTP Installed & Activated', 'wpforms-lite' ) : esc_html__( 'Activate WP Mail SMTP', 'wpforms-lite' ); $step['button_class'] = $this->output_data['plugin_activated'] ? 'grey disabled' : ''; $step['button_action'] = $this->output_data['plugin_activated'] ? '' : 'activate'; $step['plugin'] = $this->output_data['pro_plugin_installed'] ? $this->config['pro_plugin'] : $this->config['lite_plugin']; } return $step; } /** * Step 'Setup' data. * * @since 1.5.7 * * @return array Step data. */ protected function get_data_step_setup() { $step = array(); $step['icon'] = 'step-2.svg'; $step['section_class'] = $this->output_data['plugin_activated'] ? '' : 'grey'; $step['button_text'] = esc_html__( 'Start Setup', 'wpforms-lite' ); $step['button_class'] = 'grey disabled'; if ( $this->output_data['plugin_setup'] ) { $step['icon'] = 'step-complete.svg'; $step['section_class'] = ''; $step['button_text'] = esc_html__( 'Go to SMTP settings', 'wpforms-lite' ); } else { $step['button_class'] = $this->output_data['plugin_activated'] ? '' : 'grey disabled'; } return $step; } /** * Ajax endpoint. Check plugin setup status. * Used to properly init step 'Setup' section after completing step 'Install'. * * @since 1.5.7 */ public function ajax_check_plugin_status() { // Security checks. if ( ! check_ajax_referer( 'wpforms-admin', 'nonce', false ) || ! wpforms_current_user_can() ) { wp_send_json_error( array( 'error' => esc_html__( 'You do not have permission.', 'wpforms-lite' ), ) ); } $result = array(); if ( ! $this->is_smtp_activated() ) { wp_send_json_error( array( 'error' => esc_html__( 'Plugin unavailable.', 'wpforms-lite' ), ) ); } $result['setup_status'] = (int) $this->is_smtp_configured(); $result['license_level'] = wp_mail_smtp()->get_license_type(); wp_send_json_success( $result ); } /** * Get $phpmailer instance. * * @since 1.5.7 * * @return \PHPMailer Instance of PHPMailer. */ protected function get_phpmailer() { global $phpmailer; if ( ! is_object( $phpmailer ) || ! is_a( $phpmailer, 'PHPMailer' ) ) { require_once ABSPATH . WPINC . '/class-phpmailer.php'; $phpmailer = new \PHPMailer( true ); // phpcs:ignore } return $phpmailer; } /** * Whether WP Mail SMTP plugin configured or not. * * @since 1.5.7 * * @return bool True if some mailer is selected and configured properly. */ protected function is_smtp_configured() { if ( ! $this->is_smtp_activated() ) { return false; } $phpmailer = $this->get_phpmailer(); $mailer = \WPMailSMTP\Options::init()->get( 'mail', 'mailer' ); $is_mailer_complete = wp_mail_smtp()->get_providers()->get_mailer( $mailer, $phpmailer )->is_mailer_complete(); return 'mail' !== $mailer && $is_mailer_complete; } /** * Whether WP Mail SMTP plugin active or not. * * @since 1.5.7 * * @return bool True if SMTP plugin is active. */ protected function is_smtp_activated() { return function_exists( 'wp_mail_smtp' ) && ( is_plugin_active( $this->config['lite_plugin'] ) || is_plugin_active( $this->config['pro_plugin'] ) ); } /** * Redirect to SMTP settings page. * * @since 1.5.7 */ public function redirect_to_smtp_settings() { // Redirect to SMTP plugin if it is activated. if ( $this->is_smtp_configured() ) { wp_safe_redirect( admin_url( $this->config['smtp_settings'] ) ); exit; } } } Admin/Pages/Community.php000066600000012733152141020640011335 0ustar00hooks(); } } /** * Hooks. * * @since 1.5.6 */ public function hooks() { // Check what page we are on. $page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore WordPress.CSRF.NonceVerification // Only load if we are actually on the Community page. if ( self::SLUG !== $page ) { return; } add_action( 'wpforms_admin_page', array( $this, 'output' ) ); // Hook for addons. do_action( 'wpforms_admin_community_init' ); } /** * Page data. * * @since 1.5.6 */ public function get_blocks_data() { $data = array(); $data['vip_circle'] = array( 'title' => esc_html__( 'WPForms VIP Circle Facebook Group', 'wpforms-lite' ), 'description' => esc_html__( 'Powered by the community, for the community. Anything and everything WPForms: Discussions. Questions. Tutorials. Insights and sneak peaks. Also, exclusive giveaways!', 'wpforms-lite' ), 'button_text' => esc_html__( 'Join WPForms VIP Circle', 'wpforms-lite' ), 'button_link' => 'https://www.facebook.com/groups/wpformsvip/', 'cover_bg_color' => '#E4F0F6', 'cover_img' => 'vip-circle.png', 'cover_img2x' => 'vip-circle@2x.png', ); $data['dev_docs'] = array( 'title' => esc_html__( 'WPForms Developer Documentation', 'wpforms-lite' ), 'description' => esc_html__( 'Customize and extend WPForms with code. Our comprehensive developer resources include tutorials, snippets, and documentation on core actions, filters, functions, and more.', 'wpforms-lite' ), 'button_text' => esc_html__( 'View WPForms Dev Docs', 'wpforms-lite' ), 'button_link' => 'https://wpforms.com/developers/?utm_source=WordPress&utm_medium=Community&utm_campaign=liteplugin&utm_content=Developers', 'cover_bg_color' => '#EBEBEB', 'cover_img' => 'dev-docs.png', 'cover_img2x' => 'dev-docs@2x.png', ); $data['wpbeginner'] = array( 'title' => esc_html__( 'WPBeginner Engage Facebook Group', 'wpforms-lite' ), 'description' => esc_html__( 'Hang out with other WordPress experts and like minded website owners such as yourself! Hosted by WPBeginner, the largest free WordPress site for beginners.', 'wpforms-lite' ), 'button_text' => esc_html__( 'Join WPBeginner Engage', 'wpforms-lite' ), 'button_link' => 'https://www.facebook.com/groups/wpbeginner/', 'cover_bg_color' => '#FCEBDF', 'cover_img' => 'wpbeginner.png', 'cover_img2x' => 'wpbeginner@2x.png', ); $data['translators'] = array( 'title' => esc_html__( 'WPForms Translators Community', 'wpforms-lite' ), 'description' => esc_html__( 'We\'re building a community of translators and i18n experts to translate WPForms. Sign up to our translator community newsletter to learn more and get information on how you can contribute!', 'wpforms-lite' ), 'button_text' => esc_html__( 'Join Translators Community', 'wpforms-lite' ), 'button_link' => 'https://wpforms.com/translator-community-signup/?utm_source=WordPress&utm_medium=Community&utm_campaign=liteplugin&utm_content=Translators', 'cover_bg_color' => '#F2FAED', 'cover_img' => 'translators.png', 'cover_img2x' => 'translators@2x.png', ); $data['suggest'] = array( 'title' => esc_html__( 'Suggest a Feature', 'wpforms-lite' ), 'description' => esc_html__( 'Do you have an idea or suggestion for WPForms? If you have thoughts on features, integrations, addons, or improvements - we want to hear it! We appreciate all feedback and insight from our users.', 'wpforms-lite' ), 'button_text' => esc_html__( 'Suggest a Feature', 'wpforms-lite' ), 'button_link' => 'https://wpforms.com/features/suggest/?utm_source=WordPress&utm_medium=Community&utm_campaign=liteplugin&utm_content=Feature', 'cover_bg_color' => '#FFF9EF', 'cover_img' => 'suggest.png', 'cover_img2x' => 'suggest@2x.png', ); return $data; } /** * Generate and output page HTML. * * @since 1.5.6 */ public function output() { ?>

get_blocks_data(); foreach ( $data as $item ) { printf( '
%4$s

%s

%s

', esc_attr( $item['cover_bg_color'] ), esc_url( WPFORMS_PLUGIN_URL . 'assets/images/community/' . $item['cover_img'] ), esc_url( WPFORMS_PLUGIN_URL . 'assets/images/community/' . $item['cover_img2x'] ), esc_html( $item['title'] ), esc_html( $item['description'] ), esc_url( $item['button_link'] ), esc_html( $item['button_text'] ) ); } ?>
'google-analytics-for-wordpress/googleanalytics.php', 'lite_download_url' => 'https://downloads.wordpress.org/plugin/google-analytics-for-wordpress.zip', 'pro_plugin' => 'google-analytics-premium/googleanalytics-premium.php', 'forms_addon' => 'monsterinsights-forms/monsterinsights-forms.php', 'mi_forms_addon_page' => 'https://www.monsterinsights.com/addon/forms/?utm_source=wpformsplugin&utm_medium=link&utm_campaign=analytics-page', 'mi_onboarding' => 'admin.php?page=monsterinsights-onboarding', 'mi_addons' => 'admin.php?page=monsterinsights_settings#/addons', 'mi_forms' => 'admin.php?page=monsterinsights_reports#/forms', ); /** * Runtime data used for generating page HTML. * * @since 1.5.7 * * @var array */ private $output_data = array(); /** * Constructor. * * @since 1.5.7 */ public function __construct() { if ( ! \wpforms_current_user_can() ) { return; } $this->hooks(); } /** * Hooks. * * @since 1.5.7 */ public function hooks() { if ( wp_doing_ajax() ) { add_action( 'wp_ajax_wpforms_analytics_page_check_plugin_status', array( $this, 'ajax_check_plugin_status' ) ); } // Check what page we are on. $page = isset( $_GET['page'] ) ? \sanitize_key( \wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore WordPress.CSRF.NonceVerification // Only load if we are actually on the Analytics page. if ( self::SLUG !== $page ) { return; } add_action( 'admin_init', array( $this, 'redirect_to_mi_forms' ) ); add_filter( 'wpforms_admin_header', '__return_false' ); add_action( 'wpforms_admin_page', array( $this, 'output' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) ); // Hook for addons. do_action( 'wpforms_admin_pages_analytics_hooks' ); } /** * Enqueue JS and CSS files. * * @since 1.5.7 */ public function enqueue_assets() { $min = \wpforms_get_min_suffix(); // Lity. wp_enqueue_style( 'wpforms-lity', WPFORMS_PLUGIN_URL . 'assets/css/lity.min.css', null, '3.0.0' ); wp_enqueue_script( 'wpforms-lity', WPFORMS_PLUGIN_URL . 'assets/js/lity.min.js', array( 'jquery' ), '3.0.0', true ); wp_enqueue_script( 'wpforms-admin-page-analytics', WPFORMS_PLUGIN_URL . "assets/js/components/admin/pages/analytics{$min}.js", array( 'jquery' ), WPFORMS_VERSION, true ); \wp_localize_script( 'wpforms-admin-page-analytics', 'wpforms_pluginlanding', $this->get_js_strings() ); } /** * JS Strings. * * @since 1.5.7 * * @return array Array of strings. */ protected function get_js_strings() { $error_could_not_install = sprintf( wp_kses( /* translators: %s - Lite plugin download URL. */ __( 'Could not install plugin. Please download and install manually.', 'wpforms-lite' ), array( 'a' => array( 'href' => true, ), ) ), esc_url( $this->config['lite_download_url'] ) ); $error_could_not_activate = sprintf( wp_kses( /* translators: %s - Lite plugin download URL. */ __( 'Could not activate plugin. Please activate from the Plugins page.', 'wpforms-lite' ), array( 'a' => array( 'href' => true, ), ) ), esc_url( admin_url( 'plugins.php' ) ) ); return array( 'installing' => esc_html__( 'Installing...', 'wpforms-lite' ), 'activating' => esc_html__( 'Activating...', 'wpforms-lite' ), 'activated' => esc_html__( 'MonsterInsights Installed & Activated', 'wpforms-lite' ), 'install_now' => esc_html__( 'Install Now', 'wpforms-lite' ), 'activate_now' => esc_html__( 'Activate Now', 'wpforms-lite' ), 'download_now' => esc_html__( 'Download Now', 'wpforms-lite' ), 'plugins_page' => esc_html__( 'Go to Plugins page', 'wpforms-lite' ), 'error_could_not_install' => $error_could_not_install, 'error_could_not_activate' => $error_could_not_activate, 'mi_manual_install_url' => $this->config['lite_download_url'], 'mi_manual_activate_url' => admin_url( 'plugins.php' ), ); } /** * Generate and output page HTML. * * @since 1.5.7 */ public function output() { echo '
'; $this->output_section_heading(); $this->output_section_screenshot(); $this->output_section_step_install(); $this->output_section_step_setup(); $this->output_section_step_addon(); echo '
'; } /** * Generate and output heading section HTML. * * @since 1.5.7 */ public function output_section_heading() { // Heading section. printf( '
%3$s

%4$s

%5$s

', esc_url( WPFORMS_PLUGIN_URL . 'assets/images/analytics/wpforms-monsterinsights.png' ), esc_url( WPFORMS_PLUGIN_URL . 'assets/images/analytics/wpforms-monsterinsights@2x.png' ), esc_attr__( 'WPForms ♥ MonsterInsights', 'wpforms-lite' ), esc_html__( 'The Best Google Analytics Plugin for WordPress', 'wpforms-lite' ), esc_html__( 'MonsterInsights connects WPForms to Google Analytics, providing a powerful integration with their Forms addon. MonsterInsights is a sister company of WPForms.', 'wpforms-lite' ) ); } /** * Generate and output heading section HTML. * * @since 1.5.7 */ protected function output_section_screenshot() { // Screenshot section. printf( '
%2$s
', esc_url( WPFORMS_PLUGIN_URL . 'assets/images/analytics/screenshot-tnail.jpg' ), esc_attr__( 'Analytics screenshot', 'wpforms-lite' ), esc_url( WPFORMS_PLUGIN_URL . 'assets/images/analytics/screenshot-full.jpg' ), esc_html__( 'Track form impressions and conversions.', 'wpforms-lite' ), esc_html__( 'View form conversion rates from WordPress.', 'wpforms-lite' ), esc_html__( 'Complete UTM tracking with form entries.', 'wpforms-lite' ), esc_html__( 'Automatic integration with WPForms.', 'wpforms-lite' ) ); } /** * Generate and output step 'Install' section HTML. * * @since 1.5.7 */ protected function output_section_step_install() { $step = $this->get_data_step_install(); if ( empty( $step ) ) { return; } printf( '

%3$s

%4$s

', esc_url( WPFORMS_PLUGIN_URL . 'assets/images/' . $step['icon'] ), esc_attr__( 'Step 1', 'wpforms-lite' ), esc_html__( 'Install & Activate MonsterInsights', 'wpforms-lite' ), esc_html__( 'Track form impressions and conversions.', 'wpforms-lite' ), esc_attr( $step['button_class'] ), esc_attr( $step['plugin'] ), esc_attr( $step['button_action'] ), esc_html( $step['button_text'] ) ); } /** * Generate and output step 'Setup' section HTML. * * @since 1.5.7 */ protected function output_section_step_setup() { $step = $this->get_data_step_setup(); if ( empty( $step ) ) { return; } printf( '

%4$s

%5$s

', esc_attr( $step['section_class'] ), esc_url( WPFORMS_PLUGIN_URL . 'assets/images/' . $step['icon'] ), esc_attr__( 'Step 2', 'wpforms-lite' ), esc_html__( 'Setup MonsterInsights', 'wpforms-lite' ), esc_html__( 'MonsterInsights has an intuitive setup wizard to guide you through the setup process.', 'wpforms-lite' ), esc_attr( $step['button_class'] ), esc_url( admin_url( $this->config['mi_onboarding'] ) ), esc_html( $step['button_text'] ) ); } /** * Generate and output step 'Addon' section HTML. * * @since 1.5.7 */ protected function output_section_step_addon() { $step = $this->get_data_step_addon(); if ( empty( $step ) ) { return; } printf( '

%4$s

%5$s

', esc_attr( $step['section_class'] ), esc_url( WPFORMS_PLUGIN_URL . 'assets/images/step-3.svg' ), esc_attr__( 'Step 3', 'wpforms-lite' ), esc_html__( 'Get Form Conversion Tracking', 'wpforms-lite' ), esc_html__( 'With the MonsterInsights Form addon you can easily track your form views, entries, conversion rates, and more.', 'wpforms-lite' ), esc_attr( $step['button_class'] ), esc_url( $step['button_url'] ), esc_html( $step['button_text'] ) ); } /** * Step 'Install' data. * * @since 1.5.7 * * @return array Step data. */ protected function get_data_step_install() { $this->output_data['all_plugins'] = get_plugins(); $this->output_data['plugin_installed'] = array_key_exists( $this->config['lite_plugin'], $this->output_data['all_plugins'] ); $this->output_data['plugin_activated'] = false; $this->output_data['pro_plugin_installed'] = array_key_exists( $this->config['pro_plugin'], $this->output_data['all_plugins'] ); $this->output_data['pro_plugin_activated'] = false; $step = array(); if ( ! $this->output_data['plugin_installed'] && ! $this->output_data['pro_plugin_installed'] ) { $step['icon'] = 'step-1.svg'; $step['button_text'] = esc_html__( 'Install MonsterInsights', 'wpforms-lite' ); $step['button_class'] = ''; $step['button_action'] = 'install'; $step['plugin'] = $this->config['lite_download_url']; } else { $this->output_data['plugin_activated'] = is_plugin_active( $this->config['lite_plugin'] ) || is_plugin_active( $this->config['pro_plugin'] ); $step['icon'] = $this->output_data['plugin_activated'] ? 'step-complete.svg' : 'step-1.svg'; $step['button_text'] = $this->output_data['plugin_activated'] ? esc_html__( 'MonsterInsights Installed & Activated', 'wpforms-lite' ) : esc_html__( 'Activate MonsterInsights', 'wpforms-lite' ); $step['button_class'] = $this->output_data['plugin_activated'] ? 'grey disabled' : ''; $step['button_action'] = $this->output_data['plugin_activated'] ? '' : 'activate'; $step['plugin'] = $this->output_data['pro_plugin_installed'] ? $this->config['pro_plugin'] : $this->config['lite_plugin']; } return $step; } /** * Step 'Setup' data. * * @since 1.5.7 * * @return array Step data. */ protected function get_data_step_setup() { $step = array(); $this->output_data['plugin_setup'] = false; if ( $this->output_data['plugin_activated'] ) { $this->output_data['plugin_setup'] = '' !== (string) \monsterinsights_get_ua(); } $step['icon'] = 'step-2.svg'; $step['section_class'] = $this->output_data['plugin_activated'] ? '' : 'grey'; $step['button_text'] = esc_html__( 'Run Setup Wizard', 'wpforms-lite' ); $step['button_class'] = 'grey disabled'; if ( $this->output_data['plugin_setup'] ) { $step['icon'] = 'step-complete.svg'; $step['section_class'] = ''; $step['button_text'] = esc_html__( 'Setup Complete', 'wpforms-lite' ); } else { $step['button_class'] = $this->output_data['plugin_activated'] ? '' : 'grey disabled'; } return $step; } /** * Step 'Addon' data. * * @since 1.5.7 * * @return array Step data. */ protected function get_data_step_addon() { $step = array(); $step['icon'] = 'step-3.svg'; $step['section_class'] = $this->output_data['plugin_setup'] ? '' : 'grey'; $step['button_text'] = esc_html__( 'Learn More', 'wpforms-lite' ); $step['button_class'] = 'grey disabled'; $step['button_url'] = ''; $plugin_license_level = false; if ( $this->output_data['plugin_activated'] ) { $mi = \MonsterInsights(); $plugin_license_level = 'lite'; if ( is_object( $mi->license ) && method_exists( $mi->license, 'license_can' ) ) { $plugin_license_level = $mi->license->license_can( 'plus' ) ? 'lite' : $plugin_license_level; $plugin_license_level = $mi->license->license_can( 'pro' ) || $mi->license->license_can( 'agency' ) ? 'pro' : $plugin_license_level; } } switch ( $plugin_license_level ) { case 'lite': $step['button_url'] = $this->config['mi_forms_addon_page']; $step['button_class'] = ''; break; case 'pro': $addon_installed = array_key_exists( $this->config['forms_addon'], $this->output_data['all_plugins'] ); $step['button_text'] = $addon_installed ? esc_html__( 'Activate Now', 'wpforms-lite' ) : esc_html__( 'Install Now', 'wpforms-lite' ); $step['button_url'] = admin_url( $this->config['mi_addons'] ); $step['button_class'] = ''; break; } return $step; } /** * Ajax endpoint. Check plugin setup status. * Used to properly init step 2 section after completing step 1. * * @since 1.5.7 */ public function ajax_check_plugin_status() { // Security checks. if ( ! check_ajax_referer( 'wpforms-admin', 'nonce', false ) || ! wpforms_current_user_can() ) { wp_send_json_error( array( 'error' => esc_html__( 'You do not have permission.', 'wpforms-lite' ), ) ); } $result = array(); if ( ! function_exists( 'MonsterInsights' ) || ! function_exists( 'monsterinsights_get_ua' ) ) { wp_send_json_error( array( 'error' => esc_html__( 'Plugin unavailable.', 'wpforms-lite' ), ) ); } $result['setup_status'] = (int) ( '' !== (string) \monsterinsights_get_ua() ); $mi = \MonsterInsights(); $result['license_level'] = 'lite'; $result['step3_button_url'] = $this->config['mi_forms_addon_page']; if ( is_object( $mi->license ) && method_exists( $mi->license, 'license_can' ) ) { $result['license_level'] = $mi->license->license_can( 'pro' ) || $mi->license->license_can( 'agency' ) ? 'pro' : $result['license_level']; $result['step3_button_url'] = admin_url( $this->config['mi_addons'] ); } $result['addon_installed'] = (int) array_key_exists( $this->config['forms_addon'], get_plugins() ); wp_send_json_success( $result ); } /** * Redirect to MI forms reporting page. * We need this function because `is_plugin_active()` available only after `admin_init` action. * * @since 1.5.7 */ public function redirect_to_mi_forms() { require_once ABSPATH . 'wp-admin/includes/plugin.php'; // Redirect to MI Forms addon if it is activated. if ( is_plugin_active( $this->config['forms_addon'] ) ) { wp_safe_redirect( admin_url( $this->config['mi_forms'] ) ); exit; } } } Admin/Challenge.php000066600000054036152141020640010176 0ustar00hooks(); } } /** * Hooks. * * @since 1.5.0 */ public function hooks() { \add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) ); \add_action( 'wpforms_builder_init', array( $this, 'start_challenge' ) ); \add_action( 'admin_footer', array( $this, 'challenge_html' ) ); \add_action( 'wpforms_welcome_intro_after', array( $this, 'welcome_html' ) ); \add_action( 'wp_ajax_wpforms_challenge_embed_page_url', array( $this, 'get_embed_page_url_ajax' ) ); \add_action( 'wp_ajax_wpforms_challenge_save_option', array( $this, 'save_challenge_option_ajax' ) ); \add_action( 'wp_ajax_wpforms_challenge_send_contact_form', array( $this, 'send_contact_form_ajax' ) ); } /** * Check if the current page is related to Challenge. * * @since 1.5.0 */ public function is_challenge_page() { return \wpforms_is_admin_page() || $this->is_builder_page() || $this->is_form_embed_page(); } /** * Check if the current page is a forms builder page related to Challenge. * * @since 1.5.0 */ public function is_builder_page() { if ( ! \wpforms_is_admin_page( 'builder' ) ) { return false; } if ( ! $this->challenge_active() ) { return false; } $step = \absint( $this->get_challenge_option( 'step' ) ); $form_id = \absint( $this->get_challenge_option( 'form_id' ) ); if ( $form_id && $step < 2 ) { return false; } $current_form_id = isset( $_GET['form_id'] ) ? \absint( $_GET['form_id'] ) : 0; $is_new_form = isset( $_GET['newform'] ) ? \absint( $_GET['newform'] ) : 0; if ( $is_new_form && 2 !== $step ) { return false; } if ( ! $is_new_form && $form_id !== $current_form_id && $step >= 2 ) { return false; } return true; } /** * Check if the current page is a form embed page edit related to Challenge. * * @since 1.5.0 */ public function is_form_embed_page() { if ( ! \is_admin() || ! \is_user_logged_in() ) { return false; } $screen = \get_current_screen(); if ( ! isset( $screen->id ) || 'page' !== $screen->id ) { return false; } if ( ! $this->challenge_active() ) { return false; } $step = $this->get_challenge_option( 'step' ); if ( ! \in_array( $step, array( 4, 5 ), true ) ) { return false; } $embed_page = $this->get_challenge_option( 'embed_page' ); if ( isset( $screen->action ) && 'add' === $screen->action && 0 === $embed_page ) { return true; } if ( isset( $_GET['post'] ) && $embed_page === \absint( $_GET['post'] ) ) { return true; } return false; } /** * Load scripts and styles. * * @since 1.5.0 */ public function enqueue_scripts() { if ( $this->challenge_finished() ) { return; } $min = \wpforms_get_min_suffix(); if ( $this->is_challenge_page() ) { \wp_enqueue_style( 'wpforms-challenge', \WPFORMS_PLUGIN_URL . "assets/css/challenge{$min}.css", array(), \WPFORMS_VERSION ); \wp_enqueue_script( 'wpforms-challenge-admin', \WPFORMS_PLUGIN_URL . "assets/js/components/admin/challenge/challenge-admin{$min}.js", array( 'jquery' ), \WPFORMS_VERSION, true ); \wp_localize_script( 'wpforms-challenge-admin', 'wpforms_challenge_admin', array( 'nonce' => \wp_create_nonce( 'wpforms_challenge_ajax_nonce' ), 'minutes_left' => \absint( $this->minutes ), ) ); } if ( $this->is_builder_page() || $this->is_form_embed_page() ) { \wp_enqueue_style( 'tooltipster', \WPFORMS_PLUGIN_URL . 'assets/css/tooltipster.css', null, '4.2.6' ); \wp_enqueue_script( 'tooltipster', \WPFORMS_PLUGIN_URL . 'assets/js/jquery.tooltipster.min.js', array( 'jquery' ), '4.2.6', true ); \wp_enqueue_script( 'wpforms-challenge-core', \WPFORMS_PLUGIN_URL . "assets/js/components/admin/challenge/challenge-core{$min}.js", array( 'jquery', 'tooltipster', 'wpforms-challenge-admin' ), \WPFORMS_VERSION, true ); } if ( $this->is_builder_page() ) { \wp_enqueue_script( 'wpforms-challenge-builder', \WPFORMS_PLUGIN_URL . "assets/js/components/admin/challenge/challenge-builder{$min}.js", array( 'jquery', 'tooltipster', 'wpforms-challenge-core' ), \WPFORMS_VERSION, true ); } if ( $this->is_form_embed_page() ) { \wp_enqueue_style( 'wpforms-font-awesome', \WPFORMS_PLUGIN_URL . 'assets/css/font-awesome.min.css', null, '4.7.0' ); \wp_enqueue_script( 'wpforms-challenge-embed', \WPFORMS_PLUGIN_URL . "assets/js/components/admin/challenge/challenge-embed{$min}.js", array( 'jquery', 'tooltipster', 'wpforms-challenge-core' ), \WPFORMS_VERSION, true ); } } /** * Get 'wpforms_challenge' option schema. * * @since 1.5.0 */ public function get_challenge_option_schema() { return array( 'status' => '', 'step' => 0, 'user_id' => \get_current_user_id(), 'form_id' => 0, 'embed_page' => 0, 'started_date_gmt' => '', 'finished_date_gmt' => '', 'seconds_spent' => 0, 'seconds_left' => 0, 'feedback_sent' => false, 'feedback_contact_me' => false, ); } /** * Get Challenge parameter(s) from Challenge option. * * @since 1.5.0 * * @param array|string|null $query Query using 'wpforms_challenge' schema keys. * * @return array|mixed */ public function get_challenge_option( $query = null ) { if ( ! $query ) { return \get_option( 'wpforms_challenge' ); } if ( ! \is_array( $query ) ) { $return_single = true; $query = array( $query ); } $query = \array_flip( $query ); $option = \get_option( 'wpforms_challenge' ); if ( ! $option || ! \is_array( $option ) ) { return \array_intersect_key( $this->get_challenge_option_schema(), $query ); } $result = \array_intersect_key( $option, $query ); if ( $return_single ) { $result = \reset( $result ); } return $result; } /** * Set Challenge parameter(s) to Challenge option. * * @since 1.5.0 * * @param array $query Query using 'wpforms_challenge' schema keys. */ public function set_challenge_option( $query ) { if ( empty( $query ) || ! \is_array( $query ) ) { return; } $schema = $this->get_challenge_option_schema(); $replace = \array_intersect_key( $query, $schema ); if ( ! $replace ) { return; } // Validate and sanitize the data. foreach ( $replace as $key => $value ) { if ( \in_array( $key, array( 'step', 'user_id', 'form_id', 'embed_page', 'seconds_spent', 'seconds_left' ), true ) ) { $replace[ $key ] = \absint( $value ); continue; } if ( \in_array( $key, array( 'feedback_sent', 'feedback_contact_me' ), true ) ) { $replace[ $key ] = \wp_validate_boolean( $value ); continue; } $replace[ $key ] = \sanitize_text_field( $value ); } $option = \get_option( 'wpforms_challenge' ); if ( ! $option || ! \is_array( $option ) ) { \update_option( 'wpforms_challenge', \array_merge( $schema, $replace ) ); return; } \update_option( 'wpforms_challenge', \array_merge( $option, $replace ) ); } /** * Check if any forms are present on a site. * * @since 1.5.0 */ public function website_has_forms() { return (bool) \wpforms()->form->get( '', array( 'numberposts' => 1 ) ); } /** * Check if Challenge was started. * * @since 1.5.0 */ public function challenge_started() { return 'started' === $this->get_challenge_option( 'status' ); } /** * Check if Challenge was finished. * * @since 1.5.0 */ public function challenge_finished() { $status = $this->get_challenge_option( 'status' ); return \in_array( $status, array( 'completed', 'canceled', 'skipped' ), true ); } /** * Check if Challenge is in progress. * * @since 1.5.0 */ public function challenge_active() { return $this->challenge_started() && ! $this->challenge_finished(); } /** * Check if Challenge can be started. * * @since 1.5.0 */ public function challenge_can_start() { if ( $this->website_has_forms() ) { return false; } if ( $this->challenge_started() || $this->challenge_finished() ) { return false; } return true; } /** * Start the Challenge in Form Builder. * * @since 1.5.0 */ public function start_challenge() { if ( ! isset( $_GET['challenge'] ) || 'start' !== $_GET['challenge'] ) { return; } if ( ! $this->challenge_can_start() ) { return; } $this->set_challenge_option( array( 'status' => 'started', 'started_date_gmt' => \current_time( 'mysql', true ), ) ); \wp_safe_redirect( \remove_query_arg( 'challenge' ) ); } /** * Include Challenge HTML. * * @since 1.5.0 */ public function challenge_html() { if ( $this->challenge_finished() ) { return; } if ( \wpforms_is_admin_page() && ! \wpforms_is_admin_page( 'getting-started' ) && $this->challenge_can_start() ) { $this->challenge_modal_html( 'start' ); } if ( $this->is_builder_page() ) { $this->challenge_modal_html( 'progress' ); $this->challenge_builder_templates_html(); } if ( $this->is_form_embed_page() ) { $this->challenge_modal_html( 'progress' ); $this->challenge_embed_templates_html(); } } /** * Include Challenge main modal window HTML. * * @since 1.5.0 * * @param string $state State of Challenge ('start' or 'progress'). */ public function challenge_modal_html( $state ) { ?>

WPForms Challenge and get up and running within %1$d %2$s.', 'wpforms-lite' ), \absint( $this->minutes ), \_n( 'minute', 'minutes', \absint( $this->minutes ), 'wpforms-lite' ) ), array( 'b' => array() ) ); ?>

<?php \esc_html_e( 'Sullie the WPForms mascot', 'wpforms-lite' ); ?>

' . \absint( $this->minutes ) .':00' ); ?>

%1$s %2$s %3$s %4$s. Share your success story with other WPForms users and help us spread the word by giving WPForms a 5-star rating (%5$s) on WordPress.org. Thanks for your support and we look forward to bringing more awesome features.', 'wpforms-lite' ), '', \_n( 'minute', 'minutes', \absint( $this->minutes ), 'wpforms-lite' ), '', \_n( 'second', 'seconds', \absint( $this->minutes ), 'wpforms-lite' ), '' ), array( 'span' => array( 'id' => array(), 'class' => array(), ), 'b' => array(), 'i' => array( 'class' => array(), ), ) ); ?>

minutes ), \_n( 'minute', 'minutes', \absint( $this->minutes ), 'wpforms-lite' ) ) ); ?>

challenge_finished() ) { return; } ?>

get_var( "SELECT ID FROM $wpdb->posts WHERE post_type = 'page' AND post_name LIKE '%contact%';" ) ); if ( $page_id ) { $url = \get_edit_post_link( $page_id, '' ); $this->set_challenge_option( array( 'embed_page' => $page_id ) ); } else { $url = \add_query_arg( 'post_type', 'page', \admin_url( 'post-new.php' ) ); $this->set_challenge_option( array( 'embed_page' => 0 ) ); } \wp_send_json_success( $url ); } /** * Save Challenge data via AJAX. * * @since 1.5.0 */ public function save_challenge_option_ajax() { \check_admin_referer( 'wpforms_challenge_ajax_nonce' ); if ( empty( $_POST['option_data'] ) ) { \wp_send_json_error(); } $schema = $this->get_challenge_option_schema(); foreach ( $schema as $key => $value ) { if ( ! empty( $_POST['option_data'][ $key ] ) ) { $query[ $key ] = \sanitize_text_field( \wp_unslash( $_POST['option_data'][ $key ] ) ); } } if ( empty( $query ) ) { \wp_send_json_error(); } if ( ! empty( $query['status'] ) && \in_array( $query['status'], array( 'completed', 'canceled', 'skipped' ), true ) ) { $query['finished_date_gmt'] = \current_time( 'mysql', true ); } if ( ! empty( $query['status'] ) && 'skipped' === $query['status'] ) { $query['started_date_gmt'] = \current_time( 'mysql', true ); $query['finished_date_gmt'] = $query['started_date_gmt']; } $this->set_challenge_option( $query ); \wp_send_json_success(); } /** * Send contact form to wpforms.com via AJAX. * * @since 1.5.0 */ public function send_contact_form_ajax() { \check_admin_referer( 'wpforms_challenge_ajax_nonce' ); $url = 'https://wpforms.com/wpforms-challenge-feedback/'; $message = ! empty( $_POST['contact_data']['message'] ) ? \sanitize_textarea_field( \wp_unslash( $_POST['contact_data']['message'] ) ) : ''; $email = ''; if ( ! empty( $_POST['contact_data']['contact_me'] ) && 'true' === $_POST['contact_data']['contact_me'] ) { $current_user = \wp_get_current_user(); $email = $current_user->user_email; $this->set_challenge_option( array( 'feedback_contact_me' => true ) ); } if ( empty( $message ) && empty( $email ) ) { \wp_send_json_error(); } $data = array( 'body' => array( 'wpforms' => array( 'id' => 296355, 'submit' => 'wpforms-submit', 'fields' => array( 2 => $message, 3 => $email, ), ), ), ); $response = \wp_remote_post( $url, $data ); if ( \is_wp_error( $response ) ) { \wp_send_json_error(); } $this->set_challenge_option( array( 'feedback_sent' => true ) ); \wp_send_json_success(); } } Admin/Loader.php000066600000003441152141020640007514 0ustar00register_class( $class_name ); } } /** * Register a new class. * * @since 1.5.0 * * @param string $class_name Class name to register. */ public function register_class( $class_name ) { $class_name = \sanitize_text_field( $class_name ); // Load Lite class if exists. if ( ! \wpforms()->pro && \class_exists( 'WPForms\Lite\Admin\\' . $class_name ) ) { $class_name = 'WPForms\Lite\Admin\\' . $class_name; new $class_name(); return; } // Load Pro class if exists. if ( \wpforms()->pro && \class_exists( 'WPForms\Pro\Admin\\' . $class_name ) ) { $class_name = 'WPForms\Pro\Admin\\' . $class_name; new $class_name(); return; } // Load general class if neither Pro nor Lite class exists. if ( \class_exists( __NAMESPACE__ . '\\' . $class_name ) ) { $class_name = __NAMESPACE__ . '\\' . $class_name; new $class_name(); } } } Admin/FlyoutMenu.php000066600000007416152141020640010423 0ustar00form->get( '', array( 'numberposts' => 1 ) ); if ( ! $forms_exists && ( empty( $challenge ) || ( ! empty( $challenge['status'] ) && ! \in_array( $challenge['status'], array( 'completed', 'canceled', 'skipped' ), true ) ) ) ) { return; } $this->hooks(); } /** * Hooks. * * @since 1.5.7 */ public function hooks() { \add_action( 'admin_footer', array( $this, 'output' ) ); } /** * Menu items data. * * @since 1.5.7 */ public function menu_items() { $is_pro = \wpforms()->pro; $utm_campaign = $is_pro ? 'plugin' : 'liteplugin'; $items = array( array( 'title' => \esc_html__( 'Upgrade to WPForms Pro', 'wpforms-lite' ), 'url' => \wpforms_admin_upgrade_link( 'flyout-menu' ), 'icon' => 'fa-star', 'bgcolor' => '#E1772F', 'hover_bgcolor' => '#ff8931', ), array( 'title' => \esc_html__( 'Support & Docs', 'wpforms-lite' ), 'url' => 'https://wpforms.com/docs/?utm_source=WordPress&utm_medium=Flyout Menu&utm_campaign=' . $utm_campaign . '&utm_content=Support', 'icon' => 'fa-life-ring', ), array( 'title' => \esc_html__( 'Join Our Community', 'wpforms-lite' ), 'url' => 'https://www.facebook.com/groups/wpformsvip/', 'icon' => 'fa-comments', ), array( 'title' => \esc_html__( 'Suggest a Feature', 'wpforms-lite' ), 'url' => 'https://wpforms.com/features/suggest/?utm_source=WordPress&utm_medium=Flyout Menu&utm_campaign=' . $utm_campaign . '&utm_content=Feature', 'icon' => 'fa-lightbulb-o', ), ); if ( $is_pro ) { array_shift( $items ); } return \apply_filters( 'wpforms_admin_flyout_menu_items', $items ); } /** * Output menu. * * @since 1.5.7 */ public function output() { printf( '
%1$s
%2$s
%2$s
', $this->get_items_html(), // phpcs:ignore \esc_attr__( 'See Quick Links', 'wpforms-lite' ), \esc_url( \WPFORMS_PLUGIN_URL . 'assets/images/admin-flyout-menu/sullie-default.svg' ), \esc_url( \WPFORMS_PLUGIN_URL . 'assets/images/admin-flyout-menu/sullie-active.svg' ) ); } /** * Generate menu items HTML. * * @since 1.5.7 * * @return string Menu items HTML. */ public function get_items_html() { $items = array_reverse( $this->menu_items() ); $items_html = ''; foreach ( $items as $item_key => $item ) { $items_html .= sprintf( '
%3$s
', \esc_url( $item['url'] ), (int) $item_key, \esc_html( $item['title'] ), \sanitize_html_class( $item['icon'] ), ! empty( $item['bgcolor'] ) ? ' style="background-color: ' . \esc_attr( $item['bgcolor'] ) . '"' : '', ! empty( $item['hover_bgcolor'] ) ? ' onMouseOver="this.style.backgroundColor=\'' . \esc_attr( $item['hover_bgcolor'] ) . '\'" onMouseOut="this.style.backgroundColor=\'' . \esc_attr( $item['bgcolor'] ) . '\'"' : '' ); } return $items_html; } } Admin/Notifications.php000066600000026735152141020640011132 0ustar00hooks(); } /** * Register hooks. * * @since 1.6.0 */ public function hooks() { add_action( 'wpforms_overview_enqueue', [ $this, 'enqueues' ] ); add_action( 'wpforms_admin_overview_before_table', [ $this, 'output' ] ); add_action( 'wpforms_admin_notifications_update', [ $this, 'update' ] ); add_action( 'wp_ajax_wpforms_notification_dismiss', [ $this, 'dismiss' ] ); } /** * Check if user has access and is enabled. * * @since 1.6.0 * * @return bool */ public function has_access() { $access = false; if ( wpforms_current_user_can( 'view_forms' ) && ! wpforms_setting( 'hide-announcements', false ) ) { $access = true; } return apply_filters( 'wpforms_admin_notifications_has_access', $access ); } /** * Get option value. * * @since 1.6.0 * * @param bool $cache Reference property cache if available. * * @return array */ public function get_option( $cache = true ) { if ( $this->option && $cache ) { return $this->option; } $option = get_option( 'wpforms_notifications', [] ); $this->option = [ 'update' => ! empty( $option['update'] ) ? $option['update'] : 0, 'events' => ! empty( $option['events'] ) ? $option['events'] : [], 'feed' => ! empty( $option['feed'] ) ? $option['feed'] : [], 'dismissed' => ! empty( $option['dismissed'] ) ? $option['dismissed'] : [], ]; return $this->option; } /** * Fetch notifications from feed. * * @since 1.6.0 * * @return array */ public function fetch_feed() { $res = wp_remote_get( self::SOURCE_URL ); if ( is_wp_error( $res ) ) { return []; } $body = wp_remote_retrieve_body( $res ); if ( empty( $body ) ) { return []; } return $this->verify( json_decode( $body, true ) ); } /** * Verify notification data before it is saved. * * @since 1.6.0 * * @param array $notifications Array of notifications items to verify. * * @return array */ public function verify( $notifications ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh $data = []; if ( ! is_array( $notifications ) || empty( $notifications ) ) { return $data; } $option = $this->get_option(); foreach ( $notifications as $notification ) { // The message and license should never be empty, if they are, ignore. if ( empty( $notification['content'] ) || empty( $notification['type'] ) ) { continue; } // Ignore if license type does not match. $license = wpforms_get_license_type() ? wpforms_get_license_type() : 'lite'; if ( ! in_array( $license, $notification['type'], true ) ) { continue; } // Ignore if expired. if ( ! empty( $notification['end'] ) && time() > strtotime( $notification['end'] ) ) { continue; } // Ignore if notifcation has already been dismissed. if ( ! empty( $option['dismissed'] ) && in_array( $notification['id'], $option['dismissed'] ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict continue; } // Ignore if notification existed before installing WPForms. // Prevents bombarding the user with notifications after activation. $activated = wpforms_get_activated_timestamp(); if ( ! empty( $activated ) && ! empty( $notification['start'] ) && $activated > strtotime( $notification['start'] ) ) { continue; } $data[] = $notification; } return $data; } /** * Verify saved notification data for active notifications. * * @since 1.6.0 * * @param array $notifications Array of notifications items to verify. * * @return array */ public function verify_active( $notifications ) { if ( ! is_array( $notifications ) || empty( $notifications ) ) { return []; } // Remove notfications that are not active. foreach ( $notifications as $key => $notification ) { if ( ( ! empty( $notification['start'] ) && time() < strtotime( $notification['start'] ) ) || ( ! empty( $notification['end'] ) && time() > strtotime( $notification['end'] ) ) ) { unset( $notifications[ $key ] ); } } return $notifications; } /** * Get notification data. * * @since 1.6.0 * * @return array */ public function get() { if ( ! $this->has_access() ) { return []; } $option = $this->get_option(); // Update notifications using async task. if ( empty( $option['update'] ) || time() > $option['update'] + DAY_IN_SECONDS ) { if ( empty( wpforms()->get( 'tasks' )->is_scheduled( 'wpforms_admin_notifications_update' ) ) ) { wpforms()->get( 'tasks' ) ->create( 'wpforms_admin_notifications_update' ) ->async() ->params() ->register(); } } $events = ! empty( $option['events'] ) ? $this->verify_active( $option['events'] ) : []; $feed = ! empty( $option['feed'] ) ? $this->verify_active( $option['feed'] ) : []; return array_merge( $events, $feed ); } /** * Get notification count. * * @since 1.6.0 * * @return int */ public function get_count() { return count( $this->get() ); } /** * Add a manual notification event. * * @since 1.6.0 * * @param array $notification Notification data. */ public function add( $notification ) { if ( empty( $notification['id'] ) ) { return; } $option = $this->get_option(); if ( in_array( $notification['id'], $option['dismissed'] ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict return; } foreach ( $option['events'] as $item ) { if ( $item['id'] === $notification['id'] ) { return; } } $notification = $this->verify( [ $notification ] ); update_option( 'wpforms_notifications', [ 'update' => $option['update'], 'feed' => $option['feed'], 'events' => array_merge( $notification, $option['events'] ), 'dismissed' => $option['dismissed'], ] ); } /** * Update notification data from feed. * * @since 1.6.0 */ public function update() { $feed = $this->fetch_feed(); $option = $this->get_option(); update_option( 'wpforms_notifications', [ 'update' => time(), 'feed' => $feed, 'events' => $option['events'], 'dismissed' => $option['dismissed'], ] ); } /** * Admin area Form Overview enqueues. * * @since 1.6.0 */ public function enqueues() { if ( ! $this->has_access() ) { return; } $notifications = $this->get(); if ( empty( $notifications ) ) { return; } $min = wpforms_get_min_suffix(); wp_enqueue_style( 'wpforms-admin-notifications', WPFORMS_PLUGIN_URL . "assets/css/admin-notifications{$min}.css", [], WPFORMS_VERSION ); wp_enqueue_script( 'wpforms-admin-notifications', WPFORMS_PLUGIN_URL . "assets/js/admin-notifications{$min}.js", [ 'jquery' ], WPFORMS_VERSION, true ); } /** * Output notifications on Form Overview admin area. * * @since 1.6.0 */ public function output() { $notifications = $this->get(); if ( empty( $notifications ) ) { return; } $notifications_html = ''; $current_class = ' current'; $content_allowed_tags = [ 'em' => [], 'strong' => [], 'span' => [ 'style' => [], ], 'a' => [ 'href' => [], 'target' => [], 'rel' => [], ], ]; foreach ( $notifications as $notification ) { // Buttons HTML. $buttons_html = ''; if ( ! empty( $notification['btns'] ) && is_array( $notification['btns'] ) ) { foreach ( $notification['btns'] as $btn_type => $btn ) { $buttons_html .= sprintf( '%4$s', ! empty( $btn['url'] ) ? esc_url( $btn['url'] ) : '', $btn_type === 'main' ? 'primary' : 'secondary', ! empty( $btn['target'] ) && $btn['target'] === '_blank' ? ' target="_blank" rel="noopener noreferrer"' : '', ! empty( $btn['text'] ) ? sanitize_text_field( $btn['text'] ) : '' ); } $buttons_html = ! empty( $buttons_html ) ? '
' . $buttons_html . '
' : ''; } // Notification HTML. $notifications_html .= sprintf( '

%1$s

%2$s

%3$s
', ! empty( $notification['title'] ) ? sanitize_text_field( $notification['title'] ) : '', ! empty( $notification['content'] ) ? wp_kses( $notification['content'], $content_allowed_tags ) : '', $buttons_html, ! empty( $notification['id'] ) ? esc_attr( sanitize_text_field( $notification['id'] ) ) : 0, $current_class ); // Only first notification is current. $current_class = ''; } ?>
has_access() || empty( $_POST['id'] ) ) { wp_send_json_error(); } $id = sanitize_text_field( wp_unslash( $_POST['id'] ) ); $option = $this->get_option(); $type = is_numeric( $id ) ? 'feed' : 'events'; $option['dismissed'][] = $id; $option['dismissed'] = array_unique( $option['dismissed'] ); // Remove notification. if ( is_array( $option[ $type ] ) && ! empty( $option[ $type ] ) ) { foreach ( $option[ $type ] as $key => $notification ) { if ( $notification['id'] == $id ) { // phpcs:ignore WordPress.PHP.StrictComparisons unset( $option[ $type ][ $key ] ); break; } } } update_option( 'wpforms_notifications', $option ); wp_send_json_success(); } } Admin/AdminBarMenu.php000066600000015134152141020640010612 0ustar00hooks(); } /** * Register hooks. * * @since 1.6.0 */ public function hooks() { add_action( 'wp_enqueue_scripts', [ $this, 'enqueues' ] ); add_action( 'admin_enqueue_scripts', [ $this, 'enqueues' ] ); add_action( 'admin_bar_menu', [ $this, 'register' ], 999 ); } /** * Check if current user has access to see admin bar menu. * * @since 1.6.0 * * @return bool */ public function has_access() { $access = false; if ( is_user_logged_in() && wpforms_current_user_can() && ! wpforms_setting( 'hide-admin-bar', false ) ) { $access = true; } return apply_filters( 'wpforms_admin_adminbarmenu_has_access', $access ); } /** * Check if new notifications are available. * * @since 1.6.0 * * @return bool */ public function has_notifications() { return wpforms()->get( 'notifications' )->get_count(); } /** * Enqueue styles. * * @since 1.6.0 */ public function enqueues() { if ( ! $this->has_access() ) { return; } $min = wpforms_get_min_suffix(); wp_enqueue_style( 'wpforms-admin-bar', WPFORMS_PLUGIN_URL . "assets/css/admin-bar{$min}.css", [], WPFORMS_VERSION ); } /** * Register and render admin menu bar items. * * @since 1.6.0 * * @param \WP_Admin_Bar $wp_admin_bar WordPress Admin Bar object. */ public function register( \WP_Admin_Bar $wp_admin_bar ) { if ( ! $this->has_access() ) { return; } $items = apply_filters( 'wpforms_admin_adminbarmenu_register', [ 'main_menu', 'notification_menu', 'forms_menu', 'all_forms_menu', 'add_new_menu', 'community_menu', 'support_menu', ], $wp_admin_bar ); foreach ( $items as $item ) { $this->{ $item }( $wp_admin_bar ); do_action( "wpforms_admin_adminbarmenu_register_{$item}_after", $wp_admin_bar ); } } /** * Render primary top-level admin menu bar item. * * @since 1.6.0 * * @param \WP_Admin_Bar $wp_admin_bar WordPress Admin Bar object. */ public function main_menu( \WP_Admin_Bar $wp_admin_bar ) { $indicator = ''; if ( $this->has_notifications() ) { $count = $this->has_notifications() < 10 ? $this->has_notifications() : '!'; $indicator = '
' . $count . '
'; } $wp_admin_bar->add_menu( [ 'id' => 'wpforms-menu', 'title' => 'WPForms' . $indicator, 'href' => admin_url( 'admin.php?page=wpforms-overview' ), ] ); } /** * Render Notifications admin menu bar item. * * @since 1.6.0 * * @param \WP_Admin_Bar $wp_admin_bar WordPress Admin Bar object. */ public function notification_menu( \WP_Admin_Bar $wp_admin_bar ) { if ( ! $this->has_notifications() ) { return; } $wp_admin_bar->add_menu( [ 'parent' => 'wpforms-menu', 'id' => 'wpforms-notifications', 'title' => __( 'Notifications', 'wpforms-lite' ) . '
', 'href' => admin_url( 'admin.php?page=wpforms-overview' ), ] ); } /** * Render individual forms admin menu bar items and sub-items. * * @since 1.6.0 * * @param \WP_Admin_Bar $wp_admin_bar WordPress Admin Bar object. */ public function forms_menu( \WP_Admin_Bar $wp_admin_bar ) { if ( is_admin() ) { return; } $forms = wpforms()->frontend->forms; $x = 0; if ( empty( $forms ) ) { return; } foreach ( $forms as $form ) { $x++; $form_id = absint( $form['id'] ); $class = 'wpforms-menu-form'; $this->displaying_forms = true; if ( $this->has_notifications() && $x === 1 ) { $class .= ' wpforms-menu-form-notifications'; } if ( $x === count( $forms ) ) { $class .= ' wpforms-menu-form-last'; } // Shrink the long form title. $form_title = sanitize_text_field( $form['settings']['form_title'] ); $form_title = mb_strlen( $form_title ) > 99 ? mb_substr( $form_title, 0, 99 ) . '…' : $form_title; $wp_admin_bar->add_menu( [ 'parent' => 'wpforms-menu', 'id' => 'wpforms-form-id-' . $form_id, 'title' => $form_title, 'href' => '#wpforms-' . $form_id, 'meta' => [ 'class' => $class, ], ] ); $wp_admin_bar->add_menu( [ 'parent' => 'wpforms-form-id-' . $form_id, 'id' => 'wpforms-edit-form-id-' . $form_id, 'title' => __( 'Edit Form', 'wpforms-lite' ), 'href' => admin_url( 'admin.php?page=wpforms-builder&view=fields&form_id=' . $form_id ), ] ); do_action( 'wpforms_admin_adminbarmenu_forms_menu_after', $wp_admin_bar, $form ); } } /** * Render All Forms admin menu bar item. * * @since 1.6.0 * * @param \WP_Admin_Bar $wp_admin_bar WordPress Admin Bar object. */ public function all_forms_menu( \WP_Admin_Bar $wp_admin_bar ) { $wp_admin_bar->add_menu( [ 'parent' => 'wpforms-menu', 'id' => 'wpforms-forms', 'title' => __( 'All Forms', 'wpforms-lite' ), 'href' => admin_url( 'admin.php?page=wpforms-overview' ), ] ); } /** * Render Add New admin menu bar item. * * @since 1.6.0 * * @param \WP_Admin_Bar $wp_admin_bar WordPress Admin Bar object. */ public function add_new_menu( \WP_Admin_Bar $wp_admin_bar ) { $wp_admin_bar->add_menu( [ 'parent' => 'wpforms-menu', 'id' => 'wpforms-add-new', 'title' => __( 'Add New', 'wpforms-lite' ), 'href' => admin_url( 'admin.php?page=wpforms-builder' ), ] ); } /** * Render Community admin menu bar item. * * @since 1.6.0 * * @param \WP_Admin_Bar $wp_admin_bar WordPress Admin Bar object. */ public function community_menu( \WP_Admin_Bar $wp_admin_bar ) { $wp_admin_bar->add_menu( [ 'parent' => 'wpforms-menu', 'id' => 'wpforms-community', 'title' => __( 'Community', 'wpforms-lite' ), 'href' => 'https://www.facebook.com/groups/wpformsvip/', 'meta' => [ 'target' => '_blank', 'rel' => 'noopener noreferrer', ], ] ); } /** * Render Support admin menu bar item. * * @since 1.6.0 * * @param \WP_Admin_Bar $wp_admin_bar WordPress Admin Bar object. */ public function support_menu( \WP_Admin_Bar $wp_admin_bar ) { $wp_admin_bar->add_menu( [ 'parent' => 'wpforms-menu', 'id' => 'wpforms-support', 'title' => __( 'Support', 'wpforms-lite' ), 'href' => 'https://wpforms.com/docs/', 'meta' => [ 'target' => '_blank', 'rel' => 'noopener noreferrer', ], ] ); } } Integrations/SiteHealth/SiteHealth.php000066600000006325152141020640014014 0ustar00=' ); } /** * Load an integration. * * @since 1.5.5 */ public function load() { $this->hooks(); } /** * Integration hooks. * * @since 1.5.5 */ protected function hooks() { add_filter( 'debug_information', array( $this, 'add_info_section' ) ); } /** * Add WPForms section to Info tab. * * @since 1.5.5 * * @param array $debug_info Array of all information. * * @return array Array with added WPForms info section. */ public function add_info_section( $debug_info ) { $wpforms = array( 'label' => 'WPForms', 'fields' => array( 'version' => array( 'label' => esc_html__( 'Version', 'wpforms-lite' ), 'value' => WPFORMS_VERSION, ), ), ); // License key type. $wpforms['fields']['license'] = array( 'label' => esc_html__( 'License key type', 'wpforms-lite' ), 'value' => wpforms_get_license_type(), ); // Install date. $activated = get_option( 'wpforms_activated', array() ); if ( ! empty( $activated['lite'] ) ) { $date = $activated['lite'] + ( get_option( 'gmt_offset' ) * 3600 ); $wpforms['fields']['lite'] = array( 'label' => esc_html__( 'Lite install date', 'wpforms-lite' ), 'value' => date_i18n( esc_html__( 'M j, Y @ g:ia' ), $date ), ); } if ( ! empty( $activated['pro'] ) ) { $date = $activated['pro'] + ( get_option( 'gmt_offset' ) * 3600 ); $wpforms['fields']['pro'] = array( 'label' => esc_html__( 'Pro install date', 'wpforms-lite' ), 'value' => date_i18n( esc_html__( 'M j, Y @ g:ia' ), $date ), ); } // DB tables. if ( wpforms()->pro ) { $db_tables = wpforms()->get( 'pro' )->get_existing_custom_tables(); $db_tables_str = empty( $db_tables ) ? esc_html__( 'Not found', 'wpforms-lite' ) : implode( ', ', $db_tables ); $wpforms['fields']['db_tables'] = array( 'label' => esc_html__( 'DB tables', 'wpforms-lite' ), 'value' => $db_tables_str, ); } // Total forms. $wpforms['fields']['total_forms'] = array( 'label' => esc_html__( 'Total forms', 'wpforms-lite' ), 'value' => wp_count_posts( 'wpforms' )->publish, ); // Total entries. if ( wpforms()->pro ) { $wpforms['fields']['total_entries'] = array( 'label' => esc_html__( 'Total entries', 'wpforms-lite' ), 'value' => wpforms()->entry->get_entries( array(), true ), ); } else { $forms = \wpforms()->form->get( '', array( 'fields' => 'ids' ) ); if ( empty( $forms ) || ! \is_array( $forms ) ) { $forms = array(); } $count = 0; foreach ( $forms as $form_id ) { $count += (int) \get_post_meta( $form_id, 'wpforms_entries_count', true ); } $wpforms['fields']['total_entries'] = array( 'label' => esc_html__( 'Total submissions (since v1.5.0)', 'wpforms-lite' ), 'value' => $count, ); } $debug_info['wpforms'] = $wpforms; return $debug_info; } } Integrations/WPMailSMTP/Notifications.php000066600000005145152141020640014375 0ustar00options = new \WPMailSMTP\Options(); $this->filters(); } /** * Integration filters. * * @since 1.4.8 */ protected function filters() { \add_filter( 'wpforms_builder_notifications_from_name_after', array( $this, 'from_name_after' ) ); \add_filter( 'wpforms_builder_notifications_from_email_after', array( $this, 'from_email_after' ) ); } /** * Display hint if WP Mail SMTP is forcing from name. * * @since 1.4.8 * * @param string $after Text displayed after setting. * * @return string */ public function from_name_after( $after ) { if ( ! $this->options->get( 'mail', 'from_name_force' ) ) { return $after; } return sprintf( \wp_kses( /* translators: %s - URL WP Mail SMTP settings. */ \__( 'This setting is disabled because you have the "Force From Name" setting enabled in WP Mail SMTP.', 'wpforms-lite' ), array( 'a' => array( 'href' => array(), 'rel' => array(), 'target' => array(), ), ) ), \esc_url( \admin_url( 'options-general.php?page=wp-mail-smtp#wp-mail-smtp-setting-row-from_name' ) ) ); } /** * Display hint if WP Mail SMTP is forcing from email. * * @since 1.4.8 * * @param string $after Text displayed after setting. * * @return string */ public function from_email_after( $after ) { if ( ! $this->options->get( 'mail', 'from_email_force' ) ) { return $after; } return sprintf( \wp_kses( /* translators: %s - URL WP Mail SMTP settings. */ \__( 'This setting is disabled because you have the "Force From Email" setting enabled in WP Mail SMTP.', 'wpforms-lite' ), array( 'a' => array( 'href' => array(), 'rel' => array(), 'target' => array(), ), ) ), \esc_url( \admin_url( 'options-general.php?page=wp-mail-smtp#wp-mail-smtp-setting-row-from_email' ) ) ); } } Integrations/Gutenberg/FormSelector.php000066600000014342152141020640014254 0ustar00hooks(); } /** * Integration hooks. * * @since 1.4.8 */ protected function hooks() { \add_action( 'init', array( $this, 'register_block' ) ); \add_action( 'enqueue_block_editor_assets', array( $this, 'enqueue_block_editor_assets' ) ); } /** * Register WPForms Gutenberg block on the backend. * * @since 1.4.8 */ public function register_block() { \wp_register_style( 'wpforms-gutenberg-form-selector', WPFORMS_PLUGIN_URL . 'assets/css/wpforms-full.css', array( 'wp-edit-blocks' ), WPFORMS_VERSION ); $attributes = array( 'formId' => array( 'type' => 'string', ), 'displayTitle' => array( 'type' => 'boolean', ), 'displayDesc' => array( 'type' => 'boolean', ), 'className' => array( 'type' => 'string', ), ); \register_block_type( 'wpforms/form-selector', array( 'attributes' => \apply_filters( 'wpforms_gutenberg_form_selector_attributes', $attributes ), 'editor_style' => 'wpforms-gutenberg-form-selector', 'render_callback' => array( $this, 'get_form_html' ), ) ); } /** * Load WPForms Gutenberg block scripts. * * @since 1.4.8 */ public function enqueue_block_editor_assets() { $i18n = array( 'title' => \esc_html__( 'WPForms', 'wpforms-lite' ), 'description' => \esc_html__( 'Select and display one of your forms.', 'wpforms-lite' ), 'form_keywords' => array( \esc_html__( 'form', 'wpforms-lite' ), \esc_html__( 'contact', 'wpforms-lite' ), \esc_html__( 'survey', 'wpforms-lite' ), ), 'form_select' => \esc_html__( 'Select a Form', 'wpforms-lite' ), 'form_settings' => \esc_html__( 'Form Settings', 'wpforms-lite' ), 'form_selected' => \esc_html__( 'Form', 'wpforms-lite' ), 'show_title' => \esc_html__( 'Show Title', 'wpforms-lite' ), 'show_description' => \esc_html__( 'Show Description', 'wpforms-lite' ), 'panel_notice_head' => \esc_html__( 'Heads up!', 'wpforms-lite' ), 'panel_notice_text' => \esc_html__( 'Do not forget to test your form.', 'wpforms-lite' ), 'panel_notice_link' => \esc_html__( 'Check out our complete guide!', 'wpforms-lite' ), ); \wp_enqueue_script( 'wpforms-gutenberg-form-selector', WPFORMS_PLUGIN_URL . 'assets/js/components/admin/gutenberg/formselector.min.js', array( 'wp-blocks', 'wp-i18n', 'wp-element' ), WPFORMS_VERSION, true ); $forms = \wpforms()->form->get( '', array( 'order' => 'DESC' ) ); $forms = ! empty( $forms ) ? $forms : array(); $forms = array_map( function( $form ) { $form->post_title = htmlspecialchars_decode( $form->post_title, ENT_QUOTES ); return $form; }, $forms ); \wp_localize_script( 'wpforms-gutenberg-form-selector', 'wpforms_gutenberg_form_selector', array( 'logo_url' => WPFORMS_PLUGIN_URL . 'assets/images/sullie-alt.png', 'wpnonce' => \wp_create_nonce( 'wpforms-gutenberg-form-selector' ), 'forms' => $forms, 'i18n' => $i18n, ) ); } /** * Get form HTML to display in a WPForms Gutenberg block. * * @param array $attr Attributes passed by WPForms Gutenberg block. * * @since 1.4.8 * * @return string */ public function get_form_html( $attr ) { $id = ! empty( $attr['formId'] ) ? \absint( $attr['formId'] ) : 0; if ( empty( $id ) ) { return ''; } $title = ! empty( $attr['displayTitle'] ) ? true : false; $desc = ! empty( $attr['displayDesc'] ) ? true : false; // Disable form fields if called from the Gutenberg editor. if ( $this->is_gb_editor() ) { \add_filter( 'wpforms_frontend_container_class', function ( $classes ) { $classes[] = 'wpforms-gutenberg-form-selector'; $classes[] = 'wpforms-container-full'; return $classes; } ); \add_action( 'wpforms_frontend_output', function () { echo '
'; }, 3 ); \add_action( 'wpforms_frontend_output', function () { echo '
'; }, 30 ); } if ( ! empty( $attr['className'] ) ) { \add_filter( 'wpforms_frontend_container_class', function ( $classes ) use ( $attr ) { $cls = array_map( 'esc_attr', explode( ' ', $attr['className'] ) ); return array_unique( array_merge( $classes, $cls ) ); } ); } \ob_start(); \do_action( 'wpforms_gutenberg_block_before' ); if ( $this->is_gb_editor() ) { wpforms_display( $id, apply_filters( 'wpforms_gutenberg_block_form_title', $title, $id ), apply_filters( 'wpforms_gutenberg_block_form_desc', $desc, $id ) ); } else { printf( '[wpforms id="%s" title="%d" description="%d"]', absint( $id ), // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped apply_filters( 'wpforms_gutenberg_block_form_title', $title, $id ), // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped apply_filters( 'wpforms_gutenberg_block_form_desc', $desc, $id ) // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ); } \do_action( 'wpforms_gutenberg_block_after' ); $content = \ob_get_clean(); if ( empty( $content ) ) { $content = '
' . \esc_html__( 'The form cannot be displayed.', 'wpforms-lite' ) . '
'; } return \apply_filters( 'wpforms_gutenberg_block_form_content', $content, $id ); } /** * Checking if is Gutenberg REST API call. * * @since 1.5.7 * * @return bool True if is Gutenberg REST API call. */ public function is_gb_editor() { // TODO: Find a better way to check if is GB editor API call. return \defined( 'REST_REQUEST' ) && REST_REQUEST && ! empty( $_REQUEST['context'] ) && 'edit' === $_REQUEST['context']; // phpcs:ignore } } Integrations/Elementor/Elementor.php000066600000003604152141020640013611 0ustar00hooks(); } /** * Integration hooks. * * @since 1.6.0 */ protected function hooks() { add_action( 'elementor/preview/init', [ $this, 'init' ] ); add_action( 'elementor/frontend/after_enqueue_scripts', [ $this, 'enqueue_assets' ] ); } /** * Init an integration logic. * * @since 1.6.0 */ public function init() { /** * Allow developers to determine if use or not this compatibility. * We make it on this place because we want that this filter will be available for theme developers too. * * @since 1.6.0 * * @param bool $use_compat */ $use_compat = apply_filters( 'wpforms_apply_elementor_preview_compat', true ); if ( true !== $use_compat ) { return; } // Load WPForms assets globally in Elementor Preview mode only. add_filter( 'wpforms_global_assets', '__return_true' ); } /** * Load an integration javascript. * * @since 1.6.0 */ public function enqueue_assets() { // Return, if no forms on Elementor page/popup. if ( empty( wpforms()->frontend->forms ) ) { return; } $min = wpforms_get_min_suffix(); wp_enqueue_script( 'wpforms-elementor', WPFORMS_PLUGIN_URL . "assets/js/integrations/wpforms-elementor{$min}.js", [ 'wpforms' ], WPFORMS_VERSION, true ); wp_localize_script( 'wpforms-elementor', 'wpformsElementorVars', [ 'recaptcha_type' => wpforms_setting( 'recaptcha-type', 'v2' ), ] ); } } Integrations/Loader.php000066600000004131152141020640011127 0ustar00register_class( $class_name ); if ( ! empty( $integration ) ) { $this->load_integration( $integration ); } } } /** * Load an integration. * * @param IntegrationInterface $integration Instance of an integration class. * * @since 1.4.8 */ protected function load_integration( IntegrationInterface $integration ) { if ( $integration->allow_load() ) { $integration->load(); } } /** * Register a new class. * * @since 1.5.6 * * @param string $class_name Class name to register. * * @return IntegrationInterface Instance of class. */ public function register_class( $class_name ) { $class_name = \sanitize_text_field( $class_name ); // Load Lite class if exists. if ( ! \wpforms()->pro && \class_exists( 'WPForms\Lite\Integrations\\' . $class_name ) ) { $class_name = 'WPForms\Lite\Integrations\\' . $class_name; return new $class_name(); } // Load Pro class if exists. if ( \wpforms()->pro && \class_exists( 'WPForms\Pro\Integrations\\' . $class_name ) ) { $class_name = 'WPForms\Pro\Integrations\\' . $class_name; return new $class_name(); } // Load general class if neither Pro nor Lite class exists. if ( \class_exists( __NAMESPACE__ . '\\' . $class_name ) ) { $class_name = __NAMESPACE__ . '\\' . $class_name; return new $class_name(); } } } Integrations/IntegrationInterface.php000066600000000642152141020640014030 0ustar00hooks(); } /** * General hooks. * * @since 1.5.9 */ private function hooks() { add_action( 'wpforms_loaded', array( $this, 'maybe_migrate' ), -9999 ); add_action( 'wpforms_loaded', array( $this, 'update_version' ), -9998 ); } /** * Run the migration if needed. * * @since 1.5.9 */ public function maybe_migrate() { if ( ! is_admin() ) { return; } // Retrieve the last known version. $version = get_option( self::OPTION_NAME ); if ( empty( $version ) ) { $version = '0.0.1'; } $this->migrate( $version ); } /** * Run the migrations for a specific version. * * @since 1.5.9 * * @param string $version Version to run the migrations for. */ private function migrate( $version ) { if ( version_compare( $version, '1.5.9', '<' ) ) { $this->v159_upgrade(); } } /** * If upgrade has occurred, update version options in database. * * @since 1.5.9 */ public function update_version() { if ( ! is_admin() ) { return; } if ( ! $this->is_migrated ) { return; } update_option( self::OPTION_NAME, WPFORMS_VERSION ); } /** * Do all the required migrations for WPForms v1.5.9. * * @since 1.5.9 */ private function v159_upgrade() { $meta = wpforms()->get( 'tasks_meta' ); // Create the table if it doesn't exist. if ( $meta && ! $meta->table_exists() ) { $meta->create_table(); } $this->is_migrated = true; } } Helpers/PluginSilentUpgraderSkin.php000066600000002224152141020640013612 0ustar00 '', // Please always pass this. 'destination' => '', // And this 'clear_destination' => false, 'abort_if_destination_exists' => true, // Abort if the Destination directory exists, Pass clear_destination as false please 'clear_working' => true, 'is_multi' => false, 'hook_extra' => array(), // Pass any extra $hook_extra args here, this will be passed to any hooked filters. ); $options = wp_parse_args( $options, $defaults ); /** * Filter the package options before running an update. * * See also {@see 'upgrader_process_complete'}. * * @since 4.3.0 * * @param array $options { * Options used by the upgrader. * * @type string $package Package for update. * @type string $destination Update location. * @type bool $clear_destination Clear the destination resource. * @type bool $clear_working Clear the working resource. * @type bool $abort_if_destination_exists Abort if the Destination directory exists. * @type bool $is_multi Whether the upgrader is running multiple times. * @type array $hook_extra { * Extra hook arguments. * * @type string $action Type of action. Default 'update'. * @type string $type Type of update process. Accepts 'plugin', 'theme', or 'core'. * @type bool $bulk Whether the update process is a bulk update. Default true. * @type string $plugin Path to the plugin file relative to the plugins directory. * @type string $theme The stylesheet or template name of the theme. * @type string $language_update_type The language pack update type. Accepts 'plugin', 'theme', * or 'core'. * @type object $language_update The language pack update offer. * } * } */ $options = apply_filters( 'upgrader_package_options', $options ); if ( ! $options['is_multi'] ) { // call $this->header separately if running multiple times $this->skin->header(); } // Connect to the Filesystem first. $res = $this->fs_connect( array( WP_CONTENT_DIR, $options['destination'] ) ); // Mainly for non-connected filesystem. if ( ! $res ) { if ( ! $options['is_multi'] ) { $this->skin->footer(); } return false; } $this->skin->before(); if ( is_wp_error( $res ) ) { $this->skin->error( $res ); $this->skin->after(); if ( ! $options['is_multi'] ) { $this->skin->footer(); } return $res; } /* * Download the package (Note, This just returns the filename * of the file if the package is a local file) */ $download = $this->download_package( $options['package'], true ); // Allow for signature soft-fail. // WARNING: This may be removed in the future. if ( is_wp_error( $download ) && $download->get_error_data( 'softfail-filename' ) ) { // Don't output the 'no signature could be found' failure message for now. if ( 'signature_verification_no_signature' != $download->get_error_code() || WP_DEBUG ) { // Outout the failure error as a normal feedback, and not as an error: //$this->skin->feedback( $download->get_error_message() ); // Report this failure back to WordPress.org for debugging purposes. wp_version_check( array( 'signature_failure_code' => $download->get_error_code(), 'signature_failure_data' => $download->get_error_data(), ) ); } // Pretend this error didn't happen. $download = $download->get_error_data( 'softfail-filename' ); } if ( is_wp_error( $download ) ) { $this->skin->error( $download ); $this->skin->after(); if ( ! $options['is_multi'] ) { $this->skin->footer(); } return $download; } $delete_package = ( $download != $options['package'] ); // Do not delete a "local" file // Unzips the file into a temporary directory. $working_dir = $this->unpack_package( $download, $delete_package ); if ( is_wp_error( $working_dir ) ) { $this->skin->error( $working_dir ); $this->skin->after(); if ( ! $options['is_multi'] ) { $this->skin->footer(); } return $working_dir; } // With the given options, this installs it to the destination directory. $result = $this->install_package( array( 'source' => $working_dir, 'destination' => $options['destination'], 'clear_destination' => $options['clear_destination'], 'abort_if_destination_exists' => $options['abort_if_destination_exists'], 'clear_working' => $options['clear_working'], 'hook_extra' => $options['hook_extra'], ) ); $this->skin->set_result( $result ); if ( is_wp_error( $result ) ) { $this->skin->error( $result ); //$this->skin->feedback( 'process_failed' ); } else { // Installation succeeded. //$this->skin->feedback( 'process_success' ); } $this->skin->after(); if ( ! $options['is_multi'] ) { /** * Fire when the upgrader process is complete. * * See also {@see 'upgrader_package_options'}. * * @since 3.6.0 * @since 3.7.0 Added to WP_Upgrader::run(). * @since 4.6.0 `$translations` was added as a possible argument to `$hook_extra`. * * @param WP_Upgrader $this WP_Upgrader instance. In other contexts, $this, might be a * Theme_Upgrader, Plugin_Upgrader, Core_Upgrade, or Language_Pack_Upgrader instance. * @param array $hook_extra { * Array of bulk item update data. * * @type string $action Type of action. Default 'update'. * @type string $type Type of update process. Accepts 'plugin', 'theme', 'translation', or 'core'. * @type bool $bulk Whether the update process is a bulk update. Default true. * @type array $plugins Array of the basename paths of the plugins' main files. * @type array $themes The theme slugs. * @type array $translations { * Array of translations update data. * * @type string $language The locale the translation is for. * @type string $type Type of translation. Accepts 'plugin', 'theme', or 'core'. * @type string $slug Text domain the translation is for. The slug of a theme/plugin or * 'default' for core translations. * @type string $version The version of a theme, plugin, or core. * } * } */ do_action( 'upgrader_process_complete', $this, $options['hook_extra'] ); $this->skin->footer(); } return $result; } /** * Toggle maintenance mode for the site. * * Create/delete the maintenance file to enable/disable maintenance mode. * * @since 2.8.0 * * @global WP_Filesystem_Base $wp_filesystem Subclass * * @param bool $enable True to enable maintenance mode, false to disable. */ public function maintenance_mode( $enable = false ) { global $wp_filesystem; $file = $wp_filesystem->abspath() . '.maintenance'; if ( $enable ) { //$this->skin->feedback( 'maintenance_start' ); // Create maintenance file to signal that we are upgrading $maintenance_string = ''; $wp_filesystem->delete( $file ); $wp_filesystem->put_contents( $file, $maintenance_string, FS_CHMOD_FILE ); } elseif ( ! $enable && $wp_filesystem->exists( $file ) ) { //$this->skin->feedback( 'maintenance_end' ); $wp_filesystem->delete( $file ); } } /** * Download a package. * * @since 2.8.0 * * @param string $package The URI of the package. If this is the full path to an * existing local file, it will be returned untouched. * @param bool $check_signatures Whether to validate file signatures. Default false. * @return string|WP_Error The full path to the downloaded package file, or a WP_Error object. */ public function download_package( $package, $check_signatures = false ) { /** * Filter whether to return the package. * * @since 3.7.0 * * @param bool $reply Whether to bail without returning the package. * Default false. * @param string $package The package file name. * @param WP_Upgrader $this The WP_Upgrader instance. */ $reply = apply_filters( 'upgrader_pre_download', false, $package, $this ); if ( false !== $reply ) { return $reply; } if ( ! preg_match( '!^(http|https|ftp)://!i', $package ) && file_exists( $package ) ) { //Local file or remote? return $package; //must be a local file.. } if ( empty( $package ) ) { return new WP_Error( 'no_package', $this->strings['no_package'] ); } //$this->skin->feedback( 'downloading_package', $package ); $download_file = download_url( $package, 300, $check_signatures ); if ( is_wp_error( $download_file ) && ! $download_file->get_error_data( 'softfail-filename' ) ) { return new WP_Error( 'download_failed', $this->strings['download_failed'], $download_file->get_error_message() ); } return $download_file; } /** * Unpack a compressed package file. * * @since 2.8.0 * * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. * * @param string $package Full path to the package file. * @param bool $delete_package Optional. Whether to delete the package file after attempting * to unpack it. Default true. * @return string|WP_Error The path to the unpacked contents, or a WP_Error on failure. */ public function unpack_package( $package, $delete_package = true ) { global $wp_filesystem; //$this->skin->feedback( 'unpack_package' ); $upgrade_folder = $wp_filesystem->wp_content_dir() . 'upgrade/'; //Clean up contents of upgrade directory beforehand. $upgrade_files = $wp_filesystem->dirlist( $upgrade_folder ); if ( ! empty( $upgrade_files ) ) { foreach ( $upgrade_files as $file ) { $wp_filesystem->delete( $upgrade_folder . $file['name'], true ); } } // We need a working directory - Strip off any .tmp or .zip suffixes $working_dir = $upgrade_folder . basename( basename( $package, '.tmp' ), '.zip' ); // Clean up working directory if ( $wp_filesystem->is_dir( $working_dir ) ) { $wp_filesystem->delete( $working_dir, true ); } // Unzip package to working directory $result = unzip_file( $package, $working_dir ); // Once extracted, delete the package if required. if ( $delete_package ) { unlink( $package ); } if ( is_wp_error( $result ) ) { $wp_filesystem->delete( $working_dir, true ); if ( 'incompatible_archive' == $result->get_error_code() ) { return new WP_Error( 'incompatible_archive', $this->strings['incompatible_archive'], $result->get_error_data() ); } return $result; } return $working_dir; } /** * Install a package. * * Copies the contents of a package form a source directory, and installs them in * a destination directory. Optionally removes the source. It can also optionally * clear out the destination folder if it already exists. * * @since 2.8.0 * * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass. * @global array $wp_theme_directories * * @param array|string $args { * Optional. Array or string of arguments for installing a package. Default empty array. * * @type string $source Required path to the package source. Default empty. * @type string $destination Required path to a folder to install the package in. * Default empty. * @type bool $clear_destination Whether to delete any files already in the destination * folder. Default false. * @type bool $clear_working Whether to delete the files form the working directory * after copying to the destination. Default false. * @type bool $abort_if_destination_exists Whether to abort the installation if * the destination folder already exists. Default true. * @type array $hook_extra Extra arguments to pass to the filter hooks called by * WP_Upgrader::install_package(). Default empty array. * } * * @return array|WP_Error The result (also stored in `WP_Upgrader::$result`), or a WP_Error on failure. */ public function install_package( $args = array() ) { global $wp_filesystem, $wp_theme_directories; $defaults = array( 'source' => '', // Please always pass this 'destination' => '', // and this 'clear_destination' => false, 'clear_working' => false, 'abort_if_destination_exists' => true, 'hook_extra' => array(), ); $args = wp_parse_args( $args, $defaults ); // These were previously extract()'d. $source = $args['source']; $destination = $args['destination']; $clear_destination = $args['clear_destination']; set_time_limit( 300 ); if ( empty( $source ) || empty( $destination ) ) { return new WP_Error( 'bad_request', $this->strings['bad_request'] ); } //$this->skin->feedback( 'installing_package' ); /** * Filter the install response before the installation has started. * * Returning a truthy value, or one that could be evaluated as a WP_Error * will effectively short-circuit the installation, returning that value * instead. * * @since 2.8.0 * * @param bool|WP_Error $response Response. * @param array $hook_extra Extra arguments passed to hooked filters. */ $res = apply_filters( 'upgrader_pre_install', true, $args['hook_extra'] ); if ( is_wp_error( $res ) ) { return $res; } //Retain the Original source and destinations $remote_source = $args['source']; $local_destination = $destination; $source_files = array_keys( $wp_filesystem->dirlist( $remote_source ) ); $remote_destination = $wp_filesystem->find_folder( $local_destination ); //Locate which directory to copy to the new folder, This is based on the actual folder holding the files. if ( 1 == count( $source_files ) && $wp_filesystem->is_dir( trailingslashit( $args['source'] ) . $source_files[0] . '/' ) ) { //Only one folder? Then we want its contents. $source = trailingslashit( $args['source'] ) . trailingslashit( $source_files[0] ); } elseif ( count( $source_files ) == 0 ) { return new WP_Error( 'incompatible_archive_empty', $this->strings['incompatible_archive'], $this->strings['no_files'] ); // There are no files? } else { // It's only a single file, the upgrader will use the folder name of this file as the destination folder. Folder name is based on zip filename. $source = trailingslashit( $args['source'] ); } /** * Filter the source file location for the upgrade package. * * @since 2.8.0 * @since 4.4.0 The $hook_extra parameter became available. * * @param string $source File source location. * @param string $remote_source Remote file source location. * @param WP_Upgrader $this WP_Upgrader instance. * @param array $hook_extra Extra arguments passed to hooked filters. */ $source = apply_filters( 'upgrader_source_selection', $source, $remote_source, $this, $args['hook_extra'] ); if ( is_wp_error( $source ) ) { return $source; } // Has the source location changed? If so, we need a new source_files list. if ( $source !== $remote_source ) { $source_files = array_keys( $wp_filesystem->dirlist( $source ) ); } /* * Protection against deleting files in any important base directories. * Theme_Upgrader & Plugin_Upgrader also trigger this, as they pass the * destination directory (WP_PLUGIN_DIR / wp-content/themes) intending * to copy the directory into the directory, whilst they pass the source * as the actual files to copy. */ $protected_directories = array( ABSPATH, WP_CONTENT_DIR, WP_PLUGIN_DIR, WP_CONTENT_DIR . '/themes' ); if ( is_array( $wp_theme_directories ) ) { $protected_directories = array_merge( $protected_directories, $wp_theme_directories ); } if ( in_array( $destination, $protected_directories ) ) { $remote_destination = trailingslashit( $remote_destination ) . trailingslashit( basename( $source ) ); $destination = trailingslashit( $destination ) . trailingslashit( basename( $source ) ); } if ( $clear_destination ) { // We're going to clear the destination if there's something there. //$this->skin->feedback( 'remove_old' ); $removed = $this->clear_destination( $remote_destination ); /** * Filter whether the upgrader cleared the destination. * * @since 2.8.0 * * @param mixed $removed Whether the destination was cleared. true on success, WP_Error on failure * @param string $local_destination The local package destination. * @param string $remote_destination The remote package destination. * @param array $hook_extra Extra arguments passed to hooked filters. */ $removed = apply_filters( 'upgrader_clear_destination', $removed, $local_destination, $remote_destination, $args['hook_extra'] ); if ( is_wp_error( $removed ) ) { return $removed; } } elseif ( $args['abort_if_destination_exists'] && $wp_filesystem->exists( $remote_destination ) ) { //If we're not clearing the destination folder and something exists there already, Bail. //But first check to see if there are actually any files in the folder. $_files = $wp_filesystem->dirlist( $remote_destination ); if ( ! empty( $_files ) ) { $wp_filesystem->delete( $remote_source, true ); //Clear out the source files. return new WP_Error( 'folder_exists', $this->strings['folder_exists'], $remote_destination ); } } //Create destination if needed if ( ! $wp_filesystem->exists( $remote_destination ) ) { if ( ! $wp_filesystem->mkdir( $remote_destination, FS_CHMOD_DIR ) ) { return new WP_Error( 'mkdir_failed_destination', $this->strings['mkdir_failed'], $remote_destination ); } } // Copy new version of item into place. $result = copy_dir( $source, $remote_destination ); if ( is_wp_error( $result ) ) { if ( $args['clear_working'] ) { $wp_filesystem->delete( $remote_source, true ); } return $result; } //Clear the Working folder? if ( $args['clear_working'] ) { $wp_filesystem->delete( $remote_source, true ); } $destination_name = basename( str_replace( $local_destination, '', $destination ) ); if ( '.' == $destination_name ) { $destination_name = ''; } $this->result = compact( 'source', 'source_files', 'destination', 'destination_name', 'local_destination', 'remote_destination', 'clear_destination' ); /** * Filter the installation response after the installation has finished. * * @since 2.8.0 * * @param bool $response Installation response. * @param array $hook_extra Extra arguments passed to hooked filters. * @param array $result Installation result data. */ $res = apply_filters( 'upgrader_post_install', true, $args['hook_extra'], $this->result ); if ( is_wp_error( $res ) ) { $this->result = $res; return $res; } //Bombard the calling function will all the info which we've just used. return $this->result; } } Helpers/Chain.php000066600000012254152141020640007704 0ustar00value = $value; } /** * Bind some function to value. * * @since 1.5.6 * * @param mixed $fn Some function. * * @return Chain */ public function bind( $fn ) { $this->value = $fn( $this->value ); return $this; } /** * Get value. * * @since 1.5.6 * * @return mixed */ public function value() { return $this->value; } /** * Magic call. * * @since 1.5.6 * * @param string $name Method name. * @param array $params Parameters. * * @throws \BadFunctionCallException Invalid function is called. * * @return Chain */ public function __call( $name, $params ) { if ( in_array( $name, $this->allowed_methods(), true ) ) { $params = null === $params ? array() : $params; array_unshift( $params, $this->value ); $this->value = call_user_func_array( $name, $params ); return $this; } throw new \BadFunctionCallException( "Provided function { $name } is not allowed. See Chain::allowed_methods()." ); } /** * Join array elements with a string. * * @since 1.5.6 * * @param string $glue Defaults to an empty string. * * @return Chain */ public function implode( $glue = '' ) { $this->value = implode( $glue, $this->value ); return $this; } /** * Split a string by a string. * * @since 1.5.6 * * @param string $delimiter The boundary string. * * @return Chain */ public function explode( $delimiter ) { $this->value = explode( $delimiter, $this->value ); return $this; } /** * Apply the callback to the elements of the given arrays. * * @since 1.5.6 * * @param callable $cb Callback. * * @return Chain */ public function map( $cb ) { $this->value = array_map( $cb, $this->value ); return $this; } /** * Pop array. * * @since 1.5.6 * * @return Chain */ public function pop() { $this->value = array_pop( $this->value ); return $this; } /** * Run first or second callback based on a condition. * * @since 1.5.6 * * @param callable $condition Condition function. * @param callable $true_result If condition will return true we run this function. * @param callable $false_result If condition will return false we run this function. * * @return Chain */ public function iif( $condition, $true_result, $false_result = null ) { if ( ! is_callable( $false_result ) ) { $false_result = function() { return ''; }; } $this->value = array_map( function( $el ) use ( $condition, $true_result, $false_result ) { if ( call_user_func( $condition, $el ) ) { return call_user_func( $true_result, $el ); } return call_user_func( $false_result, $el ); }, $this->value ); return $this; } /** * All allowed methods to work with data. * * @since 1.5.6 * * @return array */ public function allowed_methods() { return array( 'array_change_key_case', 'array_chunk', 'array_column', 'array_combine', 'array_count_values', 'array_diff_assoc', 'array_diff_key', 'array_diff_uassoc', 'array_diff_ukey', 'array_diff', 'array_fill_keys', 'array_fill', 'array_filter', 'array_flip', 'array_intersect_assoc', 'array_intersect_key', 'array_intersect_uassoc', 'array_intersect_ukey', 'array_intersect', 'array_key_first', 'array_key_last', 'array_keys', 'array_map', 'array_merge_recursive', 'array_merge', 'array_pad', 'array_pop', 'array_product', 'array_rand', 'array_reduce', 'array_replace_recursive', 'array_replace', 'array_reverse', 'array_shift', 'array_slice', 'array_splice', 'array_sum', 'array_udiff_assoc', 'array_udiff_uassoc', 'array_udiff', 'array_uintersect_assoc', 'array_uintersect_uassoc', 'array_uintersect', 'array_unique', 'array_values', 'count', 'current', 'end', 'key', 'next', 'prev', 'range', 'reset', 'implode', 'ltrim', 'rtrim', 'md5', 'str_getcsv', 'str_ireplace', 'str_pad', 'str_repeat', 'str_rot13', 'str_shuffle', 'str_split', 'str_word_count', 'strcasecmp', 'strchr', 'strcmp', 'strcoll', 'strcspn', 'strip_tags', 'stripcslashes', 'stripos', 'stripslashes', 'stristr', 'strlen', 'strnatcasecmp', 'strnatcmp', 'strncasecmp', 'strncmp', 'strpbrk', 'strpos', 'strrchr', 'strrev', 'strripos', 'strrpos', 'strspn', 'strstr', 'strtok', 'strtolower', 'strtoupper', 'strtr', 'substr_compare', 'substr_count', 'substr_replace', 'substr', 'trim', 'ucfirst', 'ucwords', 'vfprintf', 'vprintf', 'vsprintf', 'wordwrap', ); } /** * Create myself. * * @since 1.5.6 * * @param mixed $value Current. * * @return Chain */ public static function of( $value = null ) { return new self( $value ); } } Helpers/Templates.php000066600000007016152141020640010620 0ustar00 \trailingslashit( \get_stylesheet_directory() ) . $template_dir, 10 => \trailingslashit( \get_template_directory() ) . $template_dir, 100 => \trailingslashit( \WPFORMS_PLUGIN_DIR ) . 'templates', ); $file_paths = \apply_filters( 'wpforms_helpers_templates_get_theme_template_paths', $file_paths ); // Sort the file paths based on priority. \ksort( $file_paths, SORT_NUMERIC ); return \array_map( 'trailingslashit', $file_paths ); } /** * Locate a template and return the path for inclusion. * * @since 1.5.4 * * @param string $template_name Template name. * * @return string */ public static function locate( $template_name ) { // Trim off any slashes from the template name. $template_name = \ltrim( $template_name, '/' ); if ( empty( $template_name ) ) { return \apply_filters( 'wpforms_helpers_templates_locate', '', $template_name ); } $located = ''; // Try locating this template file by looping through the template paths. foreach ( self::get_theme_template_paths() as $template_path ) { if ( \file_exists( $template_path . $template_name ) ) { $located = $template_path . $template_name; break; } } return \apply_filters( 'wpforms_helpers_templates_locate', $located, $template_name ); } /** * Include a template. * Use 'require' if $args are passed or 'load_template' if not. * * @since 1.5.4 * * @param string $template_name Template name. * @param array $args Arguments. * @param bool $extract Extract arguments. * * @throws \RuntimeException If extract() tries to modify the scope. */ public static function include_html( $template_name, $args = array(), $extract = false ) { $template_name .= '.php'; // Allow 3rd party plugins to filter template file from their plugin. $located = \apply_filters( 'wpforms_helpers_templates_include_html_located', self::locate( $template_name ), $template_name, $args, $extract ); $args = \apply_filters( 'wpforms_helpers_templates_include_html_args', $args, $template_name, $extract ); if ( empty( $located ) || ! \is_readable( $located ) ) { return; } // Load template WP way if no arguments were passed. if ( empty( $args ) ) { \load_template( $located, false ); return; } $extract = \apply_filters( 'wpforms_helpers_templates_include_html_extract_args', $extract, $template_name, $args ); if ( $extract && \is_array( $args ) ) { $created_vars_count = extract( $args, EXTR_SKIP ); // phpcs:ignore WordPress.PHP.DontExtract // Protecting existing scope from modification. if ( count( $args ) !== $created_vars_count ) { throw new \RuntimeException( 'Extraction failed: variable names are clashing with the existing ones.' ); } } require $located; } /** * Like self::include_html, but returns the HTML instead of including. * * @since 1.5.4 * * @param string $template_name Template name. * @param array $args Arguments. * @param bool $extract Extract arguments. * * @return string */ public static function get_html( $template_name, $args = array(), $extract = false ) { \ob_start(); self::include_html( $template_name, $args, $extract ); return \ob_get_clean(); } } Loader.php000066600000003545152141020640006471 0ustar00populate_classes(); wpforms()->register_bulk( $this->classes ); } /** * Populate the classes to register. * * @since 1.5.8 */ protected function populate_classes() { $this->populate_admin(); $this->populate_migrations(); $this->populate_capabilities(); $this->populate_tasks(); } /** * Populate Admin related classes. * * @since 1.6.0 */ private function populate_admin() { array_push( $this->classes, [ 'name' => 'Admin\AdminBarMenu', ], [ 'name' => 'Admin\Notifications', 'id' => 'notifications', ], [ 'name' => 'Admin\Entries\Edit', 'id' => 'entries_edit', 'hook' => 'admin_init', ] ); } /** * Populate migration classes. * * @since 1.5.9 */ private function populate_migrations() { $this->classes[] = [ 'name' => 'Migrations', 'hook' => 'plugins_loaded', ]; } /** * Populate access management (capabilities) classes. * * @since 1.5.8 */ private function populate_capabilities() { array_push( $this->classes, [ 'name' => 'Access\Capabilities', 'id' => 'access', 'hook' => 'plugins_loaded', ], [ 'name' => 'Access\Integrations', ], [ 'name' => 'Admin\Settings\Access', 'condition' => is_admin(), ] ); } /** * Populate tasks related classes. * * @since 1.5.9 */ private function populate_tasks() { array_push( $this->classes, [ 'name' => 'Tasks\Tasks', 'id' => 'tasks', 'hook' => 'init', ], [ 'name' => 'Tasks\Meta', 'id' => 'tasks_meta', 'hook' => false, 'run' => false, ] ); } } Providers/Provider/Process.php000066600000004300152141020640012436 0ustar00core = $core; } /** * Receive all wpforms_process_complete params and do the actual processing. * * @since 1.4.7 * * @param array $fields Array of form fields. * @param array $entry Submitted form content. * @param array $form_data Form data and settings. * @param int $entry_id ID of a saved entry. */ abstract public function process( $fields, $entry, $form_data, $entry_id ); /** * Process conditional logic for a connection. * * @since 1.4.7 * * @param array $fields Array of form fields. * @param array $form_data Form data and settings. * @param array $connection All connection data. * * @return bool */ protected function process_conditionals( $fields, $form_data, $connection ) { if ( empty( $connection['conditional_logic'] ) || empty( $connection['conditionals'] ) ) { return true; } $process = wpforms_conditional_logic()->process( $fields, $form_data, $connection['conditionals'] ); if ( ! empty( $connection['conditional_type'] ) && 'stop' === $connection['conditional_type'] ) { $process = ! $process; } return $process; } /** * Get provider options, saved on Settings > Integrations page. * * @since 1.4.7 * * @return array */ protected function get_options() { return \wpforms_get_providers_options( $this->core->slug ); } } Providers/Provider/Settings/FormBuilder.php000066600000031312152141020640015035 0ustar00core = $core; if ( ! empty( $_GET['form_id'] ) ) { // phpcs:ignore $this->form_data = \wpforms()->form->get( \absint( $_GET['form_id'] ), // phpcs:ignore array( 'content_only' => true, ) ); } $this->init_hooks(); } /** * Register all hooks (actions and filters) here. * * @since 1.4.7 */ protected function init_hooks() { // Register builder HTML template(s). \add_action( 'wpforms_builder_print_footer_scripts', array( $this, 'builder_templates' ), 10 ); \add_action( 'wpforms_builder_print_footer_scripts', array( $this, 'builder_custom_templates' ), 11 ); // Process builder AJAX requests. \add_action( "wp_ajax_wpforms_builder_provider_ajax_{$this->core->slug}", array( $this, 'process_ajax' ) ); /* * Enqueue assets. */ if ( ( ! empty( $_GET['page'] ) && $_GET['page'] === 'wpforms-builder' ) && // phpcs:ignore ! empty( $_GET['form_id'] ) && // phpcs:ignore \is_admin() ) { \add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) ); } } /** * Used to register generic templates for all providers inside form builder. * * @since 1.4.7 */ public function builder_templates() { ?> \esc_html__( 'You do not have permission to perform this action.', 'wpforms-lite' ), ) ); } // Process required values. $error = array( 'error' => \esc_html__( 'Something went wrong while performing an AJAX request.', 'wpforms-lite' ) ); if ( empty( $_POST['id'] ) || empty( $_POST['task'] ) ) { \wp_send_json_error( $error ); } $form_id = (int) $_POST['id']; $task = \sanitize_key( $_POST['task'] ); $data = null; // Setup form data based on the ID, that we got from AJAX request. $this->form_data = \wpforms()->form->get( $form_id, array( 'content_only' => true, ) ); // Do not allow to proceed further, as form_id may be incorrect. if ( empty( $this->form_data ) ) { \wp_send_json_error( $error ); } $data = \apply_filters( 'wpforms_providers_settings_builder_ajax_' . $task . '_' . $this->core->slug, null ); if ( null !== $data ) { \wp_send_json_success( $data ); } \wp_send_json_error( $error ); } /** * Display content inside the panel sidebar area. * * @since 1.4.7 */ public function display_sidebar() { $configured = ''; if ( ! empty( $this->form_data['id'] ) && Status::init( $this->core->slug )->is_ready( $this->form_data['id'] ) ) { $configured = 'configured'; } $classes = array( 'wpforms-panel-sidebar-section', 'icon', $configured, 'wpforms-panel-sidebar-section-' . $this->core->slug, ); ?> core->name ); ?>
display_content_header(); ?>
core->slug )->is_configured(); ?>
core->name ); ?>
Settings -> Integrations page. * * @since 1.4.7 */ abstract class PageIntegrations implements PageIntegrationsInterface { /** * Get the Core loader class of a provider. * * @since 1.4.7 * * @var Core */ protected $core; /** * Integrations constructor. * * @since 1.4.7 * * @param Core $core Core provider object. */ public function __construct( Core $core ) { $this->core = $core; $this->ajax(); } /** * Process the default ajax functionality. * * @since 1.4.7 */ protected function ajax() { // Remove provider from Settings Integrations tab. \add_action( "wp_ajax_wpforms_settings_provider_disconnect_{$this->core->slug}", array( $this, 'ajax_disconnect' ) ); // Add new provider from Settings Integrations tab. \add_action( "wp_ajax_wpforms_settings_provider_add_{$this->core->slug}", array( $this, 'ajax_connect' ) ); } /** * @inheritdoc */ public function display( $active, $settings ) { $connected = ! empty( $active[ $this->core->slug ] ); $accounts = ! empty( $settings[ $this->core->slug ] ) ? $settings[ $this->core->slug ] : array(); $class = $connected && $accounts ? 'connected' : ''; $arrow = 'right'; // This lets us highlight a specific service by a special link. if ( ! empty( $_GET['wpforms-integration'] ) ) { //phpcs:ignore if ( $this->core->slug === $_GET['wpforms-integration'] ) { //phpcs:ignore $class .= ' focus-in'; $arrow = 'down'; } else { $class .= ' focus-out'; } } ?>

core->name ); ?>

core->name ) ); ?>

 
    $account ) { echo '
  • '; echo '' . \esc_html( $account['label'] ) . ''; /* translators: %s - Connection date. */ echo '' . \sprintf( \esc_html__( 'Connected on: %s', 'wpforms-lite' ), \date_i18n( \get_option( 'date_format' ), $account['date'] ) ) . ''; echo '' . \esc_html__( 'Disconnect', 'wpforms-lite' ) . ''; echo '
  • '; } } ?>
display_add_new(); ?>
core->name ); ?>

display_add_new_connection_fields(); ?>

\esc_html__( 'You do not have permission', 'wpforms-lite' ), ) ); } if ( empty( $_POST['provider'] ) || empty( $_POST['key'] ) ) { \wp_send_json_error( array( 'error' => \esc_html__( 'Missing data', 'wpforms-lite' ), ) ); } $providers = \wpforms_get_providers_options(); if ( ! empty( $providers[ $_POST['provider'] ][ $_POST['key'] ] ) ) { unset( $providers[ $_POST['provider'] ][ $_POST['key'] ] ); \update_option( 'wpforms_providers', $providers ); \wp_send_json_success(); } else { \wp_send_json_error( array( 'error' => \esc_html__( 'Connection missing', 'wpforms-lite' ), ) ); } } /** * AJAX to add a provider from the settings integrations tab. * * @since 1.4.7 * * @return bool False when not own provider is processed. */ public function ajax_connect() { // Run a security check. \check_ajax_referer( 'wpforms-admin', 'nonce' ); // Check for permissions. if ( ! \wpforms_current_user_can() ) { \wp_send_json_error( array( 'error' => \esc_html__( 'You do not have permissions.', 'wpforms-lite' ), ) ); } if ( empty( $_POST['data'] ) ) { \wp_send_json_error( array( 'error' => \esc_html__( 'Missing required data in payload.', 'wpforms-lite' ), ) ); } } } Providers/Provider/Settings/FormBuilderInterface.php000066600000001265152141020640016662 0ustar00`. * * @since 1.4.7 */ public function builder_custom_templates(); } Providers/Provider/Status.php000066600000005442152141020640012313 0ustar00provider = sanitize_key( (string) $provider ); } /** * Provide ability to statically init the object. * Useful for inline-invocations. * * @example: Status::init( 'drip' )->is_ready(); * * @since 1.4.8 * @since 1.5.9 Added a check on provider. * * @param string $provider Provider slug. * * @return \WPForms\Providers\Provider\Status */ public static function init( $provider ) { static $instance; if ( ! $instance || $provider !== $instance->provider ) { $instance = new self( $provider ); } return $instance; } /** * Check whether the defined provider is configured or not. * "Configured" means has an account, that might be checked/updated on Settings > Integrations. * * @since 1.4.8 * * @return bool */ public function is_configured() { $options = \wpforms_get_providers_options(); // We meed to leave this filter for BC. $is_configured = \apply_filters( 'wpforms_providers_' . $this->provider . '_configured', ! empty( $options[ $this->provider ] ) ? true : false ); // Use this filter to change the configuration status of the provider. return apply_filters( 'wpforms_providers_status_is_configured', $is_configured, $this->provider ); } /** * Check whether the defined provider is connected to some form. * "Connected" means it has a Connection in Form Builder > Providers > Provider tab. * * @since 1.4.8 * * @param int $form_id Form ID to check the status against. * * @return bool */ public function is_connected( $form_id ) { $is_connected = false; $this->form_data = \wpforms()->form->get( (int) $form_id, array( 'content_only' => true, ) ); if ( ! empty( $this->form_data['providers'][ $this->provider ] ) || ! empty( $this->form_data['payments'][ $this->provider ] ) ) { $is_connected = true; } return apply_filters( 'wpforms_providers_status_is_connected', $is_connected, $this->provider ); } /** * Is the current provider ready to be used? * It means both configured and connected. * * @since 1.4.8 * * @param int $form_id Form ID to check the status against. * * @return bool */ public function is_ready( $form_id ) { return $this->is_configured() && $this->is_connected( $form_id ); } } Providers/Provider/Core.php000066600000006336152141020640011723 0ustar00slug = \sanitize_key( $params['slug'] ); } else { throw new \UnexpectedValueException( 'Provider class should define a provider "slug" param in its constructor.' ); } if ( ! empty( $params['name'] ) ) { $this->name = \sanitize_text_field( $params['name'] ); } else { throw new \UnexpectedValueException( 'Provider class should define a provider "name" param in its constructor.' ); } $this->icon = WPFORMS_PLUGIN_URL . 'assets/images/sullie.png'; if ( ! empty( $params['icon'] ) ) { $this->icon = \esc_url_raw( $params['icon'] ); } } /** * Add to list of registered providers. * * @since 1.4.7 * * @param array $providers Array of all active providers. * * @return array */ public function register_provider( array $providers ) { $providers[ $this->slug ] = $this->name; return $providers; } /** * Provide an instance of the object, that should process the submitted entry. * It will use data from an already saved entry to pass it further to a Provider. * * @since 1.4.7 * * @return null|\WPForms\Providers\Provider\Process */ abstract public function get_process(); /** * Provide an instance of the object, that should display provider settings * on Settings > Integrations page in admin area. * If you don't want to display it (i.e. you don't need it), you can pass null here in your Core provider class. * * @since 1.4.7 * * @return null|\WPForms\Providers\Provider\Settings\PageIntegrations */ abstract public function get_page_integrations(); /** * Provide an instance of the object, that should display provider settings in the Form Builder. * If you don't want to display it (i.e. you don't need it), you can pass null here in your Core provider class. * * @since 1.4.7 * * @return null|\WPForms\Providers\Provider\Settings\FormBuilder */ abstract public function get_form_builder(); } Providers/Loader.php000066600000003201152141020640010433 0ustar00 Settings > Integrations page. $integration = $provider->get_page_integrations(); if ( null !== $integration ) { \add_action( 'wpforms_settings_providers', array( $integration, 'display' ), $provider::PRIORITY, 2 ); } // Editing Single Form > Form Builder. $form_builder = $provider->get_form_builder(); if ( null !== $form_builder ) { \add_action( 'wpforms_providers_panel_sidebar', array( $form_builder, 'display_sidebar' ), $provider::PRIORITY ); \add_action( 'wpforms_providers_panel_content', array( $form_builder, 'display_content' ), $provider::PRIORITY ); } // Process entry submission. $process = $provider->get_process(); if ( null !== $process ) { \add_action( 'wpforms_process_complete', array( $process, 'process' ), 5, 4 ); } } } WPForms.php000066600000025333152141020640006617 0ustar00form' or 'wpforms()->entry' * * @since 1.5.7 * * @param string $name Name of the object to get. * * @return mixed|null */ public function __get( $name ) { return $this->get( $name ); } /** * Main WPForms Instance. * * Only one instance of WPForms exists in memory at any one time. * Also prevent the need to define globals all over the place. * * @since 1.0.0 * * @return WPForms */ public static function instance() { if ( null === self::$instance || ! self::$instance instanceof self ) { self::$instance = new self(); self::$instance->constants(); self::$instance->includes(); // Load Pro or Lite specific files. if ( self::$instance->pro ) { self::$instance->registry['pro'] = require_once WPFORMS_PLUGIN_DIR . 'pro/wpforms-pro.php'; } else { require_once WPFORMS_PLUGIN_DIR . 'lite/wpforms-lite.php'; } add_action( 'plugins_loaded', array( self::$instance, 'load_textdomain' ), 10 ); add_action( 'plugins_loaded', array( self::$instance, 'objects' ), 10 ); } return self::$instance; } /** * Setup plugin constants. * All the path/URL related constants are defined in main plugin file. * * @since 1.0.0 */ private function constants() { $this->version = WPFORMS_VERSION; // Plugin Slug - Determine plugin type and set slug accordingly. if ( apply_filters( 'wpforms_allow_pro_version', file_exists( WPFORMS_PLUGIN_DIR . 'pro/wpforms-pro.php' ) ) ) { $this->pro = true; define( 'WPFORMS_PLUGIN_SLUG', 'wpforms' ); } else { define( 'WPFORMS_PLUGIN_SLUG', 'wpforms-lite' ); } } /** * Load the plugin language files. * * @since 1.0.0 * @since 1.5.0 Load only the lite translation. */ public function load_textdomain() { load_plugin_textdomain( 'wpforms-lite', false, dirname( plugin_basename( WPFORMS_PLUGIN_FILE ) ) . '/languages/' ); } /** * Include files. * * @since 1.0.0 */ private function includes() { require_once WPFORMS_PLUGIN_DIR . 'includes/class-db.php'; $this->includes_magic(); // Global includes. require_once WPFORMS_PLUGIN_DIR . 'includes/functions.php'; require_once WPFORMS_PLUGIN_DIR . 'includes/functions-list.php'; require_once WPFORMS_PLUGIN_DIR . 'includes/class-install.php'; require_once WPFORMS_PLUGIN_DIR . 'includes/class-form.php'; require_once WPFORMS_PLUGIN_DIR . 'includes/class-fields.php'; require_once WPFORMS_PLUGIN_DIR . 'includes/class-frontend.php'; // TODO: class-templates.php should be loaded in admin area only. require_once WPFORMS_PLUGIN_DIR . 'includes/class-templates.php'; // TODO: class-providers.php should be loaded in admin area only. require_once WPFORMS_PLUGIN_DIR . 'includes/class-providers.php'; require_once WPFORMS_PLUGIN_DIR . 'includes/class-process.php'; require_once WPFORMS_PLUGIN_DIR . 'includes/class-smart-tags.php'; require_once WPFORMS_PLUGIN_DIR . 'includes/class-logging.php'; require_once WPFORMS_PLUGIN_DIR . 'includes/class-widget.php'; require_once WPFORMS_PLUGIN_DIR . 'includes/class-conditional-logic-core.php'; require_once WPFORMS_PLUGIN_DIR . 'includes/emails/class-emails.php'; require_once WPFORMS_PLUGIN_DIR . 'includes/integrations.php'; require_once WPFORMS_PLUGIN_DIR . 'includes/deprecated.php'; // Admin/Dashboard only includes, also in ajax. if ( is_admin() ) { require_once WPFORMS_PLUGIN_DIR . 'includes/admin/admin.php'; require_once WPFORMS_PLUGIN_DIR . 'includes/admin/class-notices.php'; require_once WPFORMS_PLUGIN_DIR . 'includes/admin/class-menu.php'; require_once WPFORMS_PLUGIN_DIR . 'includes/admin/overview/class-overview.php'; require_once WPFORMS_PLUGIN_DIR . 'includes/admin/builder/class-builder.php'; require_once WPFORMS_PLUGIN_DIR . 'includes/admin/builder/functions.php'; require_once WPFORMS_PLUGIN_DIR . 'includes/admin/class-settings.php'; require_once WPFORMS_PLUGIN_DIR . 'includes/admin/class-welcome.php'; require_once WPFORMS_PLUGIN_DIR . 'includes/admin/class-tools.php'; require_once WPFORMS_PLUGIN_DIR . 'includes/admin/class-editor.php'; require_once WPFORMS_PLUGIN_DIR . 'includes/admin/class-review.php'; require_once WPFORMS_PLUGIN_DIR . 'includes/admin/class-importers.php'; require_once WPFORMS_PLUGIN_DIR . 'includes/admin/class-about.php'; require_once WPFORMS_PLUGIN_DIR . 'includes/admin/ajax-actions.php'; } } /** * Including the new files with PHP 5.3 style. * * @since 1.4.7 */ private function includes_magic() { // Action Scheduler requires a special loading procedure. require_once WPFORMS_PLUGIN_DIR . 'vendor/woocommerce/action-scheduler/action-scheduler.php'; // Autoload Composer packages. require_once WPFORMS_PLUGIN_DIR . 'vendor/autoload.php'; // Load the class loader. $this->register( [ 'name' => 'Loader', 'hook' => false, ] ); if ( version_compare( phpversion(), '5.5', '>=' ) ) { /* * Load PHP 5.5 email subsystem. */ add_action( 'wpforms_loaded', array( '\WPForms\Emails\Summaries', 'get_instance' ) ); } /* * Load admin components. Exclude from frontend. */ if ( is_admin() ) { add_action( 'wpforms_loaded', array( '\WPForms\Admin\Loader', 'get_instance' ) ); } /* * Load form components. */ add_action( 'wpforms_loaded', array( '\WPForms\Forms\Loader', 'get_instance' ) ); /* * Properly init the providers loader, that will handle all the related logic and further loading. */ add_action( 'wpforms_loaded', array( '\WPForms\Providers\Loader', 'get_instance' ) ); /* * Properly init the integrations loader, that will handle all the related logic and further loading. */ add_action( 'wpforms_loaded', array( '\WPForms\Integrations\Loader', 'get_instance' ) ); } /** * Setup objects. * * @since 1.0.0 */ public function objects() { // Global objects. $this->form = new \WPForms_Form_Handler(); $this->frontend = new \WPForms_Frontend(); $this->process = new \WPForms_Process(); $this->smart_tags = new \WPForms_Smart_Tags(); $this->logs = new \WPForms_Logging(); // Hook now that all of the WPForms stuff is loaded. do_action( 'wpforms_loaded' ); } /** * Register a class. * * @since 1.5.7 * * @param array $class Class registration info. */ public function register( $class ) { if ( empty( $class['name'] ) || ! is_string( $class['name'] ) ) { return; } if ( isset( $class['condition'] ) && empty( $class['condition'] ) ) { return; } $full_name = $this->pro ? '\WPForms\Pro\\' . $class['name'] : '\WPForms\Lite\\' . $class['name']; $full_name = class_exists( $full_name ) ? $full_name : '\WPForms\\' . $class['name']; if ( ! class_exists( $full_name ) ) { return; } $pattern = '/[^a-zA-Z0-9_\\\-]/'; $id = isset( $class['id'] ) ? $class['id'] : ''; $id = $id ? preg_replace( $pattern, '', (string) $id ) : $id; $hook = isset( $class['hook'] ) ? $class['hook'] : 'wpforms_loaded'; $hook = $hook ? preg_replace( $pattern, '', (string) $hook ) : $hook; $run = isset( $class['run'] ) ? $class['run'] : 'init'; $priority = isset( $class['priority'] ) && is_int( $class['priority'] ) ? $class['priority'] : 10; $callback = function () use ( $full_name, $id, $run ) { $instance = new $full_name(); if ( $id && ! array_key_exists( $id, $this->registry ) ) { $this->registry[ $id ] = $instance; } if ( $run && method_exists( $instance, $run ) ) { $instance->{$run}(); } }; if ( $hook ) { add_action( $hook, $callback, $priority ); } else { $callback(); } } /** * Register classes in bulk. * * @since 1.5.7 * * @param array $classes Classes to register. */ public function register_bulk( $classes ) { if ( ! is_array( $classes ) ) { return; } foreach ( $classes as $class ) { $this->register( $class ); } } /** * Get a class instance from a registry. * * @since 1.5.7 * * @param string $name Class name or an alias. * * @return mixed|\stdClass */ public function get( $name ) { if ( ! empty( $this->registry[ $name ] ) ) { return $this->registry[ $name ]; } return new \stdClass(); } } } namespace { /** * The function which returns the one WPForms instance. * * @since 1.0.0 * * @return WPForms\WPForms */ function wpforms() { return WPForms\WPForms::instance(); } /** * Adding an alias for backward-compatibility with plugins * that still use class_exists('WPForms') * instead of function_exists('wpforms'), which is preferred. * * In 1.5.0 we removed support for PHP 5.2 * and moved former WPForms class to a namespace: WPForms\WPForms. * * @since 1.5.1 */ class_alias( 'WPForms\WPForms', 'WPForms' ); } Lite/Admin/Connect.php000066600000017322152141020640010577 0ustar00hooks(); } /** * Hooks. * * @since 1.5.5 */ public function hooks() { \add_action( 'wpforms_settings_enqueue', array( $this, 'settings_enqueues' ) ); \add_action( 'wp_ajax_wpforms_connect_url', array( $this, 'generate_url' ) ); \add_action( 'wp_ajax_nopriv_wpforms_connect_process', array( $this, 'process' ) ); } /** * Settings page enqueues. * * @since 1.5.5 */ public function settings_enqueues() { $min = \wpforms_get_min_suffix(); \wp_enqueue_script( 'wpforms-connect', \WPFORMS_PLUGIN_URL . "lite/assets/js/admin/connect{$min}.js", array( 'jquery' ), \WPFORMS_VERSION, true ); } /** * Generate and return WPForms Connect URL. * * @since 1.5.5 */ public function generate_url() { $this->init_error_handler(); try { // Run a security check. \check_ajax_referer( 'wpforms-admin', 'nonce' ); // Check for permissions. if ( ! \current_user_can( 'install_plugins' ) ) { \wp_send_json_error( array( 'message' => \esc_html__( 'Sorry, you do not have permission to install plugins.', 'wpforms-lite' ) ) ); } $key = ! empty( $_POST['key'] ) ? \sanitize_text_field( \wp_unslash( $_POST['key'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification if ( empty( $key ) ) { \wp_send_json_error( array( 'message' => \esc_html__( 'Please enter your license key to connect.', 'wpforms-lite' ) ) ); } if ( wpforms()->pro ) { \wp_send_json_error( array( 'message' => \esc_html__( 'Only the Lite version can upgrade.', 'wpforms-lite' ) ) ); } // Verify pro version is not installed. $active = \activate_plugin( 'wpforms/wpforms.php', false, false, true ); if ( ! \is_wp_error( $active ) ) { // Deactivate Lite. \deactivate_plugins( \plugin_basename( WPFORMS_PLUGIN_FILE ) ); \wp_send_json_success( array( 'message' => \esc_html__( 'WPForms Pro was already installed and has not been activated.', 'wpforms-lite' ), 'reload' => true, ) ); } // Generate URL. $oth = hash( 'sha512', \wp_rand() ); \update_option( 'wpforms_connect_token', $oth ); \update_option( 'wpforms_connect', $key ); $version = WPFORMS_VERSION; $endpoint = \admin_url( 'admin-ajax.php' ); $redirect = \admin_url( 'admin.php?page=wpforms-settings' ); $url = \add_query_arg( array( 'key' => $key, 'oth' => $oth, 'endpoint' => $endpoint, 'version' => $version, 'siteurl' => \admin_url(), 'homeurl' => \home_url(), 'redirect' => rawurldecode( base64_encode( $redirect ) ), // phpcs:ignore 'v' => 2, ), 'https://upgrade.wpforms.com' ); \wp_send_json_success( array( 'url' => $url, 'back_url' => \add_query_arg( array( 'action' => 'wpforms_connect', 'oth' => $oth, ), $endpoint ), ) ); } catch ( \Exception $e ) { \wp_send_json_error( array( 'error' => $e->getMessage() . ' in file ' . $e->getFile() . ', line ' . $e->getLine() ) ); } } /** * Process WPForms Connect. * * @since 1.5.5 */ public function process() { $this->init_error_handler(); try { $error = esc_html__( 'Could not install upgrade. Please download from wpforms.com and install manually.', 'wpforms-lite' ); // Verify params present (oth & download link). $post_oth = ! empty( $_REQUEST['oth'] ) ? \sanitize_text_field( \wp_unslash( $_REQUEST['oth'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification $post_url = ! empty( $_REQUEST['file'] ) ? \esc_url_raw( \wp_unslash( $_REQUEST['file'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification if ( empty( $post_oth ) || empty( $post_url ) ) { \wp_send_json_error( $error ); } // Verify oth. $oth = \get_option( 'wpforms_connect_token' ); if ( empty( $oth ) || ! hash_equals( $oth, $post_oth ) ) { \wp_send_json_error( $error ); } // Delete so cannot replay. \delete_option( 'wpforms_connect_token' ); // Set the current screen to avoid undefined notices. \set_current_screen( 'wpforms_page_wpforms-settings' ); // Prepare variables. $url = \esc_url_raw( \add_query_arg( array( 'page' => 'wpforms-settings', ), \admin_url( 'admin.php' ) ) ); // Verify pro not activated. if ( wpforms()->pro ) { \wp_send_json_success( \esc_html__( 'Plugin installed & activated.', 'wpforms-lite' ) ); } // Verify pro not installed. $active = \activate_plugin( 'wpforms/wpforms.php', $url, false, true ); if ( ! \is_wp_error( $active ) ) { \deactivate_plugins( plugin_basename( WPFORMS_PLUGIN_FILE ) ); \wp_send_json_success( esc_html__( 'Plugin installed & activated.', 'wpforms-lite' ) ); } $creds = \request_filesystem_credentials( $url, '', false, false, null ); // Check for file system permissions. $perm_error = \esc_html__( 'Could not install upgrade. Please check for file system permissions and try again. Also you can download plugin from wpforms.com and install manually.', 'wpforms-lite' ); if ( false === $creds || ! \WP_Filesystem( $creds ) ) { \wp_send_json_error( $perm_error ); } /* * We do not need any extra credentials if we have gotten this far, so let's install the plugin. */ // Do not allow WordPress to search/download translations, as this will break JS output. \remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 ); // Create the plugin upgrader with our custom skin. $installer = new PluginSilentUpgrader( new ConnectSkin() ); // Error check. if ( ! method_exists( $installer, 'install' ) ) { \wp_send_json_error( $error ); } // Check license key. $key = \get_option( 'wpforms_connect', false ); if ( empty( $key ) ) { \wp_send_json_error( new WP_Error( '403', \esc_html__( 'No key provided.', 'wpforms-lite' ) ) ); } $installer->install( $post_url ); // phpcs:ignore // Flush the cache and return the newly installed plugin basename. \wp_cache_flush(); $plugin_basename = $installer->plugin_info(); if ( $plugin_basename ) { // Deactivate the lite version first. \deactivate_plugins( \plugin_basename( WPFORMS_PLUGIN_FILE ) ); // Activate the plugin silently. $activated = \activate_plugin( $plugin_basename, '', false, true ); if ( ! \is_wp_error( $activated ) ) { \add_option( 'wpforms_install', 1 ); \wp_send_json_success( \esc_html__( 'Plugin installed & activated.', 'wpforms-lite' ) ); } else { // Reactivate the lite plugin if pro activation failed. \activate_plugin( \plugin_basename( WPFORMS_PLUGIN_FILE ), '', false, true ); \wp_send_json_error( \esc_html__( 'Pro version installed but needs to be activated from the Plugins page inside your WordPress admin.', 'wpforms-lite' ) ); } } \wp_send_json_error( $error ); } catch ( \Exception $e ) { \wp_send_json_error( array( 'error' => $e->getMessage() . ' in file ' . $e->getFile() . ', line ' . $e->getLine() ) ); } } /** * Converting errors to exceptions. * * @since 1.5.5 */ public function init_error_handler() { set_error_handler( // phpcs:ignore function ( $errno, $errstr, $errfile, $errline, array $errcontex ) { throw new \Exception( $errstr ); } ); } } Lite/Admin/ConnectSkin.php000066600000001576152141020640011430 0ustar00 \esc_html__( 'There was an error installing WPForms Pro. Please try again.', 'wpforms-lite' ), ) ); die; } } } Lite/Admin/DashboardWidget.php000066600000032767152141020640012253 0ustar00settings(); $this->hooks(); } /** * Filterable widget settings. * * @since 1.5.0 */ public function settings() { $this->settings = array( // Number of forms to display in the forms list before "Show More" button appears. 'forms_list_number_to_display' => \apply_filters( 'wpforms_dash_widget_forms_list_number_to_display', 5 ), // Allow results caching to reduce DB load. 'allow_data_caching' => \apply_filters( 'wpforms_dash_widget_allow_data_caching', true ), // Transient lifetime in seconds. Defaults to the end of a current day. 'transient_lifetime' => \apply_filters( 'wpforms_dash_widget_transient_lifetime', \strtotime( 'tomorrow' ) - \time() ), // Determine if the forms with no entries should appear in a forms list. Once switched, the effect applies after cache expiration. 'display_forms_list_empty_entries' => \apply_filters( 'wpforms_dash_widget_display_forms_list_empty_entries', true ), ); } /** * Widget hooks. * * @since 1.5.0 */ public function hooks() { \add_action( 'admin_enqueue_scripts', array( $this, 'widget_scripts' ) ); \add_action( 'wp_dashboard_setup', array( $this, 'widget_register' ) ); \add_action( 'admin_init', array( $this, 'hide_widget' ) ); \add_action( 'wpforms_create_form', __CLASS__ . '::clear_widget_cache' ); \add_action( 'wpforms_save_form', __CLASS__ . '::clear_widget_cache' ); \add_action( 'wpforms_delete_form', __CLASS__ . '::clear_widget_cache' ); } /** * Load widget-specific scripts. * * @since 1.5.0 */ public function widget_scripts() { $screen = \get_current_screen(); if ( ! isset( $screen->id ) || 'dashboard' !== $screen->id ) { return; } $min = \wpforms_get_min_suffix(); \wp_enqueue_style( 'wpforms-dashboard-widget', \WPFORMS_PLUGIN_URL . "assets/css/dashboard-widget{$min}.css", array(), \WPFORMS_VERSION ); \wp_enqueue_script( 'wpforms-moment', \WPFORMS_PLUGIN_URL . 'assets/js/moment.min.js', array(), '2.22.2', true ); \wp_enqueue_script( 'wpforms-chart', \WPFORMS_PLUGIN_URL . 'assets/js/chart.min.js', array( 'wpforms-moment' ), '2.7.2', true ); \wp_enqueue_script( 'wpforms-dashboard-widget', \WPFORMS_PLUGIN_URL . "lite/assets/js/admin/dashboard-widget{$min}.js", array( 'jquery', 'wpforms-chart' ), \WPFORMS_VERSION, true ); \wp_localize_script( 'wpforms-dashboard-widget', 'wpforms_dashboard_widget', array( 'show_more_html' => \esc_html__( 'Show More', 'wpforms-lite' ) . '', 'show_less_html' => \esc_html__( 'Show Less', 'wpforms-lite' ) . '', 'i18n' => array( 'entries' => \esc_html__( 'Entries', 'wpforms-lite' ), ), ) ); } /** * Register the widget. * * @since 1.5.0 */ public function widget_register() { global $wp_meta_boxes; $widget_key = 'wpforms_reports_widget_lite'; \wp_add_dashboard_widget( $widget_key, \esc_html__( 'WPForms', 'wpforms-lite' ), array( $this, 'widget_content' ) ); // Attempt to place the widget at the top. $normal_dashboard = $wp_meta_boxes['dashboard']['normal']['core']; $widget_instance = array( $widget_key => $normal_dashboard[ $widget_key ] ); unset( $normal_dashboard[ $widget_key ] ); $sorted_dashboard = \array_merge( $widget_instance, $normal_dashboard ); $wp_meta_boxes['dashboard']['normal']['core'] = $sorted_dashboard; } /** * Load widget content. * * @since 1.5.0 */ public function widget_content() { $forms = \wpforms()->form->get( '', array( 'fields' => 'ids' ) ); echo '
'; if ( empty( $forms ) ) { $this->widget_content_no_forms_html(); } else { $this->widget_content_html(); } $plugins = \get_plugins(); if ( ! \array_key_exists( 'google-analytics-for-wordpress/googleanalytics.php', $plugins ) && ! \array_key_exists( 'google-analytics-premium/googleanalytics-premium.php', $plugins ) && ! empty( $forms ) ) { $this->recommended_plugin_block_html(); } echo '
'; } /** * Widget content HTML if a user has no forms. * * @since 1.5.0 */ public function widget_content_no_forms_html() { $create_form_url = \add_query_arg( 'page', 'wpforms-builder', \admin_url( 'admin.php' ) ); $learn_more_url = 'https://wpforms.com/docs/creating-first-form/?utm_source=WordPress&utm_medium=link&utm_campaign=liteplugin&utm_content=dashboardwidget'; ?>

forms_list_block(); ?>
get_entries_count_by_form(); if ( empty( $forms ) ) { $this->forms_list_block_empty_html(); } else { $this->forms_list_block_html( $forms ); } } /** * Empty forms list block HTML. * * @since 1.5.0 */ public function forms_list_block_empty_html() { ?>

settings['forms_list_number_to_display']; ?> $form ) : ?> = $show_forms ? 'class="wpforms-dash-widget-forms-list-hidden-el"' : ''; ?> data-form-id="">
$show_forms ) : ?> settings['allow_data_caching']; if ( $allow_caching ) { $transient_name = 'wpforms_dash_widget_lite_entries_by_form'; $cache = \get_transient( $transient_name ); // Filter the cache to clear or alter its data. $cache = \apply_filters( 'wpforms_dash_widget_lite_cached_data', $cache ); } // is_array() detects cached empty searches. if ( $allow_caching && \is_array( $cache ) ) { return $cache; } $forms = \wpforms()->form->get( '', array( 'fields' => 'ids' ) ); if ( empty( $forms ) || ! \is_array( $forms ) ) { return array(); } $result = array(); foreach ( $forms as $form_id ) { $count = \absint( \get_post_meta( $form_id, 'wpforms_entries_count', true ) ); if ( empty( $count ) && empty( $this->settings['display_forms_list_empty_entries'] ) ) { continue; } $result[ $form_id ] = array( 'form_id' => $form_id, 'count' => $count, 'title' => \get_the_title( $form_id ), ); } if ( ! empty( $result ) ) { // Sort forms by entries count (desc). \uasort( $result, function ( $a, $b ) { return ( $a['count'] > $b['count'] ) ? - 1 : 1; } ); } if ( $allow_caching ) { // Transient lifetime in seconds. Defaults to the end of a current day. $transient_lifetime = $this->settings['transient_lifetime']; \set_transient( $transient_name, $result, $transient_lifetime ); } return $result; } /** * Hide dashboard widget. * Use dashboard screen options to make it visible again. * * @since 1.5.0 */ public function hide_widget() { if ( ! \is_admin() || ! \is_user_logged_in() ) { return; } if ( ! isset( $_GET['wpforms-nonce'] ) || ! \wp_verify_nonce( \sanitize_key( \wp_unslash( $_GET['wpforms-nonce'] ) ), 'wpforms_hide_dash_widget' ) ) { return; } if ( ! isset( $_GET['wpforms-widget'] ) || 'hide' !== $_GET['wpforms-widget'] ) { return; } $user_id = \get_current_user_id(); $metaboxhidden = \get_user_meta( $user_id, 'metaboxhidden_dashboard', true ); if ( ! \is_array( $metaboxhidden ) ) { \update_user_meta( $user_id, 'metaboxhidden_dashboard', array( 'wpforms_reports_widget_lite' ) ); } if ( \is_array( $metaboxhidden ) && ! \in_array( 'wpforms_reports_widget_lite', $metaboxhidden, true ) ) { $metaboxhidden[] = 'wpforms_reports_widget_lite'; \update_user_meta( $user_id, 'metaboxhidden_dashboard', $metaboxhidden ); } $redirect_url = \remove_query_arg( array( 'wpforms-widget', 'wpforms-nonce' ) ); \wp_safe_redirect( $redirect_url ); exit(); } /** * Clear dashboard widget cached data. * * @since 1.5.2 */ public static function clear_widget_cache() { delete_transient( 'wpforms_dash_widget_lite_entries_by_form' ); } } Lite/Admin/Education.php000066600000006267152141020640011127 0ustar00hooks(); } /** * Hooks. * * @since 1.5.7 */ public function hooks() { if ( ! \wpforms_is_admin_page() && ! \wp_doing_ajax() ) { return; } if ( ! \apply_filters( 'wpforms_lite_admin_education', true ) ) { return; } // Admin page slug. $this->page = str_replace( 'wpforms-', '', filter_input( INPUT_GET, 'page', FILTER_SANITIZE_STRING ) ); \add_action( 'admin_init', array( $this, 'notice_bar_init' ) ); } /** * Notice bar init. * * @since 1.5.7 */ public function notice_bar_init() { \add_action( 'admin_enqueue_scripts', array( $this, 'enqueues' ) ); \add_action( 'wpforms_admin_header_before', array( $this, 'notice_bar_display' ) ); \add_action( 'wp_ajax_wpforms_notice_bar_dismiss', array( $this, 'notice_bar_ajax_dismiss' ) ); } /** * Notice bar display message. * * @since 1.5.7 */ public function notice_bar_display() { $current_user = \wp_get_current_user(); $dismissed = \get_user_meta( $current_user->ID, 'wpforms_dismissed', true ); if ( ! empty( $dismissed['lite-notice-bar'] ) ) { return; } $msg = sprintf( /* translators: %s - WPForms.com Upgrade page URL. */ __( 'You’re using WPForms Lite. To unlock more features consider upgrading to Pro.', 'wpforms-lite' ), \wpforms_admin_upgrade_link( 'notice-bar' ) ); printf( '
%s
', \wp_kses( $msg, array( 'a' => array( 'href' => array(), 'rel' => array(), 'target' => array(), ), ) ), \esc_attr__( 'Dismiss this message.', 'wpforms-lite' ), \esc_attr( $this->page ) ); } /** * Ajax handler for dismissing DYK notices. * * @since 1.5.7 */ public function notice_bar_ajax_dismiss() { // Run a security check. \check_ajax_referer( 'wpforms-admin', 'nonce' ); // Check for permissions. if ( ! \wpforms_current_user_can() ) { \wp_send_json_error( array( 'error' => \esc_html__( 'You do not have permission to perform this action.', 'wpforms-lite' ), ) ); } $current_user = \wp_get_current_user(); $dismissed = \get_user_meta( $current_user->ID, 'wpforms_dismissed', true ); if ( empty( $dismissed ) ) { $dismissed = array(); } $dismissed['lite-notice-bar'] = time(); \update_user_meta( $current_user->ID, 'wpforms_dismissed', $dismissed ); \wp_send_json_success(); } /** * Load enqueues. * * @since 1.5.7 */ public function enqueues() { $min = \wpforms_get_min_suffix(); \wp_enqueue_script( 'wpforms-lite-admin-education', \WPFORMS_PLUGIN_URL . "lite/assets/js/admin/education{$min}.js", array( 'jquery' ), \WPFORMS_VERSION, false ); } } Lite/Admin/Builder/Education.php000066600000054461152141020640012514 0ustar00hooks(); } /** * Hooks. * * @since 1.5.1 */ public function hooks() { if ( wp_doing_ajax() ) { add_action( 'wp_ajax_wpforms_dyk_dismiss', array( $this, 'dyk_ajax_dismiss' ) ); add_action( 'wp_ajax_wpforms_update_field_recaptcha', array( $this, 'recaptcha_field_callback' ) ); } // Only proceed for the form builder. if ( ! wpforms_is_admin_page( 'builder' ) ) { return; } add_action( 'wpforms_field_options_after_advanced-options', array( $this, 'field_conditional_logic' ), 10, 2 ); add_filter( 'wpforms_lite_builder_strings', array( $this, 'js_strings' ) ); add_action( 'wpforms_builder_enqueues_before', array( $this, 'enqueues' ) ); add_action( 'wpforms_setup_panel_after', array( $this, 'templates' ) ); add_filter( 'wpforms_builder_fields_buttons', array( $this, 'fields' ), 50 ); add_action( 'wpforms_builder_after_panel_sidebar', array( $this, 'settings' ), 100, 2 ); add_action( 'wpforms_providers_panel_sidebar', array( $this, 'providers' ), 50 ); add_action( 'wpforms_payments_panel_sidebar', array( $this, 'payments' ), 50 ); add_action( 'wpforms_builder_settings_notifications_after', array( $this, 'dyk_notifications' ) ); add_action( 'wpforms_builder_settings_confirmations_after', array( $this, 'dyk_confirmations' ) ); } /** * Localize needed strings. * * @since 1.5.1 * * @param array $strings JS strings. * * @return array */ public function js_strings( $strings ) { $strings['upgrade'] = [ 'pro' => [ 'title' => esc_html__( 'is a PRO Feature', 'wpforms-lite' ), 'message' => '

' . esc_html__( 'We\'re sorry, the %name% is not available on your plan. Please upgrade to the PRO plan to unlock all these awesome features.', 'wpforms-lite' ) . '

', 'bonus' => '

' . wp_kses( __( 'Bonus: WPForms Lite users get 50% off regular price, automatically applied at checkout.', 'wpforms-lite' ), [ 'strong' => [], 'span' => [], ] ) . '

', 'doc' => '' . esc_html__( 'Already purchased?', 'wpforms-lite' ) . '', 'button' => esc_html__( 'Upgrade to PRO', 'wpforms-lite' ), 'url' => wpforms_admin_upgrade_link( 'builder-modal', 'upgrade-pro' ), 'modal' => wpforms_get_upgrade_modal_text( 'pro' ), ], 'elite' => [ 'title' => esc_html__( 'is an Elite Feature', 'wpforms-lite' ), 'message' => '

' . esc_html__( 'We\'re sorry, the %name% is not available on your plan. Please upgrade to the Elite plan to unlock all these awesome features.', 'wpforms-lite' ) . '

', 'bonus' => '

' . wp_kses( __( 'Bonus: WPForms Lite users get 50% off regular price, automatically applied at checkout.', 'wpforms-lite' ), [ 'strong' => [], 'span' => [], ] ) . '

', 'doc' => '' . esc_html__( 'Already purchased?', 'wpforms-lite' ) . '', 'button' => esc_html__( 'Upgrade to Elite', 'wpforms-lite' ), 'url' => wpforms_admin_upgrade_link( 'builder-modal', 'upgrade-elite' ), 'modal' => wpforms_get_upgrade_modal_text( 'elite' ), ], ]; return $strings; } /** * Load enqueues. * * @since 1.5.1 */ public function enqueues() { $min = wpforms_get_min_suffix(); wp_enqueue_script( 'wpforms-builder-education', WPFORMS_PLUGIN_URL . "lite/assets/js/admin/builder-education{$min}.js", array( 'jquery', 'jquery-confirm' ), WPFORMS_VERSION, false ); } /** * Display templates. * * @since 1.5.1 */ public function templates() { $templates = array( array( 'name' => esc_html__( 'Request A Quote Form', 'wpforms-lite' ), 'slug' => 'request-quote', 'description' => esc_html__( 'Start collecting leads with this pre-made Request a quote form. You can add and remove fields as needed.', 'wpforms-lite' ), ), array( 'name' => esc_html__( 'Donation Form', 'wpforms-lite' ), 'slug' => 'donation', 'description' => esc_html__( 'Start collecting donation payments on your website with this ready-made Donation form. You can add and remove fields as needed.', 'wpforms-lite' ), ), array( 'name' => esc_html__( 'Billing / Order Form', 'wpforms-lite' ), 'slug' => 'order', 'description' => esc_html__( 'Collect payments for product and service orders with this ready-made form template. You can add and remove fields as needed.', 'wpforms-lite' ), ), ); ?>

'fa-google', 'name' => esc_html__( 'reCAPTCHA', 'wpforms-lite' ), 'type' => 'recaptcha', 'order' => 180, 'class' => 'not-draggable', ); $fields['fancy']['fields'] = array( array( 'icon' => 'fa-phone', 'name' => esc_html__( 'Phone', 'wpforms-lite' ), 'type' => 'phone', 'order' => '1', 'class' => 'upgrade-modal', ), array( 'icon' => 'fa-map-marker', 'name' => esc_html__( 'Address', 'wpforms-lite' ), 'type' => 'address', 'order' => '2', 'class' => 'upgrade-modal', ), array( 'icon' => 'fa-calendar-o', 'name' => esc_html__( 'Date / Time', 'wpforms-lite' ), 'type' => 'date-time', 'order' => '3', 'class' => 'upgrade-modal', ), array( 'icon' => 'fa-link', 'name' => esc_html__( 'Website / URL', 'wpforms-lite' ), 'type' => 'url', 'order' => '4', 'class' => 'upgrade-modal', ), array( 'icon' => 'fa-upload', 'name' => esc_html__( 'File Upload', 'wpforms-lite' ), 'type' => 'file-upload', 'order' => '5', 'class' => 'upgrade-modal', ), array( 'icon' => 'fa-lock', 'name' => esc_html__( 'Password', 'wpforms-lite' ), 'type' => 'password', 'order' => '6', 'class' => 'upgrade-modal', ), array( 'icon' => 'fa-files-o', 'name' => esc_html__( 'Page Break', 'wpforms-lite' ), 'type' => 'pagebreak', 'order' => '7', 'class' => 'upgrade-modal', ), array( 'icon' => 'fa-arrows-h', 'name' => esc_html__( 'Section Divider', 'wpforms-lite' ), 'type' => 'divider', 'order' => '8', 'class' => 'upgrade-modal', ), array( 'icon' => 'fa-eye-slash', 'name' => esc_html__( 'Hidden Field', 'wpforms-lite' ), 'type' => 'hidden', 'order' => '9', 'class' => 'upgrade-modal', ), array( 'icon' => 'fa-code', 'name' => esc_html__( 'HTML', 'wpforms-lite' ), 'type' => 'html', 'order' => '10', 'class' => 'upgrade-modal', ), array( 'icon' => 'fa-star', 'name' => esc_html__( 'Rating', 'wpforms-lite' ), 'type' => 'rating', 'order' => '11', 'class' => 'upgrade-modal', ), array( 'icon' => 'fa-question-circle', 'name' => esc_html__( 'Captcha', 'wpforms-lite' ), 'type' => 'captcha', 'order' => '12', 'class' => 'upgrade-modal', ), array( 'icon' => 'fa-pencil', 'name' => esc_html__( 'Signature', 'wpforms-lite' ), 'type' => 'signature', 'order' => '13', 'class' => 'upgrade-modal', ), array( 'icon' => 'fa-ellipsis-h', 'name' => esc_html__( 'Likert Scale', 'wpforms-lite' ), 'type' => 'likert_scale', 'order' => '14', 'class' => 'upgrade-modal', ), array( 'icon' => 'fa-tachometer', 'name' => esc_html__( 'Net Promoter Score', 'wpforms-lite' ), 'type' => 'net_promoter_score', 'order' => '15', 'class' => 'upgrade-modal', ), ); $fields['payment']['fields'] = array( array( 'icon' => 'fa-file-o', 'name' => esc_html__( 'Single Item', 'wpforms-lite' ), 'type' => 'payment-single', 'order' => '1', 'class' => 'upgrade-modal', ), array( 'icon' => 'fa-list-ul', 'name' => esc_html__( 'Multiple Items', 'wpforms-lite' ), 'type' => 'payment-multiple', 'order' => '2', 'class' => 'upgrade-modal', ), array( 'icon' => 'fa-check-square-o', 'name' => esc_html__( 'Checkbox Items', 'wpforms-lite' ), 'type' => 'payment-checkbox', 'order' => '3', 'class' => 'upgrade-modal', ), array( 'icon' => 'fa-caret-square-o-down', 'name' => esc_html__( 'Dropdown Items', 'wpforms-lite' ), 'type' => 'payment-select', 'order' => '4', 'class' => 'upgrade-modal', ), array( 'icon' => 'fa-money', 'name' => esc_html__( 'Total', 'wpforms-lite' ), 'type' => 'payment-total', 'order' => '5', 'class' => 'upgrade-modal', ), ); return $fields; } /** * Display conditional logic settings section for fields inside the form builder. * * @since 1.5.5 * * @param array $field Field data. * @param object $instance Builder instance. */ public function field_conditional_logic( $field, $instance ) { // Certain fields don't support conditional logic. if ( in_array( $field['type'], array( 'pagebreak', 'divider', 'hidden' ), true ) ) { return; } ?>
esc_html__( 'Conversational Forms', 'wpforms-lite' ), 'slug' => 'conversational-forms', 'plugin' => 'wpforms-conversational-forms/wpforms-conversational-forms.php', 'plugin_slug' => 'wpforms-conversational-forms', 'license' => 'pro', ), array( 'name' => esc_html__( 'Surveys and Polls', 'wpforms-lite' ), 'slug' => 'surveys-polls', 'plugin' => 'wpforms-surveys-polls/wpforms-surveys-polls.php', 'plugin_slug' => 'wpforms-surveys-polls', 'license' => 'pro', ), array( 'name' => esc_html__( 'Form Pages', 'wpforms-lite' ), 'slug' => 'form-pages', 'plugin' => 'wpforms-form-pages/wpforms-form-pages.php', 'plugin_slug' => 'wpforms-form-pages', 'license' => 'pro', ), array( 'name' => esc_html__( 'Form Locker', 'wpforms-lite' ), 'slug' => 'form-locker', 'plugin' => 'wpforms-form-locker/wpforms-form-locker.php', 'plugin_slug' => 'wpforms-form-locker', 'license' => 'pro', ), array( 'name' => esc_html__( 'Form Abandonment', 'wpforms-lite' ), 'slug' => 'form-abandonment', 'plugin' => 'wpforms-form-abandonment/wpforms-form-abandonment.php', 'plugin_slug' => 'wpforms-form-abandonment', 'license' => 'pro', ), array( 'name' => esc_html__( 'Post Submissions', 'wpforms-lite' ), 'slug' => 'post-submissions', 'plugin' => 'wpforms-post-submissions/wpforms-post-submissions.php', 'plugin_slug' => 'wpforms-post-submissions', 'license' => 'pro', ), ); foreach ( $settings as $setting ) { /* translators: %s - addon name. */ $modal_name = sprintf( esc_html__( '%s addon', 'wpforms' ), $setting['name'] ); printf( '', esc_attr( $setting['slug'] ), esc_attr( $modal_name ), esc_attr( $setting['license'] ) ); echo esc_html( $setting['name'] ); echo ''; echo ''; } } /** * Display providers. * * @since 1.5.1 */ public function providers() { $providers = wpforms_get_providers_all(); foreach ( $providers as $provider ) { $this->display_single_addon_btn( $provider ); } } /** * Display payments. * * @since 1.5.1 */ public function payments() { $payments = array( array( 'name' => esc_html__( 'PayPal Standard', 'wpforms-lite' ), 'slug' => 'paypal_standard', 'img' => 'addon-icon-paypal.png', 'license' => 'pro', ), array( 'name' => esc_html__( 'Stripe', 'wpforms-lite' ), 'slug' => 'stripe', 'img' => 'addon-icon-stripe.png', 'license' => 'pro', ), ); foreach ( $payments as $payment ) { $this->display_single_addon_btn( $payment ); } } /** * Display a single addon button in a builder. * * @since 1.5.7 * * @param array $addon Required keys: name, slug, img. */ protected function display_single_addon_btn( $addon ) { if ( ! isset( $addon['name'], $addon['slug'], $addon['img'], $addon['license'] ) ) { return; } /* translators: %s - addon name. */ $modal_name = sprintf( esc_html__( '%s addon', 'wpforms-lite' ), $addon['name'] ); ?> form->get( $form_id, array( 'content_only' => true ) ); if ( empty( $form_data ) ) { wp_send_json_error( esc_html__( 'Something wrong. Please, try again later.', 'wpforms-lite' ) ); } // Check that recaptcha is configured in the settings. $site_key = wpforms_setting( 'recaptcha-site-key' ); $secret_key = wpforms_setting( 'recaptcha-secret-key' ); $recaptcha_name = $this->get_recaptcha_name(); if ( empty( $recaptcha_name ) ) { wp_send_json_error( esc_html__( 'Something wrong. Please, try again later.', 'wpforms-lite' ) ); } // Prepare a result array. $data = array( 'current' => false, 'cases' => array( 'not_configured' => array( 'title' => esc_html__( 'Heads up!', 'wpforms-lite' ), 'content' => sprintf( wp_kses( /* translators: %1$s - reCaptcha settings page URL; %2$s - WPForms.com doc URL. */ __( 'Google reCAPTCHA isn\'t configured yet. Please complete the setup in your WPForms Settings, and check out our step by step tutorial for full details.', 'wpforms-lite' ), array( 'a' => array( 'href' => true, 'rel' => true, 'target' => true, ), ) ), esc_url( admin_url( 'admin.php?page=wpforms-settings&view=recaptcha' ) ), 'https://wpforms.com/docs/setup-captcha-wpforms/' ), ), 'configured_not_enabled' => array( 'title' => false, /* translators: %s - reCAPTCHA type. */ 'content' => sprintf( esc_html__( '%s has been enabled for this form. Don\'t forget to save your form!', 'wpforms-lite' ), $recaptcha_name ), ), 'configured_enabled' => array( 'title' => false, 'content' => esc_html__( 'Are you sure you want to disable Google reCAPTCHA for this form?', 'wpforms-lite' ), 'cancel' => true, ), ), ); if ( ! $site_key || ! $secret_key ) { // If reCAPTCHA is not configured in the WPForms plugin settings. $data['current'] = 'not_configured'; } elseif ( ! isset( $form_data['settings']['recaptcha'] ) || '1' !== $form_data['settings']['recaptcha'] ) { // If reCAPTCHA is configured in WPForms plugin settings, but wasn't set in form settings. $data['current'] = 'configured_not_enabled'; } else { // If reCAPTCHA is configured in WPForms plugin and form settings. $data['current'] = 'configured_enabled'; } wp_send_json_success( $data ); } /** * Retrive a reCAPTCHA type name. * * @since 1.5.8 * * @return string */ public function get_recaptcha_name() { $recaptcha_type = wpforms_setting( 'recaptcha-type', 'v2' ); // Get a recaptcha name. switch ( $recaptcha_type ) { case 'v2': $recaptcha_name = esc_html__( 'Google Checkbox v2 reCAPTCHA', 'wpforms-lite' ); break; case 'invisible': $recaptcha_name = esc_html__( 'Google Invisible v2 reCAPTCHA', 'wpforms-lite' ); break; case 'v3': $recaptcha_name = esc_html__( 'Google v3 reCAPTCHA', 'wpforms-lite' ); break; default: $recaptcha_name = ''; break; } return $recaptcha_name; } /** * "Did You Know?" Notifications. * * @since 1.5.8 */ public function dyk_notifications() { $this->dyk_display( 'notifications', array( 'desc' => esc_html__( 'You can have multiple notifications with conditional logic.', 'wpforms-lite' ), ) ); } /** * "Did You Know?" Notifications. * * @since 1.5.8 */ public function dyk_confirmations() { $this->dyk_display( 'confirmations', array( 'desc' => esc_html__( 'You can have multiple confirmations with conditional logic.', 'wpforms-lite' ), ) ); } /** * "Did You Know?" display message. * * @since 1.5.8 * * @param string $section Form builder section/area (slug). * @param array $settings Notice settings array. */ public function dyk_display( $section, $settings ) { $current_user = wp_get_current_user(); $dismissed = get_user_meta( $current_user->ID, 'wpforms_dismissed', true ); // Check if not dismissed. if ( ! empty( $dismissed[ 'dyk-builder-' . $section ] ) ) { return; } $translations = array( 'upgrade_to_pro' => __( 'Upgrade to Pro.', 'wpforms' ), 'dismiss_title' => __( 'Dismiss this message.', 'wpforms' ), 'did_you_know' => __( 'Did You Know?', 'wpforms' ), 'learn_more' => __( 'Learn More', 'wpforms' ), ); $learn_more = ( ! empty( $settings['more'] ) ) ? '' . esc_html( $translations['learn_more'] ) . '' : ''; printf( '
%s
%s
%s %s
', esc_html( $translations['did_you_know'] ), esc_html( $settings['desc'] ), $learn_more, // phpcs:ignore esc_url( wpforms_admin_upgrade_link( 'Form Builder DYK', ucfirst( $section ) ) ), esc_html( $translations['upgrade_to_pro'] ), esc_attr( $translations['dismiss_title'] ), esc_attr( $section ) ); } /** * Ajax handler for dismissing DYK notices. * * @since 1.5.8 */ public function dyk_ajax_dismiss() { // Run a security check. check_ajax_referer( 'wpforms-builder', 'nonce' ); // Check for permissions. if ( ! wpforms_current_user_can() ) { wp_send_json_error( array( 'error' => esc_html__( 'You do not have permission to perform this action.', 'wpforms-lite' ), ) ); } $current_user = wp_get_current_user(); $dismissed = get_user_meta( $current_user->ID, 'wpforms_dismissed', true ); if ( empty( $dismissed ) ) { $dismissed = array(); } $section = ! empty( $_GET['section'] ) ? sanitize_key( wp_unslash( $_GET['section'] ) ) : ''; $dismissed[ 'dyk-builder-' . $section ] = time(); update_user_meta( $current_user->ID, 'wpforms_dismissed', $dismissed ); wp_send_json_success(); } } Lite/Admin/Settings/Education.php000066600000011327152141020640012720 0ustar00hooks(); } /** * Hooks. * * @since 1.5.1 */ public function hooks() { // Only proceed for the Settings > Integrations tab. if ( ! \wpforms_is_admin_page( 'settings' ) ) { return; } // Integrations related hooks. if ( \wpforms_is_admin_page( 'settings', 'integrations' ) ) { \add_filter( 'wpforms_admin_strings', array( $this, 'js_strings' ) ); \add_action( 'admin_enqueue_scripts', array( $this, 'enqueues' ) ); \add_action( 'wpforms_settings_providers', array( $this, 'providers' ), 10000, 1 ); } } /** * Localize needed strings. * * @since 1.5.5 * * @param array $strings JS strings. * * @return array */ public function js_strings( $strings ) { $strings['upgrade'] = [ 'pro' => [ 'title' => esc_html__( 'is a PRO Feature', 'wpforms-lite' ), 'message' => '

' . esc_html__( 'We\'re sorry, the %name% is not available on your plan. Please upgrade to the PRO plan to unlock all these awesome features.', 'wpforms-lite' ) . '

', 'bonus' => '

' . wp_kses( __( 'Bonus: WPForms Lite users get 50% off regular price, automatically applied at checkout.', 'wpforms-lite' ), [ 'strong' => [], 'span' => [], ] ) . '

', 'doc' => '' . esc_html__( 'Already purchased?', 'wpforms-lite' ) . '', 'button' => esc_html__( 'Upgrade to PRO', 'wpforms-lite' ), 'url' => wpforms_admin_upgrade_link( 'settings-modal', 'upgrade-pro' ), 'modal' => wpforms_get_upgrade_modal_text( 'pro' ), ], 'elite' => [ 'title' => esc_html__( 'is an Elite Feature', 'wpforms-lite' ), 'message' => '

' . esc_html__( 'We\'re sorry, the %name% is not available on your plan. Please upgrade to the Elite plan to unlock all these awesome features.', 'wpforms-lite' ) . '

', 'bonus' => '

' . wp_kses( __( 'Bonus: WPForms Lite users get 50% off regular price, automatically applied at checkout.', 'wpforms-lite' ), [ 'strong' => [], 'span' => [], ] ) . '

', 'doc' => '' . esc_html__( 'Already purchased?', 'wpforms-lite' ) . '', 'button' => esc_html__( 'Upgrade to Elite', 'wpforms-lite' ), 'url' => wpforms_admin_upgrade_link( 'settings-modal', 'upgrade-elite' ), 'modal' => wpforms_get_upgrade_modal_text( 'elite' ), ], ]; return $strings; } /** * Load enqueues. * * @since 1.5.5 */ public function enqueues() { $min = \wpforms_get_min_suffix(); \wp_enqueue_script( 'wpforms-settings-education', \WPFORMS_PLUGIN_URL . "lite/assets/js/admin/settings-education{$min}.js", array( 'jquery', 'jquery-confirm' ), \WPFORMS_VERSION, false ); } /** * Display providers. * * @since 1.5.5 */ public function providers() { $providers = wpforms_get_providers_all(); foreach ( $providers as $provider ) { /* translators: %s - addon name*/ $modal_name = sprintf( \__( '%s addon', 'wpforms' ), $provider['name'] ); /* translators: %s - addon name*/ $descr = sprintf( \__( 'Integrate %s with WPForms', 'wpforms' ), $provider['name'] ); printf( '

%6$s

%7$s

', \esc_attr( $provider['slug'] ), \esc_attr( $modal_name ), isset( $provider['url'] ) ? \esc_attr( $provider['url'] ) : '', \esc_attr( $provider['license'] ), '', \esc_html( $provider['name'] ), \esc_html( $descr ) ); } } } Lite/Admin/Settings/Access.php000066600000014242152141020640012205 0ustar00hooks(); } /** * Hooks. * * @since 1.5.8 */ public function hooks() { add_action( 'admin_enqueue_scripts', array( $this, 'enqueues' ) ); add_filter( 'wpforms_settings_tabs', array( $this, 'add_tab' ) ); add_filter( 'wpforms_settings_defaults', array( $this, 'add_section' ) ); } /** * Enqueues. * * @since 1.5.8 */ public function enqueues() { if ( ! wpforms_is_admin_page( 'settings', self::SLUG ) ) { return; } // Lity. wp_enqueue_style( 'wpforms-lity', WPFORMS_PLUGIN_URL . 'assets/css/lity.min.css', null, '3.0.0' ); wp_enqueue_script( 'wpforms-lity', WPFORMS_PLUGIN_URL . 'assets/js/lity.min.js', array( 'jquery' ), '3.0.0', true ); } /** * Add Access tab. * * @since 1.5.8 * * @param array $tabs Array of tabs. * * @return array Array of tabs. */ public function add_tab( $tabs ) { $tab = array( self::SLUG => array( 'name' => esc_html__( 'Access', 'wpforms-lite' ), 'form' => false, 'submit' => false, ), ); return wpforms_list_insert_after( $tabs, 'integrations', $tab ); } /** * Add Access settings section. * * @since 1.5.8 * * @param array $settings Settings sections. * * @return array */ public function add_section( $settings ) { $section_rows = array( 'heading', 'screenshots', 'caps', 'upgrade_to_pro', ); foreach ( $section_rows as $section_row ) { $settings[ self::SLUG ][ self::SLUG . '-' . $section_row ] = array( 'id' => self::SLUG . '-' . $section_row, 'content' => method_exists( $this, 'output_section_row_' . $section_row ) ? $this->{ 'output_section_row_' . $section_row }() : '', 'type' => 'content', 'no_label' => true, 'class' => array( $section_row ), ); } return $settings; } /** * Generate and output section "Heading" row HTML. * * @since 1.5.8 */ public function output_section_row_heading() { return sprintf( '

%1$s%3$s

%4$s

%5$s

', esc_html__( 'Access Controls', 'wpforms-lite' ), esc_url( WPFORMS_PLUGIN_URL . 'assets/images/lite-settings-access/pro-plus.svg' ), esc_attr__( 'Pro+', 'wpforms-lite' ), esc_html__( 'Access controls allows you to manage and customize access to WPForms functionality.', 'wpforms-lite' ), esc_html__( 'You can easily grant or restrict access using the simple built-in controls, or use our official integrations with Members and User Role Editor plugins.', 'wpforms-lite' ) ); } /** * Generate and output section "Screenshots" row HTML. * * @since 1.5.8 */ public function output_section_row_screenshots() { $format = '
%6$s %5$s
'; $images_url = WPFORMS_PLUGIN_URL . 'assets/images/lite-settings-access/'; $content = sprintf( $format, esc_url( $images_url . 'thumbnail-access-controls.png' ), esc_url( $images_url . 'thumbnail-access-controls@2x.png' ), esc_url( $images_url . 'screenshot-access-controls.png' ), esc_url( $images_url . 'screenshot-access-controls@2x.png' ), esc_html__( 'Simple Built-in Controls', 'wpforms-lite' ), esc_attr( esc_html__( 'Simple Built-in Controls', 'wpforms-lite' ) ) ); $content .= sprintf( $format, esc_url( $images_url . 'thumbnail-members.png' ), esc_url( $images_url . 'thumbnail-members@2x.png' ), esc_url( $images_url . 'screenshot-members.png' ), esc_url( $images_url . 'screenshot-members@2x.png' ), esc_html__( 'Members Integration', 'wpforms-lite' ), esc_attr( esc_html__( 'Members Integration', 'wpforms-lite' ) ) ); $content .= sprintf( $format, esc_url( $images_url . 'thumbnail-user-role-editor.png' ), esc_url( $images_url . 'thumbnail-user-role-editor@2x.png' ), esc_url( $images_url . 'screenshot-user-role-editor.png' ), esc_url( $images_url . 'screenshot-user-role-editor@2x.png' ), esc_html__( 'User Role Editor Integration', 'wpforms-lite' ), esc_attr( esc_html__( 'User Role Editor Integration', 'wpforms-lite' ) ) ); return $content; } /** * Generate and output section "Capabilities" row HTML. * * @since 1.5.8 */ public function output_section_row_caps() { $caps = array( array( esc_html__( 'Create Forms', 'wpforms-lite' ), esc_html__( 'Edit Forms', 'wpforms-lite' ), esc_html__( 'Edit Others Forms', 'wpforms-lite' ), esc_html__( 'View Forms', 'wpforms-lite' ), esc_html__( 'View Others Forms', 'wpforms-lite' ), ), array( esc_html__( 'Delete Forms', 'wpforms-lite' ), esc_html__( 'Delete Others Forms', 'wpforms-lite' ), esc_html__( 'View Forms Entries', 'wpforms-lite' ), esc_html__( 'View Others Forms Entries', 'wpforms-lite' ), ), array( esc_html__( 'Edit Forms Entries', 'wpforms-lite' ), esc_html__( 'Edit Others Forms Entries', 'wpforms-lite' ), esc_html__( 'Delete Forms Entries', 'wpforms-lite' ), esc_html__( 'Delete Others Forms Entries', 'wpforms-lite' ), ), ); $content = '

' . esc_html__( 'Custom access to the following capabilities…', 'wpforms-lite' ) . '

'; foreach ( $caps as $column ) { $content .= ''; } return $content; } /** * Generate and output section "Upgrade to Pro" row HTML. * * @since 1.5.8 */ public function output_section_row_upgrade_to_pro() { $content = sprintf( '%2$s', esc_url( 'https://wpforms.com/lite-upgrade/?discount=LITEUPGRADE&utm_source=WordPress&utm_medium=settings-license&utm_campaign=liteplugin' ), esc_html__( 'Upgrade to WPForms Now', 'wpforms-lite' ) ); return $content; } } Lite/Reports/EntriesCount.php000066600000002124152141020640012230 0ustar00form->get( '', array( 'fields' => 'ids' ) ); if ( empty( $forms ) || ! \is_array( $forms ) ) { return array(); } $result = array(); foreach ( $forms as $form_id ) { $count = \absint( \get_post_meta( $form_id, 'wpforms_entries_count', true ) ); if ( empty( $count ) ) { continue; } $result[ $form_id ] = array( 'form_id' => $form_id, 'count' => $count, 'title' => \get_the_title( $form_id ), ); } if ( ! empty( $result ) ) { // Sort forms by entries count (desc). \uasort( $result, function ( $a, $b ) { return ( $a['count'] > $b['count'] ) ? -1 : 1; } ); } return $result; } } Emails/Mailer.php000066600000023442152141020640007704 0ustar00$key = $value; } /** * Get a property. * * @since 1.5.4 * * @param string $key Property name. * * @return string */ public function __get( $key ) { return $this->$key; } /** * Check if a property exists. * * @since 1.5.4 * * @param string $key Property name. * * @return bool */ public function __isset( $key ) { return isset( $this->key ); } /** * Unset a property. * * @since 1.5.4 * * @param string $key Property name. */ public function __unset( $key ) { unset( $this->key ); } /** * Email kill switch if needed. * * @since 1.5.4 * * @return bool */ public function is_email_disabled() { return (bool) \apply_filters( 'wpforms_emails_mailer_is_email_disabled', false, $this ); } /** * Sanitize the string. * * @uses \wpforms_decode_string() * * @since 1.5.4 * @since 1.6.0 Deprecated param: $linebreaks. This is handled by wpforms_decode_string(). * * @param string $string String that may contain tags. * * @return string */ public function sanitize( $string = '' ) { return \wpforms_decode_string( $string ); } /** * Get the email from name. * * @since 1.5.4 * * @return string */ public function get_from_name() { $this->from_name = $this->from_name ? $this->sanitize( $this->from_name ) : \get_bloginfo( 'name' ); return \apply_filters( 'wpforms_emails_mailer_get_from_name', $this->from_name, $this ); } /** * Get the email from address. * * @since 1.5.4 * * @return string */ public function get_from_address() { $this->from_address = $this->from_address ? $this->sanitize( $this->from_address ) : \get_option( 'admin_email' ); return \apply_filters( 'wpforms_emails_mailer_get_from_address', $this->from_address, $this ); } /** * Get the email reply to address. * * @since 1.5.4 * * @return string */ public function get_reply_to_address() { if ( empty( $this->reply_to ) || ! \is_email( $this->reply_to ) ) { $this->reply_to = $this->from_address; } $this->reply_to = $this->sanitize( $this->reply_to ); if ( empty( $this->reply_to ) || ! \is_email( $this->reply_to ) ) { $this->reply_to = \get_option( 'admin_email' ); } return \apply_filters( 'wpforms_emails_mailer_get_reply_to_address', $this->reply_to, $this ); } /** * Get the email carbon copy addresses. * * @since 1.5.4 * * @return string The email carbon copy addresses. */ public function get_cc_address() { if ( empty( $this->cc ) ) { return \apply_filters( 'wpforms_emails_mailer_get_cc_address', $this->cc, $this ); } $this->cc = $this->sanitize( $this->cc ); $addresses = \array_map( 'trim', \explode( ',', $this->cc ) ); foreach ( $addresses as $key => $address ) { if ( ! \is_email( $address ) ) { unset( $addresses[ $key ] ); } } $this->cc = \implode( ',', $addresses ); return \apply_filters( 'wpforms_emails_mailer_get_cc_address', $this->cc, $this ); } /** * Get the email content type. * * @since 1.5.4 * * @return string The email content type. */ public function get_content_type() { $is_html = 'default' === \wpforms_setting( 'email-template', 'default' ); if ( ! $this->content_type && $is_html ) { $this->content_type = \apply_filters( 'wpforms_emails_mailer_get_content_type_default', 'text/html', $this ); } elseif ( ! $is_html ) { $this->content_type = 'text/plain'; } return \apply_filters( 'wpforms_emails_mailer_get_content_type', $this->content_type, $this ); } /** * Get the email message. * * @since 1.5.4 * * @return string The email message. */ public function get_message() { if ( empty( $this->message ) && ! empty( $this->template ) ) { $this->message = $this->template->get(); } return \apply_filters( 'wpforms_emails_mailer_get_message', $this->message, $this ); } /** * Get the email headers. * * @since 1.5.4 * * @return string The email headers. */ public function get_headers() { if ( $this->headers ) { return \apply_filters( 'wpforms_emails_mailer_get_headers', $this->headers, $this ); } $this->headers = "From: {$this->get_from_name()} <{$this->get_from_address()}>\r\n"; if ( $this->get_reply_to_address() ) { $this->headers .= "Reply-To: {$this->get_reply_to_address()}\r\n"; } if ( $this->get_cc_address() ) { $this->headers .= "Cc: {$this->get_cc_address()}\r\n"; } $this->headers .= "Content-Type: {$this->get_content_type()}; charset=utf-8\r\n"; return \apply_filters( 'wpforms_emails_mailer_get_headers', $this->headers, $this ); } /** * Get the email attachments. * * @since 1.5.4 * * @return string */ public function get_attachments() { return \apply_filters( 'wpforms_emails_mailer_get_attachments', $this->attachments, $this ); } /** * Set email address to send to. * * @since 1.5.4 * * @param string $email Email address. * * @return Mailer */ public function to_email( $email ) { $this->to_email = \apply_filters( 'wpforms_emails_mailer_to_email', $email, $this ); return $this; } /** * Set email subject. * * @since 1.5.4 * * @param string $subject Email subject. * * @return Mailer */ public function subject( $subject ) { $subject = $this->sanitize( $subject ); $this->subject = \apply_filters( 'wpforms_emails_mailer_subject', $subject, $this ); return $this; } /** * Set email message (body). * * @since 1.5.4 * * @param string $message Email message. * * @return Mailer */ public function message( $message ) { $this->message = \apply_filters( 'wpforms_emails_mailer_message', $message, $this ); return $this; } /** * Set email template. * * @since 1.5.4 * * @param General $template Email template. * * @return Mailer */ public function template( General $template ) { $this->template = \apply_filters( 'wpforms_emails_mailer_template', $template, $this ); return $this; } /** * Get email errors. * * @since 1.5.4 * * @return array */ protected function get_errors() { $errors = array(); if ( ! \is_email( $this->to_email ) ) { $errors[] = \esc_html__( '[WPForms\Emails\Mailer] Invalid email address.', 'wpforms-lite' ); } if ( empty( $this->subject ) ) { $errors[] = \esc_html__( '[WPForms\Emails\Mailer] Empty subject line.', 'wpforms-lite' ); } if ( empty( $this->get_message() ) ) { $errors[] = \esc_html__( '[WPForms\Emails\Mailer] Empty message.', 'wpforms-lite' ); } return $errors; } /** * Log given email errors. * * @since 1.5.4 * * @param array $errors Errors to log. */ protected function log_errors( $errors ) { if ( empty( $errors ) || ! \is_array( $errors ) ) { return; } foreach ( $errors as $error ) { \wpforms_log( $error, array( 'to_email' => $this->to_email, 'subject' => $this->subject, 'message' => \wp_trim_words( $this->get_message() ), ), array( 'type' => 'error', ) ); } } /** * Send the email. * * @since 1.5.4 * * @return bool */ public function send() { if ( ! \did_action( 'init' ) && ! \did_action( 'admin_init' ) ) { \_doing_it_wrong( __FUNCTION__, \esc_html__( 'You cannot send emails with WPForms\Emails\Mailer until init/admin_init has been reached.', 'wpforms-lite' ), null ); return false; } // Don't send anything if emails have been disabled. if ( $this->is_email_disabled() ) { return false; } $errors = $this->get_errors(); if ( $errors ) { $this->log_errors( $errors ); return false; } $this->send_before(); $sent = \wp_mail( $this->to_email, $this->subject, $this->get_message(), $this->get_headers(), $this->get_attachments() ); $this->send_after(); return $sent; } /** * Add filters / actions before the email is sent. * * @since 1.5.4 */ public function send_before() { \do_action( 'wpforms_emails_mailer_send_before', $this ); \add_filter( 'wp_mail_from', array( $this, 'get_from_address' ) ); \add_filter( 'wp_mail_from_name', array( $this, 'get_from_name' ) ); \add_filter( 'wp_mail_content_type', array( $this, 'get_content_type' ) ); } /** * Remove filters / actions after the email is sent. * * @since 1.5.4 */ public function send_after() { \do_action( 'wpforms_emails_mailer_send_after', $this ); \remove_filter( 'wp_mail_from', array( $this, 'get_from_address' ) ); \remove_filter( 'wp_mail_from_name', array( $this, 'get_from_name' ) ); \remove_filter( 'wp_mail_content_type', array( $this, 'get_content_type' ) ); } } Emails/InfoBlocks.php000066600000006732152141020640010527 0ustar00verify_fetched( $body ); } /** * Verify fetched blocks data. * * @since 1.5.4 * * @param array $fetched Fetched blocks data. * * @return array */ protected function verify_fetched( $fetched ) { $info = array(); if ( ! \is_array( $fetched ) ) { return $info; } foreach ( $fetched as $item ) { if ( empty( $item['id'] ) ) { continue; } $id = \absint( $item['id'] ); if ( empty( $id ) ) { continue; } $info[ $id ] = $item; } return $info; } /** * Get info blocks relevant to customer's licence. * * @since 1.5.4 * * @return array */ protected function get_by_license() { $data = $this->fetch_all(); $filtered = array(); if ( empty( $data ) || ! \is_array( $data ) ) { return $filtered; } $license_type = \wpforms_setting( 'type', false, 'wpforms_license' ); foreach ( $data as $key => $item ) { if ( ! isset( $item['type'] ) || ! \is_array( $item['type'] ) ) { continue; } if ( ! \in_array( $license_type, $item['type'], true ) ) { continue; } $filtered[ $key ] = $item; } return $filtered; } /** * Get the first block with a valid id. * Needed to ignore blocks with invalid/missing ids. * * @since 1.5.4 * * @param array $data Blocks array. * * @return array */ protected function get_first_with_id( $data ) { if ( empty( $data ) || ! \is_array( $data ) ) { return array(); } foreach ( $data as $item ) { $item_id = \absint( $item['id'] ); if ( ! empty( $item_id ) ) { return $item; } } return array(); } /** * Get next info block that wasn't sent yet. * * @since 1.5.4 * * @return array */ public function get_next() { $data = $this->get_by_license(); $block = array(); if ( empty( $data ) || ! \is_array( $data ) ) { return $block; } $blocks_sent = \get_option( 'wpforms_emails_infoblocks_sent' ); if ( empty( $blocks_sent ) || ! \is_array( $blocks_sent ) ) { $block = $this->get_first_with_id( $data ); } if ( empty( $block ) ) { $data = \array_diff_key( $data, \array_flip( $blocks_sent ) ); $block = $this->get_first_with_id( $data ); } return $block; } /** * Register a block as sent. * * @since 1.5.4 * * @param array $info_block Info block. */ public function register_sent( $info_block ) { $block_id = isset( $info_block['id'] ) ? \absint( $info_block['id'] ) : false; if ( empty( $block_id ) ) { return; } $option_name = 'wpforms_email_summaries_info_blocks_sent'; $blocks = \get_option( $option_name ); if ( empty( $blocks ) || ! \is_array( $blocks ) ) { \update_option( $option_name, array( $block_id ) ); return; } if ( \in_array( $block_id, $blocks, true ) ) { return; } $blocks[] = $block_id; \update_option( $option_name, $blocks ); } } Emails/Templates/General.php000066600000021446152141020640012010 0ustar00set_message( $message ); $this->plain_text = 'default' !== \wpforms_setting( 'email-template', 'default' ); $this->set_initial_args(); } /** * Set initial arguments to use in a template. * * @since 1.5.4 */ public function set_initial_args() { $header_args = array( 'title' => \esc_html__( 'WPForms', 'wpforms-lite' ), ); if ( ! $this->plain_text ) { $header_args['header_image'] = $this->get_header_image(); } $args = array( 'header' => $header_args, 'body' => array( 'message' => $this->get_message() ), 'footer' => array(), 'style' => array(), ); $args = \apply_filters( 'wpforms_emails_templates_general_set_initial_args', $args, $this ); $this->set_args( $args ); } /** * Get the template slug. * * @since 1.5.4 * * @return string */ public function get_slug() { return static::TEMPLATE_SLUG; } /** * Get the template parent slug. * * @since 1.5.4 * * @return string */ public function get_parent_slug() { return self::TEMPLATE_SLUG; } /** * Get the message. * * @since 1.5.4 * * @return string */ public function get_message() { return \apply_filters( 'wpforms_emails_templates_general_get_message', $this->message, $this ); } /** * Get the dynamic tags. * * @since 1.5.4 * * @return array */ public function get_tags() { return \apply_filters( 'wpforms_emails_templates_general_get_tags', $this->tags, $this ); } /** * Get header/footer/body arguments * * @since 1.5.4 * * @param string $type Header/footer/body. * * @return array */ public function get_args( $type ) { if ( ! empty( $type ) ) { return isset( $this->args[ $type ] ) ? \apply_filters( 'wpforms_emails_templates_general_get_args_' . $type, $this->args[ $type ], $this ) : array(); } return \apply_filters( 'wpforms_emails_templates_general_get_args', $this->args, $this ); } /** * Set email message. * * @since 1.5.4 * * @param string $message Email message. * * @return General */ public function set_message( $message ) { $message = \apply_filters( 'wpforms_emails_templates_general_set_message', $message, $this ); if ( ! \is_string( $message ) ) { return $this; } $this->message = $message; return $this; } /** * Set the dynamic tags. * * @since 1.5.4 * * @param array $tags Tags to set. * * @return General */ public function set_tags( $tags ) { $tags = \apply_filters( 'wpforms_emails_templates_general_set_tags', $tags, $this ); if ( ! \is_array( $tags ) ) { return $this; } $this->tags = $tags; return $this; } /** * Set header/footer/body/style arguments to use in a template. * * @since 1.5.4 * * @param array $args Arguments to set. * @param bool $merge Merge the arguments with existing once or replace. * * @return General */ public function set_args( $args, $merge = true ) { $args = \apply_filters( 'wpforms_emails_templates_general_set_args', $args, $this ); if ( empty( $args ) || ! \is_array( $args ) ) { return $this; } foreach ( $args as $type => $value ) { if ( ! \is_array( $value ) ) { continue; } if ( ! isset( $this->args[ $type ] ) || ! \is_array( $this->args[ $type ] ) ) { $this->args[ $type ] = array(); } $this->args[ $type ] = $merge ? \array_merge( $this->args[ $type ], $value ) : $value; } return $this; } /** * Process and replace any dynamic tags. * * @since 1.5.4 * * @param string $content Content to make replacements in. * * @return string */ public function process_tags( $content ) { $tags = $this->get_tags(); if ( empty( $tags ) ) { return $content; } foreach ( $tags as $tag => $value ) { $content = \str_replace( $tag, $value, $content ); } return $content; } /** * Conditionally modify email template name. * * @since 1.5.4 * * @param string $name Base template name. * * @return string */ protected function get_full_template_name( $name ) { $name = \sanitize_file_name( $name ); if ( $this->plain_text ) { $name .= '-plain'; } $template = 'emails/' . $this->get_slug() . '-' . $name; if ( ! Templates::locate( $template . '.php' ) ) { $template = 'emails/' . $this->get_parent_slug() . '-' . $name; } return \apply_filters( 'wpforms_emails_templates_general_get_full_template_name', $template, $this ); } /** * Get header image URL from settings. * * @since 1.5.4 * * @return array */ protected function get_header_image() { /** * Additional 'width' key with an integer value can be added to $img array to control image's width in pixels. * This setting helps to scale an image in some versions of MS Outlook and old email clients. * Percentage 'width' values have no effect in MS Outlook and will be sanitized as integer by an email template.. * * Example: * * $img = array( * 'url' => \wpforms_setting( 'email-header-image' ), * 'width' => 150, * ); * * * To set percentage values for the modern email clients, use $this->set_args() method: * * $this->set_args( * array( * 'style' => array( * 'header_image_max_width' => '45%', * ), * ) *); * * Both pixel and percentage approaches work well with 'wpforms_emails_templates_general_get_header_image' filter or this class extension. */ $img = array( 'url' => \wpforms_setting( 'email-header-image' ), ); return \apply_filters( 'wpforms_emails_templates_general_get_header_image', $img, $this ); } /** * Get content part HTML. * * @since 1.5.4 * * @param string $name Name of the content part. * * @return string */ protected function get_content_part( $name ) { if ( ! \is_string( $name ) ) { return ''; } $html = Templates::get_html( $this->get_full_template_name( $name ), $this->get_args( $name ), true ); return \apply_filters( 'wpforms_emails_templates_general_get_content_part', $html, $name, $this ); } /** * Assemble all content parts in an array. * * @since 1.5.4 * * @return array */ protected function get_content_parts() { $parts = array( 'header' => $this->get_content_part( 'header' ), 'body' => $this->get_content_part( 'body' ), 'footer' => $this->get_content_part( 'footer' ), ); return \apply_filters( 'wpforms_emails_templates_general_get_content_parts', $parts, $this ); } /** * Apply inline styling and save email content. * * @since 1.5.4 * * @param string $content Content with no styling applied. */ protected function save_styled( $content ) { if ( empty( $content ) ) { $this->content = ''; return; } if ( $this->plain_text ) { $this->content = \wp_strip_all_tags( $content ); return; } $style_templates = array( 'style' => $this->get_full_template_name( 'style' ), 'queries' => $this->get_full_template_name( 'queries' ), ); $styler = new Styler( $content, $style_templates, $this->get_args( 'style' ) ); $this->content = \apply_filters( 'wpforms_emails_templates_general_save_styled_content', $styler->get(), $this ); } /** * Build an email including styling. * * @since 1.5.4 * * @param bool $force Rebuild the content if it was already built and saved. */ protected function build( $force = false ) { if ( $this->content && ! $force ) { return; } $content = \implode( $this->get_content_parts() ); if ( empty( $content ) ) { return; } $content = $this->process_tags( $content ); if ( ! $this->plain_text ) { $content = \make_clickable( $content ); } $content = \apply_filters( 'wpforms_emails_templates_general_build_content', $content, $this ); $this->save_styled( $content ); } /** * Return final email. * * @since 1.5.4 * * @param bool $force Rebuild the content if it was already built and saved. * * @return string */ public function get( $force = false ) { $this->build( $force ); return $this->content; } } Emails/Templates/Summary.php000066600000001573152141020640012067 0ustar00 \wpforms_setting( 'email-header-image' ), ); if ( ! empty( $img['url'] ) ) { return $img; } // Set specific percentage WPForms logo width for modern email clients. $this->set_args( array( 'style' => array( 'header_image_max_width' => '45%', ), ) ); // Set specific WPForms logo width in pixels for MS Outlook and old email clients. return array( 'url' => \WPFORMS_PLUGIN_URL . 'assets/images/logo.png', 'width' => 250, ); } } Emails/Summaries.php000066600000012657152141020640010446 0ustar00hooks(); $summaries_disabled = $this->is_disabled(); if ( $summaries_disabled && \wp_next_scheduled( 'wpforms_email_summaries_cron' ) ) { \wp_clear_scheduled_hook( 'wpforms_email_summaries_cron' ); } if ( ! $summaries_disabled && ! \wp_next_scheduled( 'wpforms_email_summaries_cron' ) ) { \wp_schedule_event( $this->get_first_cron_date_gmt(), 'wpforms_email_summaries_weekly', 'wpforms_email_summaries_cron' ); } } /** * Get the instance of a class and store it in itself. * * @since 1.5.4 */ public static function get_instance() { static $instance; if ( ! $instance ) { $instance = new self(); } return $instance; } /** * Email Summaries hooks. * * @since 1.5.4 */ public function hooks() { \add_filter( 'wpforms_settings_defaults', array( $this, 'disable_summaries_setting' ) ); if ( ! $this->is_disabled() ) { \add_action( 'init', array( $this, 'preview' ) ); \add_filter( 'cron_schedules', array( $this, 'add_weekly_cron_schedule' ) ); \add_action( 'wpforms_email_summaries_cron', array( $this, 'cron' ) ); } } /** * Check if Email Summaries are disabled in settings. * * @since 1.5.4 * * @return bool */ protected function is_disabled() { return (bool) apply_filters( 'wpforms_emails_summaries_is_disabled', (bool) \wpforms_setting( 'email-summaries-disable' ) ); } /** * Add "Disable Email Summaries" to WPForms settings. * * @since 1.5.4 * * @param array $settings WPForms settings. * * @return mixed */ public function disable_summaries_setting( $settings ) { if ( (bool) apply_filters( 'wpforms_emails_summaries_is_disabled', false ) ) { return $settings; } $url = \add_query_arg( array( 'wpforms_email_template' => 'summary', 'wpforms_email_preview' => '1', ), \admin_url() ); $desc = \esc_html__( 'Disable Email Summaries weekly delivery.', 'wpforms-lite' ); if ( ! $this->is_disabled() ) { $desc .= '
' . \esc_html__( 'View Email Summary Example', 'wpforms-lite' ) . ''; } $settings['misc']['email-summaries-disable'] = array( 'id' => 'email-summaries-disable', 'name' => \esc_html__( 'Disable Email Summaries', 'wpforms-lite' ), 'desc' => $desc, 'type' => 'checkbox', ); return $settings; } /** * Preview Email Summary. * * @since 1.5.4 */ public function preview() { if ( ! \wpforms_current_user_can() ) { return; } if ( ! isset( $_GET['wpforms_email_preview'], $_GET['wpforms_email_template'] ) ) { // phpcs:ignore return; } if ( 'summary' !== $_GET['wpforms_email_template'] ) { // phpcs:ignore return; } $args = array( 'body' => array( 'entries' => $this->get_entries(), 'info_block' => ( new InfoBlocks() )->get_next(), ), ); $template = ( new Templates\Summary() )->set_args( $args ); $template = \apply_filters( 'wpforms_emails_summaries_template', $template ); $content = $template->get(); if ( 'default' !== \wpforms_setting( 'email-template', 'default' ) ) { $content = \wpautop( $content ); } echo $content; // phpcs:ignore exit; } /** * Get next cron occurrence date. * * @since 1.5.4 * * @return int */ protected function get_first_cron_date_gmt() { $date = \absint( \strtotime( 'next monday 2pm' ) - ( \get_option( 'gmt_offset' ) * \HOUR_IN_SECONDS ) ); return $date ? $date : \time(); } /** * Add custom Email Summaries cron schedule. * * @since 1.5.4 * * @param array $schedules WP cron schedules. * * @return array */ public function add_weekly_cron_schedule( $schedules ) { $schedules['wpforms_email_summaries_weekly'] = array( 'interval' => \WEEK_IN_SECONDS, 'display' => \esc_html__( 'Weekly WPForms Email Summaries', 'wpforms-lite' ), ); return $schedules; } /** * Email Summaries cron callback. * * @since 1.5.4 */ public function cron() { $entries = $this->get_entries(); // Email won't be sent if there are no form entries. if ( empty( $entries ) ) { return; } $info_blocks = new InfoBlocks(); $next_block = $info_blocks->get_next(); $args = array( 'body' => array( 'entries' => $entries, 'info_block' => $next_block, ), ); $template = ( new Templates\Summary() )->set_args( $args ); $template = \apply_filters( 'wpforms_emails_summaries_template', $template ); $content = $template->get(); if ( ! $content ) { return; } $to_email = \apply_filters( 'wpforms_emails_summaries_cron_to_email', \get_option( 'admin_email' ) ); $subject = \apply_filters( 'wpforms_emails_summaries_cron_subject', \esc_html__( 'WPForms Summary', 'wpforms-lite' ) ); $sent = ( new Mailer() ) ->template( $template ) ->subject( $subject ) ->to_email( $to_email ) ->send(); if ( true === $sent ) { $info_blocks->register_sent( $next_block ); } } /** * Get form entries. * * @since 1.5.4 * * @return array */ protected function get_entries() { if ( \wpforms()->pro ) { $entries_count = new \WPForms\Pro\Reports\EntriesCount(); $results = $entries_count->get_by( 'form', 0, 7, 'previous sunday' ); } else { $entries_count = new \WPForms\Lite\Reports\EntriesCount(); $results = $entries_count->get_by_form(); } return $results; } } Emails/Styler.php000066600000005123152141020640007751 0ustar00email = $email; $this->style_templates = \is_array( $style_templates ) ? $style_templates : array(); $this->style_overrides = \is_array( $style_overrides ) ? $style_overrides : array(); } /** * Template style overrides. * * @since 1.5.4 * * @return array */ protected function get_style_overrides() { $defaults = array( 'email_background_color' => \wpforms_setting( 'email-background-color', '#e9eaec' ), ); $overrides = \wp_parse_args( $this->style_overrides, $defaults ); return \apply_filters( 'wpforms_emails_mailer_get_style_overrides', $overrides, $this ); } /** * Locate template name matching styles. * * @since 1.5.4 * * @param string $name Template file name part. * * @return string */ protected function get_styles( $name = 'style' ) { if ( ! \array_key_exists( $name, $this->style_templates ) ) { return ''; } return Templates::get_html( $this->style_templates[ $name ], $this->get_style_overrides(), true ); } /** * Final processing of the template markup. * * @since 1.5.4 */ public function process_markup() { $this->styled_email = ( new CssToInlineStyles() )->convert( $this->email, $this->get_styles() ); $queries = '\n"; // Inject media queries, CssToInlineStyles strips them. $this->styled_email = \str_replace( '', $queries, $this->styled_email ); } /** * Get an email with inline styles. * * @since 1.5.4 * * @return string */ public function get() { if ( empty( $this->styled_email ) ) { $this->process_markup(); } return $this->styled_email; } } Tasks/Task.php000066600000011234152141020640007244 0ustar00action = sanitize_key( $action ); if ( empty( $this->action ) ) { throw new \UnexpectedValueException( 'Task action cannot be empty.' ); } } /** * Define the type of the task as async. * * @since 1.5.9 * * @return \WPForms\Tasks\Task */ public function async() { $this->type = self::TYPE_ASYNC; return $this; } /** * Define the type of the task as recurring. * * @since 1.5.9 * * @param int $timestamp When the first instance of the job will run. * @param int $interval How long to wait between runs. * * @return \WPForms\Tasks\Task */ public function recurring( $timestamp, $interval ) { $this->type = self::TYPE_RECURRING; $this->timestamp = (int) $timestamp; $this->interval = (int) $interval; return $this; } /** * Define the type of the task as one-time. * * @since 1.5.9 * * @param int $timestamp When the first instance of the job will run. * * @return \WPForms\Tasks\Task */ public function once( $timestamp ) { $this->type = self::TYPE_ONCE; $this->timestamp = (int) $timestamp; return $this; } /** * Pass any number of params that should be saved to Meta table. * * @since 1.5.9 * * @return \WPForms\Tasks\Task */ public function params() { $this->params = func_get_args(); return $this; } /** * Register the action. * Should be the final call in a chain. * * @since 1.5.9 * * @return null|string Action ID. */ public function register() { $action_id = null; // No processing if ActionScheduler is not usable. if ( ! wpforms()->get( 'tasks' )->is_usable() ) { return $action_id; } // Save data to tasks meta table. $task_meta = new Meta(); $this->meta_id = $task_meta->add( [ 'action' => $this->action, 'data' => $this->params, ] ); if ( empty( $this->meta_id ) ) { return $action_id; } switch ( $this->type ) { case self::TYPE_ASYNC: $action_id = $this->register_async(); break; case self::TYPE_RECURRING: $action_id = $this->register_recurring(); break; case self::TYPE_ONCE: $action_id = $this->register_once(); break; } return $action_id; } /** * Register the async task. * * @since 1.5.9 * * @return null|string Action ID. */ protected function register_async() { if ( ! function_exists( 'as_enqueue_async_action' ) ) { return null; } return as_enqueue_async_action( $this->action, [ 'tasks_meta_id' => $this->meta_id ], Tasks::GROUP ); } /** * Register the recurring task. * * @since 1.5.9 * * @return null|string Action ID. */ protected function register_recurring() { if ( ! function_exists( 'as_schedule_recurring_action' ) ) { return null; } return as_schedule_recurring_action( $this->timestamp, $this->interval, $this->action, [ 'tasks_meta_id' => $this->meta_id ], Tasks::GROUP ); } /** * Register the one-time task. * * @since 1.5.9 * * @return null|string Action ID. */ protected function register_once() { if ( ! function_exists( 'as_schedule_single_action' ) ) { return null; } return as_schedule_single_action( $this->timestamp, $this->action, [ 'tasks_meta_id' => $this->meta_id ], Tasks::GROUP ); } } Tasks/Actions/EntryEmailsMetaCleanupTask.php000066600000002535152141020640015144 0ustar00init(); } /** * Initialize the task with all the proper checks. * * @since 1.5.9 */ public function init() { // Register the action handler. add_action( self::ACTION, [ $this, 'process' ] ); if ( ! function_exists( 'as_next_scheduled_action' ) ) { return; } // Add new if none exists. if ( as_next_scheduled_action( self::ACTION ) !== false ) { return; } $interval = (int) apply_filters( 'wpforms_tasks_entry_emails_meta_cleanup_interval', DAY_IN_SECONDS ); $this->recurring( strtotime( 'tomorrow' ), $interval ) ->params( $interval ) ->register(); } /** * Perform the cleanup action: remove outdated meta for entry emails task. * * @since 1.5.9 * * @param int $interval Data older than this interval will be removed. */ public function process( $interval ) { ( new Meta() )->clean_by( EntryEmailsTask::ACTION, (int) $interval ); } } Tasks/Actions/EntryEmailsTask.php000066600000002532152141020640013022 0ustar00async(); } /** * Get the data from Tasks meta table, check/unpack it and * send the email straight away. * * @since 1.5.9 * @since 1.5.9.3 Send immediately instead of calling \WPForms_Process::entry_email() method. * * @param int $meta_id ID for meta information for a task. */ public static function process( $meta_id ) { $task_meta = new Meta(); $meta = $task_meta->get( (int) $meta_id ); // We should actually receive something. if ( empty( $meta ) || empty( $meta->data ) ) { return; } // We expect a certain number of params. if ( count( $meta->data ) !== 5 ) { return; } // We expect a certain meta data structure for this task. list( $to, $subject, $message, $headers, $attachments ) = $meta->data; // Let's do this NOW, finally. wp_mail( $to, $subject, $message, $headers, $attachments ); } } Tasks/Tasks.php000066600000010241152141020640007424 0ustar00get_tasks() as $task ) { if ( ! is_subclass_of( $task, Task::class ) ) { continue; } new $task(); } add_action( 'admin_menu', [ $this, 'admin_hide_as_menu' ], PHP_INT_MAX ); /* * By default we send emails in the same process as the form submission is done. * That means that when many emails are set in form Notifications - * the form submission can take a while because of all those emails that are sending in the background. * Since WPForms 1.6.0 users can enable a new option in Settings > Emails, * called "Optimize Email Sending", to send email in async way. * This feature was enabled for WPForms 1.5.9, but some users were not happy. */ if ( ! (bool) wpforms_setting( 'email-async', false ) ) { add_filter( 'wpforms_tasks_entry_emails_trigger_send_same_process', '__return_true' ); } add_action( EntryEmailsTask::ACTION, [ EntryEmailsTask::class, 'process' ] ); } /** * Get the list of WPForms default scheduled tasks. * Tasks, that are fired under certain specific circumstances * (like sending form submission email notifications) * are not listed here. * * @since 1.5.9 * * @return Task[] List of tasks classes. */ public function get_tasks() { if ( ! $this->is_usable() ) { return []; } $tasks = [ Actions\EntryEmailsMetaCleanupTask::class, ]; return apply_filters( 'wpforms_tasks_get_tasks', $tasks ); } /** * Hide Action Scheduler admin area when not in debug mode. * * @since 1.5.9 */ public function admin_hide_as_menu() { // Filter to redefine that WPForms hides Tools > Action Scheduler menu item. if ( apply_filters( 'wpforms_tasks_admin_hide_as_menu', ! wpforms_debug() ) ) { remove_submenu_page( 'tools.php', 'action-scheduler' ); } } /** * Create a new task. * Used for "inline" tasks, that require additional information * from the plugin runtime before they can be scheduled. * * Example: * wpforms()->get( 'tasks' ) * ->create( 'i_am_the_dude' ) * ->async() * ->params( 'The Big Lebowski', 1998 ) * ->register(); * * This `i_am_the_dude` action will be later processed as: * add_action( 'i_am_the_dude', 'thats_what_you_call_me' ); * * Function `thats_what_you_call_me()` will receive `$meta_id` param, * and you will be able to receive all params from the action like this: * $params = ( new Meta() )->get( (int) $meta_id ); * list( $name, $year ) = $meta->data; * * @since 1.5.9 * * @param string $action Action that will be used as a hook. * * @return \WPForms\Tasks\Task */ public function create( $action ) { return new Task( $action ); } /** * Cancel all the AS actions for a group. * * @since 1.5.9 * * @param string $group Group to cancel all actions for. */ public function cancel_all( $group = '' ) { if ( empty( $group ) ) { $group = self::GROUP; } else { $group = sanitize_key( $group ); } if ( class_exists( 'ActionScheduler_DBStore' ) ) { \ActionScheduler_DBStore::instance()->cancel_actions_by_group( $group ); } } /** * Whether ActionScheduler thinks that it has migrated or not. * * @since 1.5.9.3 * * @return bool */ public function is_usable() { // No tasks if ActionScheduler wasn't loaded. if ( ! class_exists( 'ActionScheduler_DataController' ) ) { return false; } return \ActionScheduler_DataController::is_migration_complete(); } /** * Whether task has been scheduled and is pending. * * @since 1.6.0 * * @param string $hook Hook to check for. * * @return bool */ public function is_scheduled( $hook ) { if ( ! function_exists( 'as_next_scheduled_action' ) ) { return false; } return as_next_scheduled_action( $hook ); } } Tasks/Meta.php000066600000011060152141020640007225 0ustar00191 chars in JSON to AS, * so we need to store them somewhere (and clean from time to time). * * @since 1.5.9 */ class Meta extends \WPForms_DB { /** * Primary key (unique field) for the database table. * * @since 1.5.9 * * @var string */ public $primary_key = 'id'; /** * Database type identifier. * * @since 1.5.9 * * @var string */ public $type = 'tasks_meta'; /** * Primary class constructor. * * @since 1.5.9 */ public function __construct() { $this->table_name = self::get_table_name(); } /** * Get the DB table name. * * @since 1.5.9 * * @return string */ public static function get_table_name() { global $wpdb; return $wpdb->prefix . 'wpforms_tasks_meta'; } /** * Get table columns. * * @since 1.5.9 */ public function get_columns() { return array( 'id' => '%d', 'action' => '%s', 'data' => '%s', 'date' => '%s', ); } /** * Default column values. * * @since 1.5.9 * * @return array */ public function get_column_defaults() { return array( 'action' => '', 'data' => '', 'date' => gmdate( 'Y-m-d H:i:s' ), ); } /** * Create custom entry meta database table. * Used in migration and on plugin activation. * * @since 1.5.9 */ public function create_table() { global $wpdb; require_once ABSPATH . 'wp-admin/includes/upgrade.php'; $charset_collate = ''; if ( ! empty( $wpdb->charset ) ) { $charset_collate .= "DEFAULT CHARACTER SET {$wpdb->charset}"; } if ( ! empty( $wpdb->collate ) ) { $charset_collate .= " COLLATE {$wpdb->collate}"; } $sql = "CREATE TABLE {$this->table_name} ( id bigint(20) NOT NULL AUTO_INCREMENT, action varchar(255) NOT NULL, data longtext NOT NULL, date datetime NOT NULL, PRIMARY KEY (id) ) {$charset_collate};"; dbDelta( $sql ); } /** * Remove queue records for a defined period of time in the past. * Calling this method will remove queue records that are older than $period seconds. * * @since 1.5.9 * * @param string $action Action that should be cleaned up. * @param int $interval Number of seconds from now. * * @return int Number of removed tasks meta records. */ public function clean_by( $action, $interval ) { global $wpdb; if ( empty( $action ) || empty( $interval ) ) { return 0; } $table = self::get_table_name(); $action = sanitize_key( $action ); $date = gmdate( 'Y-m-d H:i:s', time() - (int) $interval ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching return (int) $wpdb->query( $wpdb->prepare( "DELETE FROM `$table` WHERE action = %s AND date < %s", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared $action, $date ) ); } /** * Inserts a new record into the database. * * @since 1.5.9 * * @param array $data Column data. * @param string $type Optional. Data type context. * * @return int ID for the newly inserted record. 0 otherwise. */ public function add( $data, $type = '' ) { if ( empty( $data['action'] ) || ! is_string( $data['action'] ) ) { return 0; } $data['action'] = sanitize_key( $data['action'] ); if ( isset( $data['data'] ) ) { $string = wp_json_encode( $data['data'] ); if ( $string === false ) { $string = ''; } /* * We are encoding the string representation of all the data * to make sure that nothing can harm the database. * This is not an encryption, and we need this data later as is, * so we are using one of the fastest way to do that. * This data is removed from DB on a daily basis. */ // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode $data['data'] = base64_encode( $string ); } if ( empty( $type ) ) { $type = $this->type; } return parent::add( $data, $type ); } /** * Retrieve a row from the database based on a given row ID. * * @since 1.5.9} * * @param int $meta_id Meta ID. * * @return null|object */ public function get( $meta_id ) { $meta = parent::get( $meta_id ); if ( empty( $meta ) || empty( $meta->data ) ) { return $meta; } // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode $decoded = base64_decode( $meta->data ); if ( $decoded === false || ! is_string( $decoded ) ) { $meta->data = ''; } else { $meta->data = json_decode( $decoded, true ); } return $meta; } }