OrderPK!r00libs/CSVParser/CSVParser.phpnu[import_data = $data; } /** * Detect the CSV delimiter, by analyzing some rows to determine the most probable delimiter character. * * @since 1.0.0 * * @return string Most probable delimiter character. */ public function find_delimiter() { $data = &$this->import_data; $delimiter_count = array(); $enclosed = false; $current_line = 0; // Walk through each character in the CSV string (up to $this->delimiter_search_max_lines) and search potential delimiter characters. $data_length = strlen( $data ); for ( $i = 0; $i < $data_length; $i++ ) { $prev_char = ( $i - 1 >= 0 ) ? $data[ $i - 1 ] : ''; $curr_char = $data[ $i ]; $next_char = ( $i + 1 < $data_length ) ? $data[ $i + 1 ] : ''; if ( $curr_char === $this->enclosure ) { // Open and closing quotes. if ( ! $enclosed || $next_char !== $this->enclosure ) { $enclosed = ! $enclosed; // Flip bool. } elseif ( $enclosed ) { $i++; // Skip next character. } } elseif ( ( "\n" === $curr_char && "\r" !== $prev_char || "\r" === $curr_char ) && ! $enclosed ) { // Reached end of a line. $current_line++; if ( $current_line >= $this->delimiter_search_max_lines ) { break; } } elseif ( ! $enclosed ) { // At this point, $curr_char seems to be used as a delimiter, as it is not enclosed. // Count $curr_char if it is not in the $this->non_delimiter_chars list if ( 0 === preg_match( '#[' . $this->non_delimiter_chars . ']#i', $curr_char ) ) { if ( ! isset( $delimiter_count[ $curr_char ][ $current_line ] ) ) { $delimiter_count[ $curr_char ][ $current_line ] = 0; // Initialize empty } $delimiter_count[ $curr_char ][ $current_line ]++; } } } // Find most probable delimiter, by sorting their counts. $potential_delimiters = array(); foreach ( $delimiter_count as $char => $line_counts ) { $is_possible_delimiter = $this->_check_delimiter_count( $char, $line_counts, $current_line ); if ( false !== $is_possible_delimiter ) { $potential_delimiters[ $is_possible_delimiter ] = $char; } } ksort( $potential_delimiters ); // If no valid delimiter was found, use the character that was found in most rows. if ( empty( $potential_delimiters ) ) { $delimiter_counts = array_map( 'count', $delimiter_count ); arsort( $delimiter_counts, SORT_NUMERIC ); $potential_delimiters = array_keys( $delimiter_counts ); } // Return first array element, as that has the highest count. return array_shift( $potential_delimiters ); } /** * Check if passed character can be a delimiter, by checking counts in each line. * * @since 1.0.0 * * @param string $char Character to check. * @param array $line_counts Counts for the characters in the lines. * @param int $number_lines Number of lines. * @return bool|string False if delimiter is not possible, string to be used as a sort key if character could be a delimiter. */ protected function _check_delimiter_count( $char, array $line_counts, $number_lines ) { // Was the potential delimiter found in every line? if ( count( $line_counts ) !== $number_lines ) { return false; } // Check if the count in every line is the same (or one higher for an "almost"). $first = null; $equal = null; $almost = false; foreach ( $line_counts as $line => $count ) { if ( is_null( $first ) ) { $first = $count; } elseif ( $count === $first && false !== $equal ) { $equal = true; } elseif ( $count === $first + 1 && false !== $equal ) { $equal = true; $almost = true; } else { $equal = false; } } // Check equality only if there's more than one line. if ( $number_lines > 1 && ! $equal ) { return false; } // At this point, count is equal in all lines, so determine a string to sort priority. $match = ( $almost ) ? 2 : 1; $pref = strpos( $this->preferred_delimiter_chars, $char ); $pref = ( false !== $pref ) ? str_pad( $pref, 3, '0', STR_PAD_LEFT ) : '999'; return $pref . $match . '.' . ( 99999 - str_pad( $first, 5, '0', STR_PAD_LEFT ) ); } /** * Parse CSV string into a two-dimensional array. * * @since 1.0.0 * * @param string $delimiter Delimiter character for the CSV parsing. * @return array Two-dimensional array with the data from the CSV string. */ public function parse( $delimiter ) { $data = &$this->import_data; // Filter delimiter from the list, if it is a whitespace character. $white_spaces = str_replace( $delimiter, '', " \t\x0B\0" ); $rows = array(); // Complete rows. $row = array(); // Row that is currently built. $column = 0; // Current column index. $cell_content = ''; // Content of the currently processed cell. $enclosed = false; $was_enclosed = false; // To determine if the cell content will be trimmed of whitespace (only for enclosed cells). // Walk through each character in the CSV string. $data_length = strlen( $data ); for ( $i = 0; $i < $data_length; $i++ ) { $curr_char = $data[ $i ]; $next_char = ( $i + 1 < $data_length ) ? $data[ $i + 1 ] : ''; if ( $curr_char === $this->enclosure ) { // Open/close quotes, and inline quotes. if ( ! $enclosed ) { if ( '' === ltrim( $cell_content, $white_spaces ) ) { $enclosed = true; $was_enclosed = true; } else { $this->error = 2; $error_line = count( $rows ) + 1; $error_column = $column + 1; if ( ! isset( $this->error_info[ "{$error_line}-{$error_column}" ] ) ) { $this->error_info[ "{$error_line}-{$error_column}" ] = array( 'type' => 2, 'info' => "Syntax error found in line {$error_line}. Non-enclosed fields can not contain double-quotes.", 'line' => $error_line, 'column' => $error_column, ); } $cell_content .= $curr_char; } } elseif ( $next_char === $this->enclosure ) { // Enclosure character within enclosed cell (" encoded as ""). $cell_content .= $curr_char; $i++; // Skip next character } elseif ( $next_char !== $delimiter && "\r" !== $next_char && "\n" !== $next_char ) { // for-loop (instead of while-loop) that skips whitespace. for ( $x = ( $i + 1 ); isset( $data[ $x ] ) && '' === ltrim( $data[ $x ], $white_spaces ); $x++ ) { // Action is in iterator check. } if ( $data[ $x ] === $delimiter ) { $enclosed = false; $i = $x; } else { if ( $this->error < 1 ) { $this->error = 1; } $error_line = count( $rows ) + 1; $error_column = $column + 1; if ( ! isset( $this->error_info[ "{$error_line}-{$error_column}" ] ) ) { $this->error_info[ "{$error_line}-{$error_column}" ] = array( 'type' => 1, 'info' => "Syntax error found in line {$error_line}. A single double-quote was found within an enclosed string. Enclosed double-quotes must be escaped with a second double-quote.", 'line' => $error_line, 'column' => $error_column, ); } $cell_content .= $curr_char; $enclosed = false; } } else { // The " was the closing one for the cell. $enclosed = false; } } elseif ( ( $curr_char === $delimiter || "\n" === $curr_char || "\r" === $curr_char ) && ! $enclosed ) { // End of cell (by $delimiter), or end of line (by line break, and not enclosed!). $columnContent = ( $was_enclosed ) ? $cell_content : trim( $cell_content ); $row[ $column ] = $columnContent; $cell_content = ''; $was_enclosed = false; $column++; // End of line. if ( "\n" === $curr_char || "\r" === $curr_char ) { // Append completed row. $rows[] = $row; $row = array(); $column = 0; if ( "\r" === $curr_char && "\n" === $next_char ) { // Skip next character in \r\n line breaks. $i++; } } } else { // Append character to current cell. $cell_content .= $curr_char; } } return $rows; } } // class CSV_Parser PK!.r+r+9libs/ff_plugin_updater/updater/FluentFormAddOnUpdater.phpnu[api_url = trailingslashit($_api_url); $this->api_data = $_api_data; $this->name = plugin_basename($_plugin_file); $this->slug = basename($_plugin_file, '.php'); $this->response_transient_key = md5(sanitize_key($this->name) . 'response_transient'); $this->version = $_api_data['version']; if (is_array($_plugin_update_data) and isset($_plugin_update_data['license_status'], $_plugin_update_data['admin_page_url'], $_plugin_update_data['purchase_url'], $_plugin_update_data['plugin_title']) ) { $this->license_status = $_plugin_update_data ['license_status']; $this->admin_page_url = $_plugin_update_data['admin_page_url']; $this->purchase_url = $_plugin_update_data['purchase_url']; $this->plugin_title = $_plugin_update_data['plugin_title']; } // Set up hooks. $this->init(); } /** * Set up WordPress filters to hook into WP's update process. * * @uses add_filter() * * @return void */ public function init() { $this->maybe_delete_transients(); add_filter('pre_set_site_transient_update_plugins', array($this, 'check_update'), 51); add_action( 'delete_site_transient_update_plugins', [ $this, 'delete_transients' ] ); // add_filter('plugins_api', array($this, 'plugins_api_filter'), 10, 3); remove_action( 'after_plugin_row_' . $this->name, 'wp_plugin_update_row' ); // // add_action( 'after_plugin_row_' . $this->name, [ $this, 'show_update_notification' ], 10, 2 ); } function remove_plugin_update_message() { remove_action('after_plugin_row_' . $this->name, 'wp_plugin_update_row', 10, 2); } function check_update($_transient_data) { global $pagenow; if (!is_object($_transient_data)) { $_transient_data = new \stdClass(); } if ('plugins.php' === $pagenow && is_multisite()) { return $_transient_data; } return $this->check_transient_data($_transient_data); } private function check_transient_data($_transient_data) { if (!is_object($_transient_data)) { $_transient_data = new \stdClass(); } if (empty($_transient_data->checked)) { return $_transient_data; } $version_info = $this->get_transient($this->response_transient_key); if (false === $version_info) { $version_info = $this->api_request('plugin_latest_version', array('slug' => $this->slug)); if (is_wp_error($version_info)) { $version_info = new \stdClass(); $version_info->error = true; } $this->set_transient($this->response_transient_key, $version_info); } if (!empty($version_info->error) || !$version_info) { return $_transient_data; } if (is_object($version_info) && isset($version_info->new_version)) { if (version_compare($this->version, $version_info->new_version, '<')) { $_transient_data->response[$this->name] = $version_info; } $_transient_data->last_checked = time(); $_transient_data->checked[$this->name] = $this->version; } return $_transient_data; } /** * show update nofication row -- needed for multisite subsites, because WP won't tell you otherwise! * * @param string $file * @param array $plugin */ public function show_update_notification($file, $plugin) { if ( is_network_admin() ) { return; } if ( ! current_user_can( 'update_plugins' ) ) { return; } if ( $this->name !== $file ) { return; } // Remove our filter on the site transient remove_filter( 'pre_set_site_transient_update_plugins', [ $this, 'check_update' ] ); $update_cache = get_site_transient( 'update_plugins' ); $update_cache = $this->check_transient_data( $update_cache ); // set_site_transient( 'update_plugins', $update_cache ); // Restore our filter add_filter( 'pre_set_site_transient_update_plugins', [ $this, 'check_update' ] ); } /** * Updates information on the "View version x.x details" page with custom data. * * @uses api_request() * * @param mixed $_data * @param string $_action * @param object $_args * * @return object $_data */ function plugins_api_filter($_data, $_action = '', $_args = null) { if ( 'plugin_information' !== $_action ) { return $_data; } if (!isset($_args->slug) || ($_args->slug != $this->slug)) { return $_data; } $cache_key = $this->slug.'_api_request_' . substr( md5( serialize( $this->slug ) ), 0, 15 ); $api_request_transient = get_site_transient( $cache_key ); if ( empty( $api_request_transient ) ) { $to_send = array( 'slug' => $this->slug, 'is_ssl' => is_ssl(), 'fields' => array( 'banners' => false, // These will be supported soon hopefully 'reviews' => false ) ); $api_request_transient = $this->api_request('plugin_information', $to_send); // Expires in 1 day set_site_transient( $cache_key, $api_request_transient, DAY_IN_SECONDS ); } if (false !== $api_request_transient) { $_data = $api_request_transient; } return $_data; } /** * Disable SSL verification in order to prevent download update failures * * @param array $args * @param string $url * * @return object $array */ function http_request_args($args, $url) { // If it is an https request and we are performing a package download, disable ssl verification if (strpos($url, 'https://') !== false && strpos($url, 'edd_action=package_download')) { $args['sslverify'] = false; } return $args; } /** * Calls the API and, if successfull, returns the object delivered by the API. * * @uses get_bloginfo() * @uses wp_remote_post() * @uses is_wp_error() * * @param string $_action The requested action. * @param array $_data Parameters for the API action. * * @return false|object */ private function api_request($_action, $_data) { global $wp_version; $data = array_merge($this->api_data, $_data); if ($data['slug'] != $this->slug) { return; } if ($this->api_url == home_url()) { return false; // Don't allow a plugin to ping itself } $siteUrl = home_url(); if (is_multisite()) { $siteUrl = network_site_url(); } $api_params = array( 'edd_action' => 'get_version', 'license' => !empty($data['license']) ? $data['license'] : '', //'item_name' => isset( $data['item_name'] ) ? $data['item_name'] : false, 'item_id' => isset($data['item_id']) ? $data['item_id'] : false, 'slug' => $data['slug'], 'author' => $data['author'], 'url' => $siteUrl ); $request = wp_remote_post($this->api_url, array('timeout' => 15, 'sslverify' => false, 'body' => $api_params)); if (!is_wp_error($request)) { $request = json_decode(wp_remote_retrieve_body($request)); } if ($request && isset($request->sections)) { $request->sections = maybe_unserialize($request->sections); } else { $request = false; } return $request; } public function show_changelog() { if (empty($_REQUEST['edd_sl_action']) || 'view_plugin_changelog' != $_REQUEST['edd_sl_action']) { return; } if (empty($_REQUEST['plugin'])) { return; } if (empty($_REQUEST['slug'])) { return; } if (!current_user_can('update_plugins')) { wp_die(__('You do not have permission to install plugin updates', 'edd'), __('Error', 'edd'), array('response' => 403)); } $response = $this->api_request('plugin_latest_version', array('slug' => $_REQUEST['slug'])); if ($response && isset($response->sections['changelog'])) { echo '
' . $response->sections['changelog'] . '
'; } exit; } private function maybe_delete_transients() { global $pagenow; if ('update-core.php' === $pagenow || isset($_GET['force-check'])) { $this->delete_transients(); } } public function delete_transients() { $this->delete_transient($this->response_transient_key); } protected function delete_transient($cache_key) { delete_option($cache_key); } protected function get_transient($cache_key) { $cache_data = get_option($cache_key); if (empty($cache_data['timeout']) || current_time('timestamp') > $cache_data['timeout']) { // Cache is expired. return false; } return $cache_data['value']; } protected function set_transient($cache_key, $value, $expiration = 0) { if (empty($expiration)) { $expiration = strtotime('+24 hours', current_time('timestamp')); } $data = [ 'timeout' => $expiration, 'value' => $value, ]; update_option($cache_key, $data, 'no'); } } PK!rdoo9libs/ff_plugin_updater/updater/FluentFormAddOnChecker.phpnu[vars = $vars; add_action('admin_init', array($this, 'init')); add_action('admin_init', array($this, 'activate_license')); add_action('admin_init', array($this, 'deactivate_license')); add_action('admin_init', array($this, 'check_license')); add_action('admin_init', array($this, 'sl_updater'), 0); add_action('cli_init', array($this, 'sl_updater'), 0); add_filter('fluentform/global_settings_components', array($this, 'pushLicenseMenuToGlobalSettings')); add_action('fluentform/global_settings_component_license_page', array($this, 'license_page')); // add_filter('fluentform/addons_extra_menu', array($this, 'registerLicenseMenu')); self::$_instance = $this; } public static function getInstance() { return self::$_instance; } public function isLocal() { $ip_address = ''; if (array_key_exists('SERVER_ADDR', $_SERVER)) { $ip_address = $_SERVER['SERVER_ADDR']; } else if (array_key_exists('LOCAL_ADDR', $_SERVER)) { $ip_address = $_SERVER['LOCAL_ADDR']; } return in_array($ip_address, array("127.0.0.1", "::1")); } function get_var($var) { if (isset($this->vars[$var])) { return $this->vars[$var]; } return false; } public function registerLicenseMenu($menus) { $menus[$this->get_var('menu_slug')] = $this->get_var('menu_title'); return $menus; } public function register_option() { // creates our settings in the options table register_setting($this->get_var('option_group'), $this->get_var('license_key')); } /** * Show an error message that license needs to be activated */ function init() { $this->register_option(); if (defined('DOING_AJAX') && DOING_AJAX) { return; } if (!defined('FLUENTFORM_VERSION')) { return; } $licenseStatus = $this->getSavedLicenseStatus(); if (!$licenseStatus) { add_action('fluentform/global_menu', array($this, 'errorNotice')); add_action('fluentform/after_form_menu', array($this, 'errorNotice')); return; } $licenseData = get_option($this->get_var('license_status') . '_checking'); if (!$licenseData) { return; } if ($licenseStatus == 'expired') { $expireMessage = $this->getExpireMessage($licenseData); add_filter('fluentform/dashboard_notices', function ($notices) use ($expireMessage) { $notices['license_expire'] = array( 'type' => 'error', 'message' => $expireMessage, 'closable' => false ); return $notices; }); if ($this->willShowExpirationNotice()) { add_action('fluentform/global_menu', array($this, 'expireNotice')); add_action('fluentform/after_form_menu', array($this, 'expireNotice')); } return; } if ('valid' != $licenseStatus) { add_action('fluentform/global_menu', array($this, 'errorNotice')); add_action('fluentform/after_form_menu', array($this, 'errorNotice')); } } public function expireNotice() { $licenseData = get_option($this->get_var('license_status') . '_checking'); $expireMessage = $this->getExpireMessage($licenseData); echo '
' . $expireMessage . '
'; } public function errorNotice() { echo '

' . sprintf(__('The %s license needs to be activated. %sActivate Now%s', 'fluentformpro'), $this->get_var('plugin_title'), '', '') . '

'; } function sl_updater() { // retrieve our license key from the DB $license_key = trim(get_option($this->get_var('license_key'))); $license_status = get_option($this->get_var('license_status')); // setup the updater new FluentFormAddOnUpdater($this->get_var('store_url'), $this->get_var('plugin_file'), array( 'version' => $this->get_var('version'), 'license' => $license_key, 'item_name' => $this->get_var('item_name'), 'item_id' => $this->get_var('item_id'), 'author' => $this->get_var('author') ), array( 'license_status' => $license_status, 'admin_page_url' => $this->get_var('activate_url'), 'purchase_url' => $this->get_var('purchase_url'), 'plugin_title' => $this->get_var('plugin_title') ) ); } public function pushLicenseMenuToGlobalSettings($components) { $components['license_page'] = [ 'path' => '/license_page', 'title' => 'License', 'query' => [ 'component' => 'license_page' ], ]; return $components; } function license_page() { $license = $this->getSavedLicenseKey(); $status = $this->getSavedLicenseStatus(); if ($status == 'expired' && $license) { $activation = $this->tryActivateLicense($license); $status = $this->getSavedLicenseStatus(); } $licenseData = false; if ($status) { $licenseData = get_option($this->get_var('license_status') . '_checking'); if (!$licenseData) { $remoteData = $this->getRemoteLicense(); if ($remoteData && !is_wp_error($remoteData)) { $licenseData = $remoteData; } } } $renewHtml = $this->getRenewHtml($licenseData); settings_errors(); ?> jQuery('.ff_settings_list li a').on('click', function (e) { if(jQuery(this).attr('href') == '#'){ e.preventDefault(); } let subMenu = jQuery(this).parent().find('.ff_list_submenu'); jQuery(this).parent().addClass('active').siblings().removeClass('active'); subMenu.parent().toggleClass('is-submenu').siblings().removeClass('is-submenu'); subMenu.slideToggle().parent().siblings().find('.ff_list_submenu').slideUp(); }); "; ?>

get_var('option_group')); ?>

get_var('plugin_title'))); ?>

get_var('plugin_title')) ?>.

get_var('option_group') . '_nonce', $this->get_var('option_group') . '_nonce'); ?> get_var('option_group') . '_nonce', $this->get_var('option_group') . '_nonce'); ?>

get_var('contact_url') . '" target="_blank">', ''); ?>

get_var('option_group') . '_do_activate_license'])) { return; } if (!\FluentForm\App\Modules\Acl\Acl::hasPermission('fluentform_full_access')) { add_settings_error( $this->get_var('option_group'), 'deactivate', __('Sorry! You do not have permission to activate this license.', 'fluentformpro') ); return; } // run a quick security check if (!check_admin_referer($this->get_var('option_group') . '_nonce', $this->get_var('option_group') . '_nonce') ) { return; } // get out if we didn't click the Activate button // retrieve the license from the database $license = trim($_REQUEST[$this->get_var('option_group') . '_key']); $result = $this->tryActivateLicense($license); if (is_wp_error($result)) { $message = $result->get_error_message(); add_settings_error( $this->get_var('option_group'), 'activate', $message ); return; } return; } public function tryActivateLicense($license) { $isNetworkMainSite = is_multisite(); if ($isNetworkMainSite) { // data to send in our API request $api_params = array( 'edd_action' => 'activate_license', 'license' => $license, 'item_name' => urlencode($this->get_var('item_name')), // the name of our product in EDD 'item_id' => $this->get_var('item_id'), 'url' => network_site_url() ); } else { // data to send in our API request $api_params = array( 'edd_action' => 'activate_license', 'license' => $license, 'item_name' => urlencode($this->get_var('item_name')), // the name of our product in EDD 'item_id' => $this->get_var('item_id'), 'url' => home_url() ); } $payloadParams = $api_params; if ($otherData = $this->getOtherInfo()) { $payloadParams['other_data'] = $otherData; } // Call the custom API. $response = wp_remote_get( $this->get_var('store_url'), array('timeout' => 15, 'sslverify' => false, 'body' => $payloadParams) ); // make sure the response came back okay if (is_wp_error($response)) { $license_data = file_get_contents($this->get_var('store_url') . '?' . http_build_query($api_params)); if (!$license_data) { $license_data = $this->urlGetContentFallBack($this->get_var('store_url') . '?' . http_build_query($api_params)); } if (!$license_data) { return new WP_Error( 423, __('Error when contacting with license server. Please check that your server have curl installed', 'fluentformpro'), [ 'response' => $response, 'is_error' => true ] ); } $license_data = json_decode($license_data); } else { $license_data = json_decode(wp_remote_retrieve_body($response)); } // $license_data->license will be either "valid" or "invalid" if ($license_data->license) { if ($license_data->license == 'invalid' && $license_data->error == 'expired') { $this->setLicenseStatus('expired'); } else { $this->setLicenseStatus($license_data->license); } } if (!isset($license_data->next_timestamp)) { $license_data->next_timestamp = time() + $this->get_var('cache_time'); } update_option( $this->get_var('license_status') . '_checking', $license_data ); if ('valid' == $license_data->license) { $this->setLicenseKey($license); // save the license key to the database return array( 'message' => sprintf(__('Congratulation! %s is successfully activated', 'fluentformpro'), $this->get_var('plugin_title')), 'response' => $license_data, 'status' => 'valid' ); } $errorMessage = $this->getErrorMessage($license_data, $license); return new WP_Error( 423, $errorMessage, [ 'license_data' => $license_data, 'is_error' => true ] ); } function deactivate_license() { // listen for our activate button to be clicked if (isset($_POST[$this->get_var('option_group') . '_do_deactivate_license'])) { if (!\FluentForm\App\Modules\Acl\Acl::hasPermission('fluentform_full_access')) { add_settings_error( $this->get_var('option_group'), 'deactivate', __('Sorry! You do not have permission to deactivate this license.', 'fluentformpro') ); return; } // run a quick security check if (!check_admin_referer($this->get_var('option_group') . '_nonce', $this->get_var('option_group') . '_nonce') ) { return; } // get out if we didn't click the Activate button // retrieve the license from the database $license = $this->getSavedLicenseKey(); // data to send in our API request $api_params = array( 'edd_action' => 'deactivate_license', 'license' => $license, 'item_name' => urlencode($this->get_var('item_name')), // the name of our product in EDD 'item_id' => $this->get_var('item_id'), 'url' => home_url() ); // Call the custom API. $response = wp_remote_post($this->get_var('store_url'), array('timeout' => 15, 'sslverify' => false, 'body' => $api_params)); // make sure the response came back okay if (is_wp_error($response)) { add_settings_error( $this->get_var('option_group'), 'deactivate', __('There was an error deactivating the license, please try again or contact support.', 'fluentformpro') ); return false; } // decode the license data $license_data = json_decode(wp_remote_retrieve_body($response)); // $license_data->license will be either "deactivated" or "failed" if ($license_data && ('deactivated' == $license_data->license || $license_data->license == 'failed')) { $this->setLicenseStatus(false); $this->setLicenseKey(false); delete_option($this->get_var('license_status') . '_checking'); add_settings_error( $this->get_var('option_group'), 'deactivate', __('License deactivated', 'fluentformpro') ); wp_safe_redirect($this->get_var('activate_url')); exit(); } else { add_settings_error( $this->get_var('option_group'), 'deactivate', __('Unable to deactivate license, please try again or contact support.', 'fluentformpro') ); } } } public function check_license() { $cachedData = get_option($this->get_var('license_status') . '_checking'); $nextTimestamp = (!empty($cachedData->next_timestamp)) ? $cachedData->next_timestamp : 0; if ($nextTimestamp > time()) { return; } $license_data = $this->getRemoteLicense(); if (is_wp_error($license_data) || !$license_data) { return false; } if ($license_data && $license_data->license) { $this->setLicenseStatus($license_data->license); } $license_data->next_timestamp = time() + $this->get_var('cache_time'); // Set to check again in sometime later. update_option( $this->get_var('license_status') . '_checking', $license_data ); } public function getRemoteLicense() { $license = $this->getSavedLicenseKey(); if (!$license) { return false; } if (is_multisite()) { $api_params = array( 'edd_action' => 'check_license', 'license' => $license, 'item_name' => urlencode($this->get_var('item_name')), 'url' => network_site_url() ); } else { $api_params = array( 'edd_action' => 'check_license', 'license' => $license, 'item_name' => urlencode($this->get_var('item_name')), 'url' => home_url() ); } $payloadParams = $api_params; if ($otherData = $this->getOtherInfo()) { $payloadParams['other_data'] = $otherData; } // Call the custom API. $response = wp_remote_get( $this->get_var('store_url'), array( 'timeout' => 15, 'sslverify' => false, 'body' => $payloadParams ) ); if (is_wp_error($response)) { return $response; } $license_data = json_decode( wp_remote_retrieve_body($response) ); return $license_data; } private function getErrorMessage($licenseData, $licenseKey = false) { $errorMessage = __('There was an error activating the license, please verify your license is correct and try again or contact support.', 'fluentformpro'); if ($licenseData->error == 'expired') { $renewUrl = $this->getRenewUrl($licenseKey); $errorMessage = sprintf(__('Your license has been expired at %s. Please %sclick here%s to renew your license', 'fluentformpro'), $licenseData->expires, '', ''); } else if ($licenseData->error == 'no_activations_left') { $errorMessage = sprintf(__('No Activation Site left: You have activated all the sites that your license offer. Please go to wpmanageninja.com account and review your sites. You may deactivate your unused sites from wpmanageninja account or you can purchase another license. %sClick Here to purchase another license%s', 'fluentformpro'), '', ''); } else if ($licenseData->error == 'missing') { $errorMessage = __('The given license key is not valid. Please verify that your license is correct. You may login to wpmanageninja.com account and get your valid license key for your purchase.', 'fluentformpro'); } return $errorMessage; } private function urlGetContentFallBack($url) { $parts = parse_url($url); $host = $parts['host']; $result = false; if (!function_exists('curl_init')) { $ch = curl_init(); $header = array('GET /1575051 HTTP/1.1', "Host: {$host}", 'Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language:en-US,en;q=0.8', 'Cache-Control:max-age=0', 'Connection:keep-alive', 'Host:adfoc.us', 'User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36', ); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0); curl_setopt($ch, CURLOPT_COOKIESESSION, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $header); $result = curl_exec($ch); curl_close($ch); } if (!$result && function_exists('fopen') && function_exists('stream_get_contents')) { $handle = fopen($url, "r"); $result = stream_get_contents($handle); } return $result; } private function getSavedLicenseKey() { if (is_multisite()) { $license = trim(get_network_option(get_main_network_id(), $this->get_var('license_key'))); } else { $license = trim(get_option($this->get_var('license_key'))); } return $license; } private function setLicenseKey($key) { if (is_multisite()) { $status = update_network_option(get_main_network_id(), $this->get_var('license_key'), $key); } else { $status = update_option($this->get_var('license_key'), $key); } return $status; } private function getSavedLicenseStatus() { if (is_multisite()) { $status = trim(get_network_option(get_main_network_id(), $this->get_var('license_status'))); } else { $status = trim(get_option($this->get_var('license_status'))); } return $status; } private function setLicenseStatus($status) { if (is_multisite()) { $status = update_network_option(get_main_network_id(), $this->get_var('license_status'), $status); } else { $status = update_option($this->get_var('license_status'), $status); } return $status; } private function getExpireMessage($licenseData) { $renewUrl = $this->get_var('activate_url'); return sprintf(__('%sYour %s license has been %sexpired at %s, Please %sClick Here to Renew Your License%s', 'fluentformpro'), '

', $this->get_var('plugin_title'), '', date('d M Y', strtotime($licenseData->expires)) . '', '', '' . '

'); } private function willShowExpirationNotice() { if (!defined('FLUENTFORM_VERSION') || !\FluentForm\App\Modules\Acl\Acl::hasAnyFormPermission()) { return false; } global $pagenow; $showablePages = ['index.php', 'plugins.php']; if (in_array($pagenow, $showablePages)) { return true; } return false; } private function getRenewHtml($license_data) { if (!$license_data) { return; } $status = $this->getSavedLicenseStatus(); if (!$status) { return; } $renewUrl = $this->getRenewUrl(); $renewHTML = ''; if ($status == 'expired') { $expiredDate = date('d M Y', strtotime($license_data->expires)); $renewHTML = sprintf(__('%sYour license was expired at %s', 'fluentformpro'), '

', '' . $expiredDate . '

'); $renewHTML .= sprintf(__('%sClick Here to renew your license%s', 'fluentformpro'), '

', '

'); } else if ($status == 'valid') { if ($license_data->expires != 'lifetime') { $expireDate = date('d M Y', strtotime($license_data->expires)); $interval = strtotime($license_data->expires) - time(); $intervalDays = intval($interval / (60 * 60 * 24)); if ($intervalDays < 30) { $renewHTML = sprintf(__('%sYour license will be expired in %s days%s', 'fluentformpro'), '

', $intervalDays, '

'); $renewHTML .= sprintf(__('%sPlease %sClick Here to renew your license%s', 'fluentformpro'), '

', '', '

'); } } } return $renewHTML; } private function getRenewUrl($licenseKey = false) { if (!$licenseKey) { $licenseKey = $this->getSavedLicenseKey(); } if ($licenseKey) { $renewUrl = $this->get_var('store_site') . '/checkout/?edd_license_key=' . $licenseKey . '&download_id=' . $this->get_var('item_id'); } else { $renewUrl = $this->get_var('purchase_url'); } return $renewUrl; } private function getOtherInfo() { if (!$this->timeMatched()) { return false; } global $wp_version; return [ 'plugin_version' => FLUENTFORMPRO_VERSION, 'php_version' => (defined('PHP_VERSION')) ? PHP_VERSION : phpversion(), 'wp_version' => $wp_version, 'plugins' => (array)get_option('active_plugins'), 'site_lang' => get_bloginfo('language'), 'site_title' => get_bloginfo('name'), 'theme' => wp_get_theme()->get('Name') ]; } private function timeMatched() { $prevValue = get_option('_fluent_last_m_run'); if (!$prevValue) { return true; } return (time() - $prevValue) > 518400; // 6 days match } } PK!& 3libs/ff_plugin_updater/ff-fluentform-pro-update.phpnu[ FLUENTFORMPRO_DIR_FILE, // The current version of the plugin. // Also need to change in readme.txt and plugin header. 'version' => FLUENTFORMPRO_VERSION, // The main URL of your store for license verification 'store_url' => 'https://apiv2.wpmanageninja.com/plugin', 'store_site' => 'https://wpmanageninja.com', // Your name 'author' => 'WP Manage Ninja', // The URL to renew or purchase a license 'purchase_url' => 'https://wpmanageninja.com/downloads/fluentform-pro-add-on/', // The URL of your contact page 'contact_url' => 'https://wpmanageninja.com/contact', // This should match the download name exactly 'item_id' => '542', // The option names to store the license key and activation status 'license_key' => '_ff_fluentform_pro_license_key', 'license_status' => '_ff_fluentform_pro_license_status', // Option group param for the settings api 'option_group' => '_ff_fluentform_pro_license', // The plugin settings admin page slug 'admin_page_slug' => 'fluent_forms_add_ons', // If using add_menu_page, this is the parent slug to add a submenu item underneath. 'activate_url' => admin_url('admin.php?page=fluent_forms_settings&component=license_page'), // The translatable title of the plugin 'plugin_title' => __('Fluent Forms Pro Add On', 'fluentformpro'), 'menu_slug' => 'fluentform-pro-add-on', 'menu_title' => __('Fluent Forms Pro License', 'fluentformpro'), 'cache_time' => 168 * 60 * 60 // 7 days )); function fluentFormProActivateLicense($licenseKey) { $instance = FluentFormAddOnChecker::getInstance(); if ($instance) { return $instance->tryActivateLicense($licenseKey); } return false; } PK!Tlibs/index.phpnu[.el-menu-item{border-bottom:2px solid transparent;color:#909399;float:left;height:60px;line-height:60px;margin:0}.el-menu--horizontal>.el-menu-item a,.el-menu--horizontal>.el-menu-item a:hover{color:inherit}.el-menu--horizontal>.el-menu-item:not(.is-disabled):focus,.el-menu--horizontal>.el-menu-item:not(.is-disabled):hover{background-color:#fff}.el-menu--horizontal>.el-submenu{float:left}.el-menu--horizontal>.el-submenu:focus,.el-menu--horizontal>.el-submenu:hover{outline:0}.el-menu--horizontal>.el-submenu:focus .el-submenu__title,.el-menu--horizontal>.el-submenu:hover .el-submenu__title{color:#303133}.el-menu--horizontal>.el-submenu.is-active .el-submenu__title{border-bottom:2px solid #409eff;color:#303133}.el-menu--horizontal>.el-submenu .el-submenu__title{border-bottom:2px solid transparent;color:#909399;height:60px;line-height:60px}.el-menu--horizontal>.el-submenu .el-submenu__title:hover{background-color:#fff}.el-menu--horizontal>.el-submenu .el-submenu__icon-arrow{margin-left:8px;margin-top:-3px;position:static;vertical-align:middle}.el-menu--horizontal .el-menu .el-menu-item,.el-menu--horizontal .el-menu .el-submenu__title{background-color:#fff;color:#909399;float:none;height:36px;line-height:36px;padding:0 10px}.el-menu--horizontal .el-menu .el-menu-item.is-active,.el-menu--horizontal .el-menu .el-submenu.is-active>.el-submenu__title{color:#303133}.el-menu--horizontal .el-menu-item:not(.is-disabled):focus,.el-menu--horizontal .el-menu-item:not(.is-disabled):hover{color:#303133;outline:0}.el-menu--horizontal>.el-menu-item.is-active{border-bottom:2px solid #409eff;color:#303133}.el-menu--collapse{width:64px}.el-menu--collapse>.el-menu-item [class^=el-icon-],.el-menu--collapse>.el-submenu>.el-submenu__title [class^=el-icon-]{margin:0;text-align:center;vertical-align:middle;width:24px}.el-menu--collapse>.el-menu-item .el-submenu__icon-arrow,.el-menu--collapse>.el-submenu>.el-submenu__title .el-submenu__icon-arrow{display:none}.el-menu--collapse>.el-menu-item span,.el-menu--collapse>.el-submenu>.el-submenu__title span{display:inline-block;height:0;overflow:hidden;visibility:hidden;width:0}.el-menu--collapse>.el-menu-item.is-active i{color:inherit}.el-menu--collapse .el-menu .el-submenu{min-width:200px}.el-menu--collapse .el-submenu{position:relative}.el-menu--collapse .el-submenu .el-menu{border:1px solid #e4e7ed;border-radius:2px;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);left:100%;margin-left:5px;position:absolute;top:0;z-index:10}.el-menu--collapse .el-submenu.is-opened>.el-submenu__title .el-submenu__icon-arrow{transform:none}.el-menu--popup{border:none;border-radius:2px;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);min-width:200px;padding:5px 0;z-index:100}.el-menu-item,.el-submenu__title{line-height:56px;list-style:none;padding:0 20px;position:relative;white-space:nowrap}.el-menu--popup-bottom-start{margin-top:5px}.el-menu--popup-right-start{margin-left:5px;margin-right:5px}.el-menu-item{box-sizing:border-box;color:#303133;cursor:pointer;font-size:14px;height:56px;transition:border-color .3s,background-color .3s,color .3s}.el-menu-item *{vertical-align:middle}.el-menu-item i{color:#909399}.el-menu-item:focus,.el-menu-item:hover{background-color:#ecf5ff;outline:0}.el-menu-item.is-disabled{background:0 0!important;cursor:not-allowed;opacity:.25}.el-menu-item [class^=el-icon-]{font-size:18px;margin-right:5px;text-align:center;vertical-align:middle;width:24px}.el-menu-item.is-active{color:#409eff}.el-menu-item.is-active i{color:inherit}.el-submenu{list-style:none;margin:0;padding-left:0}.el-submenu__title{box-sizing:border-box;color:#303133;cursor:pointer;font-size:14px;height:56px;transition:border-color .3s,background-color .3s,color .3s}.el-submenu__title *{vertical-align:middle}.el-submenu__title i{color:#909399}.el-submenu__title:focus,.el-submenu__title:hover{background-color:#ecf5ff;outline:0}.el-submenu__title.is-disabled{background:0 0!important;cursor:not-allowed;opacity:.25}.el-submenu__title:hover{background-color:#ecf5ff}.el-submenu .el-menu{border:none}.el-submenu .el-menu-item{height:50px;line-height:50px;min-width:200px;padding:0 45px}.el-submenu__icon-arrow{font-size:12px;margin-top:-7px;position:absolute;right:20px;top:50%;transition:transform .3s}.el-submenu.is-active .el-submenu__title{border-bottom-color:#409eff}.el-submenu.is-opened>.el-submenu__title .el-submenu__icon-arrow{transform:rotate(180deg)}.el-submenu.is-disabled .el-menu-item,.el-submenu.is-disabled .el-submenu__title{background:0 0!important;cursor:not-allowed;opacity:.25}.el-submenu [class^=el-icon-]{font-size:18px;margin-right:5px;text-align:center;vertical-align:middle;width:24px}.el-menu-item-group>ul{padding:0}.el-menu-item-group__title{color:#909399;font-size:12px;line-height:normal;padding:7px 0 7px 20px}.horizontal-collapse-transition .el-submenu__title .el-submenu__icon-arrow{opacity:0;transition:.2s} .ff_pre_settings_wrapper{background:#f1f1f1;border-radius:20px;margin:50px auto;max-width:800px;padding:20px 50px 50px;text-align:center}.ff_pre_settings_wrapper h2{font-size:26px;line-height:36px;margin-bottom:10px}.ff_pre_settings_wrapper p{font-size:16px;margin-bottom:20px}.ff_payment_wrapper .el-tabs--border-card>.el-tabs__content{padding:45px}.ff_payment_sub_section{background:#f2f2f2;border-radius:8px;padding:20px 30px}.ff_connect_ok{background:#f0f9eb;border-left:5px solid #67c23a}.ff_connect_ok,.ff_connect_require{border-radius:5px;margin-bottom:20px;padding:15px 20px}.ff_connect_require{background:#fcf4e6;border-left:5px solid #ff6154}.ff_connect_require img{max-width:200px}.ff_pay_navigation{border-bottom:1px solid #e4e7ec;display:block;margin-bottom:20px;width:100%}.ff_pay_navigation li{cursor:pointer;display:inline-block;font-size:14px;font-weight:500;margin:0;padding-bottom:15px;position:relative}.ff_pay_navigation li:not(:last-child){margin-right:20px}.ff_pay_navigation li:after{background-color:#1a7efb;bottom:-1px;content:"";height:2px;left:0;position:absolute;transition:.3s;width:0}.ff_pay_navigation li.ff_active{color:#1a7efb}.ff_pay_navigation li.ff_active:after{width:100%}.el-menu-demo{background-color:transparent}.el-menu-demo.el-menu--horizontal{border-bottom:0}.el-menu-demo.el-menu--horizontal>.el-menu-item{border-bottom:0;border-radius:6px;color:#606266;display:block;float:none;height:auto;line-height:inherit;margin-bottom:10px;padding:8px 14px}.el-menu-demo.el-menu--horizontal>.el-menu-item.is-active,.el-menu-demo.el-menu--horizontal>.el-menu-item:hover{background-color:#ddddde;color:#1e1f21}.el-tabs__item{color:#606266;font-weight:400;height:auto;line-height:inherit;padding-bottom:15px;padding-left:15px;padding-right:15px}.el-tabs__nav-wrap:after{height:1px}.ff_method_settings_form h2{font-size:18px;margin-bottom:6px}.ff_method_settings_form p:not(.text-note){margin-bottom:15px} PK! &public/css/fluentform_transactions.cssnu[.ff_subscriptions .ff_subscription{background-color:#fff;border:2px solid #e3e8ee;color:#3a4f66;padding:15px 20px}.ff_subscriptions .ff_subscription button{-webkit-appearance:none;background:#fff;border:1px solid #dcdfe6;border-radius:4px;box-sizing:border-box;color:#606266;cursor:pointer;display:inline-block;font-size:14px;font-weight:500;line-height:1;margin:0;outline:0;padding:6px 15px;text-align:center;transition:.1s;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;white-space:nowrap}.ff_subscriptions .ff_subscription .ff_subscription_header{display:flex;flex-direction:row;flex-wrap:wrap;width:100%}@media only screen and (max-width:768px){.ff_subscriptions .ff_subscription .ff_subscription_header{flex-direction:column}.ff_subscriptions .ff_subscription .ff_subscription_header>div{display:flex;flex-basis:100%;flex:1;flex-direction:column}.ff_subscriptions .ff_subscription .ff_subscription_header>div.ff_plan_info{text-align:left}}.ff_subscriptions .ff_subscription .ff_subscription_header .ff_form_name{font-size:110%;font-weight:500}.ff_subscriptions .ff_subscription .ff_subscription_header>div{display:flex;flex-basis:100%;flex:1;flex-direction:column}.ff_subscriptions .ff_subscription .ff_subscription_header .ff_plan_info{text-align:right}.ff_subscriptions .ff_subscription .ff_subscription_header .pay_amount{font-size:20px;line-height:28px}.ff_subscriptions .ff_subscription .ff_subscription_header .ff_sub_name{color:#393c40;display:block;overflow:hidden;padding-bottom:10px;position:relative}.ff_subscriptions .ff_subscription .ff_subscription_header .ff_pay_status_badge{background-color:#d6ecff;border-radius:20px;color:#3d4eac;font-size:90%;font-weight:500;padding:2px 8px;text-transform:capitalize}.ff_subscriptions .ff_subscription .ff_subscription_header .ff_pay_status_badge.ff_pay_status_cancelled{background:#ff623e;color:#fff}.ff_subscriptions .ff_subscription .ff_subscription_header .ff_pay_status_badge.ff_pay_status_active{background:#67c23a;color:#fff}.ff_subscriptions .ff_subscription .ff_subscription_header .ff_billing_dates,.ff_subscriptions .ff_subscription .ff_subscription_header .ff_billing_text{margin:0;padding:0 0 10px}.ff_subscriptions .ff_subscription .ff_subscription_header .ff_billing_text{margin-top:5px}.ff_subscriptions .ff_subscription .ff_subscription_payments.ff_has_payments{background:#fafdff;border-top:1px solid #e3e8ed;margin:0 -20px -15px;padding:20px}.ff_subscriptions .ff_subscription span.ff_sub_id{font-size:80%;font-style:italic;opacity:.5}.ff_subscriptions .ff_sub_cancel_confirmation{background:#fff7f5;margin:10px -20px -20px;overflow:hidden;padding:20px;position:relative;text-align:center}.ff_subscriptions .ff_sub_cancel_confirmation button.ff_confirm_subscription_cancel{background:#cf3917;color:#fff} PK!9zFBBpublic/css/frameless.cssnu[.ff_frameless_page_body .ff_frameless_wrapper{background:#eee;min-height:100vh;padding-bottom:100px;padding-top:80px}.ff_frameless_page_body .ff_frameless_wrapper .ff_frameless_item{background-color:#fff;border-radius:8.5px;box-shadow:0 30px 40px 0 rgba(0,0,0,.25),inset 0 4px 0 0 #a1c5e5;box-sizing:border-box;color:#444;margin:0 auto;max-width:800px;padding:30px 40px}.ff_frameless_page_body .ff_frameless_wrapper .ff_frameless_item .ff_frameless_header{border-bottom:1px solid #e6e6e6;font-size:18px;font-weight:500;margin:0 -40px 20px;padding:0 40px 10px;text-align:center} PK!+[qqpublic/css/payment_entries.cssnu[.payments_wrapper{padding:24px}.payments_wrapper *{box-sizing:border-box}.payment_header .payment_title{display:inline-block;font-size:23px;margin-right:20px}.ff_brand{display:inline-flex}.ff_brand img{border-radius:4px;height:24px}.ff_badge+.ff_brand{margin-left:8px}tr.el-table__row td{padding:18px 0}.ff_form_group .el-select{display:block;width:100%}.ff_form_group_label{color:#1e1f21;display:block;font-size:14px;font-weight:500;margin-bottom:8px} .item_full_width{width:100%} .ff_coupon_form .el-form-item>label{font-weight:500;line-height:100%}.ff_coupon_form .el-form-item p{color:gray;font-size:12px;margin-top:5px} PK!:ubbpublic/css/styler_app.cssnu[@font-face{font-display:"auto";font-family:element-icons;font-style:normal;font-weight:400;src:url(../fonts/element-icons.woff?313f7dacf2076822059d2dca26dedfc6) format("woff"),url(../fonts/element-icons.ttf?4520188144a17fb24a6af28a70dae0ce) format("truetype")}[class*=" el-icon-"],[class^=el-icon-]{speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:inline-block;font-family:element-icons!important;font-style:normal;font-variant:normal;font-weight:400;line-height:1;text-transform:none;vertical-align:baseline}.el-icon-ice-cream-round:before{content:"\e6a0"}.el-icon-ice-cream-square:before{content:"\e6a3"}.el-icon-lollipop:before{content:"\e6a4"}.el-icon-potato-strips:before{content:"\e6a5"}.el-icon-milk-tea:before{content:"\e6a6"}.el-icon-ice-drink:before{content:"\e6a7"}.el-icon-ice-tea:before{content:"\e6a9"}.el-icon-coffee:before{content:"\e6aa"}.el-icon-orange:before{content:"\e6ab"}.el-icon-pear:before{content:"\e6ac"}.el-icon-apple:before{content:"\e6ad"}.el-icon-cherry:before{content:"\e6ae"}.el-icon-watermelon:before{content:"\e6af"}.el-icon-grape:before{content:"\e6b0"}.el-icon-refrigerator:before{content:"\e6b1"}.el-icon-goblet-square-full:before{content:"\e6b2"}.el-icon-goblet-square:before{content:"\e6b3"}.el-icon-goblet-full:before{content:"\e6b4"}.el-icon-goblet:before{content:"\e6b5"}.el-icon-cold-drink:before{content:"\e6b6"}.el-icon-coffee-cup:before{content:"\e6b8"}.el-icon-water-cup:before{content:"\e6b9"}.el-icon-hot-water:before{content:"\e6ba"}.el-icon-ice-cream:before{content:"\e6bb"}.el-icon-dessert:before{content:"\e6bc"}.el-icon-sugar:before{content:"\e6bd"}.el-icon-tableware:before{content:"\e6be"}.el-icon-burger:before{content:"\e6bf"}.el-icon-knife-fork:before{content:"\e6c1"}.el-icon-fork-spoon:before{content:"\e6c2"}.el-icon-chicken:before{content:"\e6c3"}.el-icon-food:before{content:"\e6c4"}.el-icon-dish-1:before{content:"\e6c5"}.el-icon-dish:before{content:"\e6c6"}.el-icon-moon-night:before{content:"\e6ee"}.el-icon-moon:before{content:"\e6f0"}.el-icon-cloudy-and-sunny:before{content:"\e6f1"}.el-icon-partly-cloudy:before{content:"\e6f2"}.el-icon-cloudy:before{content:"\e6f3"}.el-icon-sunny:before{content:"\e6f6"}.el-icon-sunset:before{content:"\e6f7"}.el-icon-sunrise-1:before{content:"\e6f8"}.el-icon-sunrise:before{content:"\e6f9"}.el-icon-heavy-rain:before{content:"\e6fa"}.el-icon-lightning:before{content:"\e6fb"}.el-icon-light-rain:before{content:"\e6fc"}.el-icon-wind-power:before{content:"\e6fd"}.el-icon-baseball:before{content:"\e712"}.el-icon-soccer:before{content:"\e713"}.el-icon-football:before{content:"\e715"}.el-icon-basketball:before{content:"\e716"}.el-icon-ship:before{content:"\e73f"}.el-icon-truck:before{content:"\e740"}.el-icon-bicycle:before{content:"\e741"}.el-icon-mobile-phone:before{content:"\e6d3"}.el-icon-service:before{content:"\e6d4"}.el-icon-key:before{content:"\e6e2"}.el-icon-unlock:before{content:"\e6e4"}.el-icon-lock:before{content:"\e6e5"}.el-icon-watch:before{content:"\e6fe"}.el-icon-watch-1:before{content:"\e6ff"}.el-icon-timer:before{content:"\e702"}.el-icon-alarm-clock:before{content:"\e703"}.el-icon-map-location:before{content:"\e704"}.el-icon-delete-location:before{content:"\e705"}.el-icon-add-location:before{content:"\e706"}.el-icon-location-information:before{content:"\e707"}.el-icon-location-outline:before{content:"\e708"}.el-icon-location:before{content:"\e79e"}.el-icon-place:before{content:"\e709"}.el-icon-discover:before{content:"\e70a"}.el-icon-first-aid-kit:before{content:"\e70b"}.el-icon-trophy-1:before{content:"\e70c"}.el-icon-trophy:before{content:"\e70d"}.el-icon-medal:before{content:"\e70e"}.el-icon-medal-1:before{content:"\e70f"}.el-icon-stopwatch:before{content:"\e710"}.el-icon-mic:before{content:"\e711"}.el-icon-copy-document:before{content:"\e718"}.el-icon-full-screen:before{content:"\e719"}.el-icon-switch-button:before{content:"\e71b"}.el-icon-aim:before{content:"\e71c"}.el-icon-crop:before{content:"\e71d"}.el-icon-odometer:before{content:"\e71e"}.el-icon-time:before{content:"\e71f"}.el-icon-bangzhu:before{content:"\e724"}.el-icon-close-notification:before{content:"\e726"}.el-icon-microphone:before{content:"\e727"}.el-icon-turn-off-microphone:before{content:"\e728"}.el-icon-position:before{content:"\e729"}.el-icon-postcard:before{content:"\e72a"}.el-icon-message:before{content:"\e72b"}.el-icon-chat-line-square:before{content:"\e72d"}.el-icon-chat-dot-square:before{content:"\e72e"}.el-icon-chat-dot-round:before{content:"\e72f"}.el-icon-chat-square:before{content:"\e730"}.el-icon-chat-line-round:before{content:"\e731"}.el-icon-chat-round:before{content:"\e732"}.el-icon-set-up:before{content:"\e733"}.el-icon-turn-off:before{content:"\e734"}.el-icon-open:before{content:"\e735"}.el-icon-connection:before{content:"\e736"}.el-icon-link:before{content:"\e737"}.el-icon-cpu:before{content:"\e738"}.el-icon-thumb:before{content:"\e739"}.el-icon-female:before{content:"\e73a"}.el-icon-male:before{content:"\e73b"}.el-icon-guide:before{content:"\e73c"}.el-icon-news:before{content:"\e73e"}.el-icon-price-tag:before{content:"\e744"}.el-icon-discount:before{content:"\e745"}.el-icon-wallet:before{content:"\e747"}.el-icon-coin:before{content:"\e748"}.el-icon-money:before{content:"\e749"}.el-icon-bank-card:before{content:"\e74a"}.el-icon-box:before{content:"\e74b"}.el-icon-present:before{content:"\e74c"}.el-icon-sell:before{content:"\e6d5"}.el-icon-sold-out:before{content:"\e6d6"}.el-icon-shopping-bag-2:before{content:"\e74d"}.el-icon-shopping-bag-1:before{content:"\e74e"}.el-icon-shopping-cart-2:before{content:"\e74f"}.el-icon-shopping-cart-1:before{content:"\e750"}.el-icon-shopping-cart-full:before{content:"\e751"}.el-icon-smoking:before{content:"\e752"}.el-icon-no-smoking:before{content:"\e753"}.el-icon-house:before{content:"\e754"}.el-icon-table-lamp:before{content:"\e755"}.el-icon-school:before{content:"\e756"}.el-icon-office-building:before{content:"\e757"}.el-icon-toilet-paper:before{content:"\e758"}.el-icon-notebook-2:before{content:"\e759"}.el-icon-notebook-1:before{content:"\e75a"}.el-icon-files:before{content:"\e75b"}.el-icon-collection:before{content:"\e75c"}.el-icon-receiving:before{content:"\e75d"}.el-icon-suitcase-1:before{content:"\e760"}.el-icon-suitcase:before{content:"\e761"}.el-icon-film:before{content:"\e763"}.el-icon-collection-tag:before{content:"\e765"}.el-icon-data-analysis:before{content:"\e766"}.el-icon-pie-chart:before{content:"\e767"}.el-icon-data-board:before{content:"\e768"}.el-icon-data-line:before{content:"\e76d"}.el-icon-reading:before{content:"\e769"}.el-icon-magic-stick:before{content:"\e76a"}.el-icon-coordinate:before{content:"\e76b"}.el-icon-mouse:before{content:"\e76c"}.el-icon-brush:before{content:"\e76e"}.el-icon-headset:before{content:"\e76f"}.el-icon-umbrella:before{content:"\e770"}.el-icon-scissors:before{content:"\e771"}.el-icon-mobile:before{content:"\e773"}.el-icon-attract:before{content:"\e774"}.el-icon-monitor:before{content:"\e775"}.el-icon-search:before{content:"\e778"}.el-icon-takeaway-box:before{content:"\e77a"}.el-icon-paperclip:before{content:"\e77d"}.el-icon-printer:before{content:"\e77e"}.el-icon-document-add:before{content:"\e782"}.el-icon-document:before{content:"\e785"}.el-icon-document-checked:before{content:"\e786"}.el-icon-document-copy:before{content:"\e787"}.el-icon-document-delete:before{content:"\e788"}.el-icon-document-remove:before{content:"\e789"}.el-icon-tickets:before{content:"\e78b"}.el-icon-folder-checked:before{content:"\e77f"}.el-icon-folder-delete:before{content:"\e780"}.el-icon-folder-remove:before{content:"\e781"}.el-icon-folder-add:before{content:"\e783"}.el-icon-folder-opened:before{content:"\e784"}.el-icon-folder:before{content:"\e78a"}.el-icon-edit-outline:before{content:"\e764"}.el-icon-edit:before{content:"\e78c"}.el-icon-date:before{content:"\e78e"}.el-icon-c-scale-to-original:before{content:"\e7c6"}.el-icon-view:before{content:"\e6ce"}.el-icon-loading:before{content:"\e6cf"}.el-icon-rank:before{content:"\e6d1"}.el-icon-sort-down:before{content:"\e7c4"}.el-icon-sort-up:before{content:"\e7c5"}.el-icon-sort:before{content:"\e6d2"}.el-icon-finished:before{content:"\e6cd"}.el-icon-refresh-left:before{content:"\e6c7"}.el-icon-refresh-right:before{content:"\e6c8"}.el-icon-refresh:before{content:"\e6d0"}.el-icon-video-play:before{content:"\e7c0"}.el-icon-video-pause:before{content:"\e7c1"}.el-icon-d-arrow-right:before{content:"\e6dc"}.el-icon-d-arrow-left:before{content:"\e6dd"}.el-icon-arrow-up:before{content:"\e6e1"}.el-icon-arrow-down:before{content:"\e6df"}.el-icon-arrow-right:before{content:"\e6e0"}.el-icon-arrow-left:before{content:"\e6de"}.el-icon-top-right:before{content:"\e6e7"}.el-icon-top-left:before{content:"\e6e8"}.el-icon-top:before{content:"\e6e6"}.el-icon-bottom:before{content:"\e6eb"}.el-icon-right:before{content:"\e6e9"}.el-icon-back:before{content:"\e6ea"}.el-icon-bottom-right:before{content:"\e6ec"}.el-icon-bottom-left:before{content:"\e6ed"}.el-icon-caret-top:before{content:"\e78f"}.el-icon-caret-bottom:before{content:"\e790"}.el-icon-caret-right:before{content:"\e791"}.el-icon-caret-left:before{content:"\e792"}.el-icon-d-caret:before{content:"\e79a"}.el-icon-share:before{content:"\e793"}.el-icon-menu:before{content:"\e798"}.el-icon-s-grid:before{content:"\e7a6"}.el-icon-s-check:before{content:"\e7a7"}.el-icon-s-data:before{content:"\e7a8"}.el-icon-s-opportunity:before{content:"\e7aa"}.el-icon-s-custom:before{content:"\e7ab"}.el-icon-s-claim:before{content:"\e7ad"}.el-icon-s-finance:before{content:"\e7ae"}.el-icon-s-comment:before{content:"\e7af"}.el-icon-s-flag:before{content:"\e7b0"}.el-icon-s-marketing:before{content:"\e7b1"}.el-icon-s-shop:before{content:"\e7b4"}.el-icon-s-open:before{content:"\e7b5"}.el-icon-s-management:before{content:"\e7b6"}.el-icon-s-ticket:before{content:"\e7b7"}.el-icon-s-release:before{content:"\e7b8"}.el-icon-s-home:before{content:"\e7b9"}.el-icon-s-promotion:before{content:"\e7ba"}.el-icon-s-operation:before{content:"\e7bb"}.el-icon-s-unfold:before{content:"\e7bc"}.el-icon-s-fold:before{content:"\e7a9"}.el-icon-s-platform:before{content:"\e7bd"}.el-icon-s-order:before{content:"\e7be"}.el-icon-s-cooperation:before{content:"\e7bf"}.el-icon-bell:before{content:"\e725"}.el-icon-message-solid:before{content:"\e799"}.el-icon-video-camera:before{content:"\e772"}.el-icon-video-camera-solid:before{content:"\e796"}.el-icon-camera:before{content:"\e779"}.el-icon-camera-solid:before{content:"\e79b"}.el-icon-download:before{content:"\e77c"}.el-icon-upload2:before{content:"\e77b"}.el-icon-upload:before{content:"\e7c3"}.el-icon-picture-outline-round:before{content:"\e75f"}.el-icon-picture-outline:before{content:"\e75e"}.el-icon-picture:before{content:"\e79f"}.el-icon-close:before{content:"\e6db"}.el-icon-check:before{content:"\e6da"}.el-icon-plus:before{content:"\e6d9"}.el-icon-minus:before{content:"\e6d8"}.el-icon-help:before{content:"\e73d"}.el-icon-s-help:before{content:"\e7b3"}.el-icon-circle-close:before{content:"\e78d"}.el-icon-circle-check:before{content:"\e720"}.el-icon-circle-plus-outline:before{content:"\e723"}.el-icon-remove-outline:before{content:"\e722"}.el-icon-zoom-out:before{content:"\e776"}.el-icon-zoom-in:before{content:"\e777"}.el-icon-error:before{content:"\e79d"}.el-icon-success:before{content:"\e79c"}.el-icon-circle-plus:before{content:"\e7a0"}.el-icon-remove:before{content:"\e7a2"}.el-icon-info:before{content:"\e7a1"}.el-icon-question:before{content:"\e7a4"}.el-icon-warning-outline:before{content:"\e6c9"}.el-icon-warning:before{content:"\e7a3"}.el-icon-goods:before{content:"\e7c2"}.el-icon-s-goods:before{content:"\e7b2"}.el-icon-star-off:before{content:"\e717"}.el-icon-star-on:before{content:"\e797"}.el-icon-more-outline:before{content:"\e6cc"}.el-icon-more:before{content:"\e794"}.el-icon-phone-outline:before{content:"\e6cb"}.el-icon-phone:before{content:"\e795"}.el-icon-user:before{content:"\e6e3"}.el-icon-user-solid:before{content:"\e7a5"}.el-icon-setting:before{content:"\e6ca"}.el-icon-s-tools:before{content:"\e7ac"}.el-icon-delete:before{content:"\e6d7"}.el-icon-delete-solid:before{content:"\e7c9"}.el-icon-eleme:before{content:"\e7c7"}.el-icon-platform-eleme:before{content:"\e7ca"}.el-icon-loading{animation:rotating 2s linear infinite}.el-icon--right{margin-left:5px}.el-icon--left{margin-right:5px}@keyframes rotating{0%{transform:rotate(0)}to{transform:rotate(1turn)}} @font-face{font-display:"auto";font-family:element-icons;font-style:normal;font-weight:400;src:url(../fonts/vendor/element-ui/packages/theme-chalk/src/element-icons.woff?313f7dacf2076822059d2dca26dedfc6) format("woff"),url(../fonts/vendor/element-ui/packages/theme-chalk/src/element-icons.ttf?4520188144a17fb24a6af28a70dae0ce) format("truetype")}[class*=" el-icon-"],[class^=el-icon-]{speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:inline-block;font-family:element-icons!important;font-style:normal;font-variant:normal;font-weight:400;line-height:1;text-transform:none;vertical-align:baseline}.el-icon-ice-cream-round:before{content:"\e6a0"}.el-icon-ice-cream-square:before{content:"\e6a3"}.el-icon-lollipop:before{content:"\e6a4"}.el-icon-potato-strips:before{content:"\e6a5"}.el-icon-milk-tea:before{content:"\e6a6"}.el-icon-ice-drink:before{content:"\e6a7"}.el-icon-ice-tea:before{content:"\e6a9"}.el-icon-coffee:before{content:"\e6aa"}.el-icon-orange:before{content:"\e6ab"}.el-icon-pear:before{content:"\e6ac"}.el-icon-apple:before{content:"\e6ad"}.el-icon-cherry:before{content:"\e6ae"}.el-icon-watermelon:before{content:"\e6af"}.el-icon-grape:before{content:"\e6b0"}.el-icon-refrigerator:before{content:"\e6b1"}.el-icon-goblet-square-full:before{content:"\e6b2"}.el-icon-goblet-square:before{content:"\e6b3"}.el-icon-goblet-full:before{content:"\e6b4"}.el-icon-goblet:before{content:"\e6b5"}.el-icon-cold-drink:before{content:"\e6b6"}.el-icon-coffee-cup:before{content:"\e6b8"}.el-icon-water-cup:before{content:"\e6b9"}.el-icon-hot-water:before{content:"\e6ba"}.el-icon-ice-cream:before{content:"\e6bb"}.el-icon-dessert:before{content:"\e6bc"}.el-icon-sugar:before{content:"\e6bd"}.el-icon-tableware:before{content:"\e6be"}.el-icon-burger:before{content:"\e6bf"}.el-icon-knife-fork:before{content:"\e6c1"}.el-icon-fork-spoon:before{content:"\e6c2"}.el-icon-chicken:before{content:"\e6c3"}.el-icon-food:before{content:"\e6c4"}.el-icon-dish-1:before{content:"\e6c5"}.el-icon-dish:before{content:"\e6c6"}.el-icon-moon-night:before{content:"\e6ee"}.el-icon-moon:before{content:"\e6f0"}.el-icon-cloudy-and-sunny:before{content:"\e6f1"}.el-icon-partly-cloudy:before{content:"\e6f2"}.el-icon-cloudy:before{content:"\e6f3"}.el-icon-sunny:before{content:"\e6f6"}.el-icon-sunset:before{content:"\e6f7"}.el-icon-sunrise-1:before{content:"\e6f8"}.el-icon-sunrise:before{content:"\e6f9"}.el-icon-heavy-rain:before{content:"\e6fa"}.el-icon-lightning:before{content:"\e6fb"}.el-icon-light-rain:before{content:"\e6fc"}.el-icon-wind-power:before{content:"\e6fd"}.el-icon-baseball:before{content:"\e712"}.el-icon-soccer:before{content:"\e713"}.el-icon-football:before{content:"\e715"}.el-icon-basketball:before{content:"\e716"}.el-icon-ship:before{content:"\e73f"}.el-icon-truck:before{content:"\e740"}.el-icon-bicycle:before{content:"\e741"}.el-icon-mobile-phone:before{content:"\e6d3"}.el-icon-service:before{content:"\e6d4"}.el-icon-key:before{content:"\e6e2"}.el-icon-unlock:before{content:"\e6e4"}.el-icon-lock:before{content:"\e6e5"}.el-icon-watch:before{content:"\e6fe"}.el-icon-watch-1:before{content:"\e6ff"}.el-icon-timer:before{content:"\e702"}.el-icon-alarm-clock:before{content:"\e703"}.el-icon-map-location:before{content:"\e704"}.el-icon-delete-location:before{content:"\e705"}.el-icon-add-location:before{content:"\e706"}.el-icon-location-information:before{content:"\e707"}.el-icon-location-outline:before{content:"\e708"}.el-icon-location:before{content:"\e79e"}.el-icon-place:before{content:"\e709"}.el-icon-discover:before{content:"\e70a"}.el-icon-first-aid-kit:before{content:"\e70b"}.el-icon-trophy-1:before{content:"\e70c"}.el-icon-trophy:before{content:"\e70d"}.el-icon-medal:before{content:"\e70e"}.el-icon-medal-1:before{content:"\e70f"}.el-icon-stopwatch:before{content:"\e710"}.el-icon-mic:before{content:"\e711"}.el-icon-copy-document:before{content:"\e718"}.el-icon-full-screen:before{content:"\e719"}.el-icon-switch-button:before{content:"\e71b"}.el-icon-aim:before{content:"\e71c"}.el-icon-crop:before{content:"\e71d"}.el-icon-odometer:before{content:"\e71e"}.el-icon-time:before{content:"\e71f"}.el-icon-bangzhu:before{content:"\e724"}.el-icon-close-notification:before{content:"\e726"}.el-icon-microphone:before{content:"\e727"}.el-icon-turn-off-microphone:before{content:"\e728"}.el-icon-position:before{content:"\e729"}.el-icon-postcard:before{content:"\e72a"}.el-icon-message:before{content:"\e72b"}.el-icon-chat-line-square:before{content:"\e72d"}.el-icon-chat-dot-square:before{content:"\e72e"}.el-icon-chat-dot-round:before{content:"\e72f"}.el-icon-chat-square:before{content:"\e730"}.el-icon-chat-line-round:before{content:"\e731"}.el-icon-chat-round:before{content:"\e732"}.el-icon-set-up:before{content:"\e733"}.el-icon-turn-off:before{content:"\e734"}.el-icon-open:before{content:"\e735"}.el-icon-connection:before{content:"\e736"}.el-icon-link:before{content:"\e737"}.el-icon-cpu:before{content:"\e738"}.el-icon-thumb:before{content:"\e739"}.el-icon-female:before{content:"\e73a"}.el-icon-male:before{content:"\e73b"}.el-icon-guide:before{content:"\e73c"}.el-icon-news:before{content:"\e73e"}.el-icon-price-tag:before{content:"\e744"}.el-icon-discount:before{content:"\e745"}.el-icon-wallet:before{content:"\e747"}.el-icon-coin:before{content:"\e748"}.el-icon-money:before{content:"\e749"}.el-icon-bank-card:before{content:"\e74a"}.el-icon-box:before{content:"\e74b"}.el-icon-present:before{content:"\e74c"}.el-icon-sell:before{content:"\e6d5"}.el-icon-sold-out:before{content:"\e6d6"}.el-icon-shopping-bag-2:before{content:"\e74d"}.el-icon-shopping-bag-1:before{content:"\e74e"}.el-icon-shopping-cart-2:before{content:"\e74f"}.el-icon-shopping-cart-1:before{content:"\e750"}.el-icon-shopping-cart-full:before{content:"\e751"}.el-icon-smoking:before{content:"\e752"}.el-icon-no-smoking:before{content:"\e753"}.el-icon-house:before{content:"\e754"}.el-icon-table-lamp:before{content:"\e755"}.el-icon-school:before{content:"\e756"}.el-icon-office-building:before{content:"\e757"}.el-icon-toilet-paper:before{content:"\e758"}.el-icon-notebook-2:before{content:"\e759"}.el-icon-notebook-1:before{content:"\e75a"}.el-icon-files:before{content:"\e75b"}.el-icon-collection:before{content:"\e75c"}.el-icon-receiving:before{content:"\e75d"}.el-icon-suitcase-1:before{content:"\e760"}.el-icon-suitcase:before{content:"\e761"}.el-icon-film:before{content:"\e763"}.el-icon-collection-tag:before{content:"\e765"}.el-icon-data-analysis:before{content:"\e766"}.el-icon-pie-chart:before{content:"\e767"}.el-icon-data-board:before{content:"\e768"}.el-icon-data-line:before{content:"\e76d"}.el-icon-reading:before{content:"\e769"}.el-icon-magic-stick:before{content:"\e76a"}.el-icon-coordinate:before{content:"\e76b"}.el-icon-mouse:before{content:"\e76c"}.el-icon-brush:before{content:"\e76e"}.el-icon-headset:before{content:"\e76f"}.el-icon-umbrella:before{content:"\e770"}.el-icon-scissors:before{content:"\e771"}.el-icon-mobile:before{content:"\e773"}.el-icon-attract:before{content:"\e774"}.el-icon-monitor:before{content:"\e775"}.el-icon-search:before{content:"\e778"}.el-icon-takeaway-box:before{content:"\e77a"}.el-icon-paperclip:before{content:"\e77d"}.el-icon-printer:before{content:"\e77e"}.el-icon-document-add:before{content:"\e782"}.el-icon-document:before{content:"\e785"}.el-icon-document-checked:before{content:"\e786"}.el-icon-document-copy:before{content:"\e787"}.el-icon-document-delete:before{content:"\e788"}.el-icon-document-remove:before{content:"\e789"}.el-icon-tickets:before{content:"\e78b"}.el-icon-folder-checked:before{content:"\e77f"}.el-icon-folder-delete:before{content:"\e780"}.el-icon-folder-remove:before{content:"\e781"}.el-icon-folder-add:before{content:"\e783"}.el-icon-folder-opened:before{content:"\e784"}.el-icon-folder:before{content:"\e78a"}.el-icon-edit-outline:before{content:"\e764"}.el-icon-edit:before{content:"\e78c"}.el-icon-date:before{content:"\e78e"}.el-icon-c-scale-to-original:before{content:"\e7c6"}.el-icon-view:before{content:"\e6ce"}.el-icon-loading:before{content:"\e6cf"}.el-icon-rank:before{content:"\e6d1"}.el-icon-sort-down:before{content:"\e7c4"}.el-icon-sort-up:before{content:"\e7c5"}.el-icon-sort:before{content:"\e6d2"}.el-icon-finished:before{content:"\e6cd"}.el-icon-refresh-left:before{content:"\e6c7"}.el-icon-refresh-right:before{content:"\e6c8"}.el-icon-refresh:before{content:"\e6d0"}.el-icon-video-play:before{content:"\e7c0"}.el-icon-video-pause:before{content:"\e7c1"}.el-icon-d-arrow-right:before{content:"\e6dc"}.el-icon-d-arrow-left:before{content:"\e6dd"}.el-icon-arrow-up:before{content:"\e6e1"}.el-icon-arrow-down:before{content:"\e6df"}.el-icon-arrow-right:before{content:"\e6e0"}.el-icon-arrow-left:before{content:"\e6de"}.el-icon-top-right:before{content:"\e6e7"}.el-icon-top-left:before{content:"\e6e8"}.el-icon-top:before{content:"\e6e6"}.el-icon-bottom:before{content:"\e6eb"}.el-icon-right:before{content:"\e6e9"}.el-icon-back:before{content:"\e6ea"}.el-icon-bottom-right:before{content:"\e6ec"}.el-icon-bottom-left:before{content:"\e6ed"}.el-icon-caret-top:before{content:"\e78f"}.el-icon-caret-bottom:before{content:"\e790"}.el-icon-caret-right:before{content:"\e791"}.el-icon-caret-left:before{content:"\e792"}.el-icon-d-caret:before{content:"\e79a"}.el-icon-share:before{content:"\e793"}.el-icon-menu:before{content:"\e798"}.el-icon-s-grid:before{content:"\e7a6"}.el-icon-s-check:before{content:"\e7a7"}.el-icon-s-data:before{content:"\e7a8"}.el-icon-s-opportunity:before{content:"\e7aa"}.el-icon-s-custom:before{content:"\e7ab"}.el-icon-s-claim:before{content:"\e7ad"}.el-icon-s-finance:before{content:"\e7ae"}.el-icon-s-comment:before{content:"\e7af"}.el-icon-s-flag:before{content:"\e7b0"}.el-icon-s-marketing:before{content:"\e7b1"}.el-icon-s-shop:before{content:"\e7b4"}.el-icon-s-open:before{content:"\e7b5"}.el-icon-s-management:before{content:"\e7b6"}.el-icon-s-ticket:before{content:"\e7b7"}.el-icon-s-release:before{content:"\e7b8"}.el-icon-s-home:before{content:"\e7b9"}.el-icon-s-promotion:before{content:"\e7ba"}.el-icon-s-operation:before{content:"\e7bb"}.el-icon-s-unfold:before{content:"\e7bc"}.el-icon-s-fold:before{content:"\e7a9"}.el-icon-s-platform:before{content:"\e7bd"}.el-icon-s-order:before{content:"\e7be"}.el-icon-s-cooperation:before{content:"\e7bf"}.el-icon-bell:before{content:"\e725"}.el-icon-message-solid:before{content:"\e799"}.el-icon-video-camera:before{content:"\e772"}.el-icon-video-camera-solid:before{content:"\e796"}.el-icon-camera:before{content:"\e779"}.el-icon-camera-solid:before{content:"\e79b"}.el-icon-download:before{content:"\e77c"}.el-icon-upload2:before{content:"\e77b"}.el-icon-upload:before{content:"\e7c3"}.el-icon-picture-outline-round:before{content:"\e75f"}.el-icon-picture-outline:before{content:"\e75e"}.el-icon-picture:before{content:"\e79f"}.el-icon-close:before{content:"\e6db"}.el-icon-check:before{content:"\e6da"}.el-icon-plus:before{content:"\e6d9"}.el-icon-minus:before{content:"\e6d8"}.el-icon-help:before{content:"\e73d"}.el-icon-s-help:before{content:"\e7b3"}.el-icon-circle-close:before{content:"\e78d"}.el-icon-circle-check:before{content:"\e720"}.el-icon-circle-plus-outline:before{content:"\e723"}.el-icon-remove-outline:before{content:"\e722"}.el-icon-zoom-out:before{content:"\e776"}.el-icon-zoom-in:before{content:"\e777"}.el-icon-error:before{content:"\e79d"}.el-icon-success:before{content:"\e79c"}.el-icon-circle-plus:before{content:"\e7a0"}.el-icon-remove:before{content:"\e7a2"}.el-icon-info:before{content:"\e7a1"}.el-icon-question:before{content:"\e7a4"}.el-icon-warning-outline:before{content:"\e6c9"}.el-icon-warning:before{content:"\e7a3"}.el-icon-goods:before{content:"\e7c2"}.el-icon-s-goods:before{content:"\e7b2"}.el-icon-star-off:before{content:"\e717"}.el-icon-star-on:before{content:"\e797"}.el-icon-more-outline:before{content:"\e6cc"}.el-icon-more:before{content:"\e794"}.el-icon-phone-outline:before{content:"\e6cb"}.el-icon-phone:before{content:"\e795"}.el-icon-user:before{content:"\e6e3"}.el-icon-user-solid:before{content:"\e7a5"}.el-icon-setting:before{content:"\e6ca"}.el-icon-s-tools:before{content:"\e7ac"}.el-icon-delete:before{content:"\e6d7"}.el-icon-delete-solid:before{content:"\e7c9"}.el-icon-eleme:before{content:"\e7c7"}.el-icon-platform-eleme:before{content:"\e7ca"}.el-icon-loading{animation:rotating 2s linear infinite}.el-icon--right{margin-left:5px}.el-icon--left{margin-right:5px}@keyframes rotating{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.el-pagination{color:#303133;font-weight:700;padding:2px 5px;white-space:nowrap}.el-pagination:after,.el-pagination:before{content:"";display:table}.el-pagination:after{clear:both}.el-pagination button,.el-pagination span:not([class*=suffix]){box-sizing:border-box;display:inline-block;font-size:13px;height:28px;line-height:28px;min-width:35.5px;vertical-align:top}.el-pagination .el-input__inner{-moz-appearance:textfield;line-height:normal;text-align:center}.el-pagination .el-input__suffix{right:0;transform:scale(.8)}.el-pagination .el-select .el-input{margin:0 5px;width:100px}.el-pagination .el-select .el-input .el-input__inner{border-radius:3px;padding-right:25px}.el-pagination button{background:transparent;border:none;padding:0 6px}.el-pagination button:focus{outline:none}.el-pagination button:hover{color:#1a7efb}.el-pagination button:disabled{background-color:#fff;color:#afb3ba;cursor:not-allowed}.el-pagination .btn-next,.el-pagination .btn-prev{background:50% no-repeat;background-color:#fff;background-size:16px;color:#303133;cursor:pointer;margin:0}.el-pagination .btn-next .el-icon,.el-pagination .btn-prev .el-icon{display:block;font-size:12px;font-weight:700}.el-pagination .btn-prev{padding-right:12px}.el-pagination .btn-next{padding-left:12px}.el-pagination .el-pager li.disabled{color:#afb3ba;cursor:not-allowed}.el-pagination--small .btn-next,.el-pagination--small .btn-prev,.el-pagination--small .el-pager li,.el-pagination--small .el-pager li.btn-quicknext,.el-pagination--small .el-pager li.btn-quickprev,.el-pagination--small .el-pager li:last-child{border-color:transparent;font-size:12px;height:22px;line-height:22px;min-width:22px}.el-pagination--small .arrow.disabled{visibility:hidden}.el-pagination--small .more:before,.el-pagination--small li.more:before{line-height:24px}.el-pagination--small button,.el-pagination--small span:not([class*=suffix]){height:22px;line-height:22px}.el-pagination--small .el-pagination__editor,.el-pagination--small .el-pagination__editor.el-input .el-input__inner{height:22px}.el-pagination__sizes{color:#606266;font-weight:400;margin:0 10px 0 0}.el-pagination__sizes .el-input .el-input__inner{font-size:13px;padding-left:8px}.el-pagination__sizes .el-input .el-input__inner:hover{border-color:#1a7efb}.el-pagination__total{color:#606266;font-weight:400;margin-right:10px}.el-pagination__jump{color:#606266;font-weight:400;margin-left:24px}.el-pagination__jump .el-input__inner{padding:0 3px}.el-pagination__rightwrapper{float:right}.el-pagination__editor{border-radius:3px;box-sizing:border-box;height:28px;line-height:18px;margin:0 2px;padding:0 2px;text-align:center}.el-pagination__editor.el-input{width:50px}.el-pagination__editor.el-input .el-input__inner{height:28px}.el-pagination__editor .el-input__inner::-webkit-inner-spin-button,.el-pagination__editor .el-input__inner::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.el-pagination.is-background .btn-next,.el-pagination.is-background .btn-prev,.el-pagination.is-background .el-pager li{background-color:#ededed;border-radius:2px;color:#606266;margin:0 5px;min-width:30px}.el-pagination.is-background .btn-next.disabled,.el-pagination.is-background .btn-prev.disabled,.el-pagination.is-background .el-pager li.disabled{color:#afb3ba}.el-pagination.is-background .btn-next,.el-pagination.is-background .btn-prev{padding:0}.el-pagination.is-background .btn-next:disabled,.el-pagination.is-background .btn-prev:disabled{color:#afb3ba}.el-pagination.is-background .el-pager li:not(.disabled):hover{color:#1a7efb}.el-pagination.is-background .el-pager li:not(.disabled).active{background-color:#1a7efb;color:#fff}.el-pagination.is-background.el-pagination--small .btn-next,.el-pagination.is-background.el-pagination--small .btn-prev,.el-pagination.is-background.el-pagination--small .el-pager li{margin:0 3px;min-width:22px}.el-pager{display:inline-block;font-size:0;list-style:none;margin:0;padding:0;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:top}.el-pager .more:before{line-height:30px}.el-pager li{background:#fff;box-sizing:border-box;cursor:pointer;display:inline-block;font-size:13px;height:28px;line-height:28px;margin:0;min-width:35.5px;padding:0 4px;text-align:center;vertical-align:top}.el-pager li.btn-quicknext,.el-pager li.btn-quickprev{color:#303133;line-height:28px}.el-pager li.btn-quicknext.disabled,.el-pager li.btn-quickprev.disabled{color:#afb3ba}.el-pager li.btn-quicknext:hover,.el-pager li.btn-quickprev:hover{cursor:pointer}.el-pager li.active+li{border-left:0}.el-pager li:hover{color:#1a7efb}.el-pager li.active{color:#1a7efb;cursor:default}.el-dialog{background:#fff;border-radius:4px;box-shadow:0 1px 3px rgba(0,0,0,.3);box-sizing:border-box;margin:0 auto 50px;position:relative;width:50%}.el-dialog.is-fullscreen{height:100%;margin-bottom:0;margin-top:0;overflow:auto;width:100%}.el-dialog__wrapper{bottom:0;left:0;margin:0;overflow:auto;position:fixed;right:0;top:0}.el-dialog__header{padding:20px 20px 10px}.el-dialog__headerbtn{background:transparent;border:none;cursor:pointer;font-size:16px;outline:none;padding:0;position:absolute;right:20px;top:20px}.el-dialog__headerbtn .el-dialog__close{color:#4b4c4d}.el-dialog__headerbtn:focus .el-dialog__close,.el-dialog__headerbtn:hover .el-dialog__close{color:#1a7efb}.el-dialog__title{color:#303133;font-size:18px;line-height:24px}.el-dialog__body{color:#606266;font-size:14px;padding:30px 20px;word-break:break-all}.el-dialog__footer{box-sizing:border-box;padding:10px 20px 20px;text-align:right}.el-dialog--center{text-align:center}.el-dialog--center .el-dialog__body{padding:25px 25px 30px;text-align:initial}.el-dialog--center .el-dialog__footer{text-align:inherit}.dialog-fade-enter-active{animation:dialog-fade-in .3s}.dialog-fade-leave-active{animation:dialog-fade-out .3s}@keyframes dialog-fade-in{0%{opacity:0;transform:translate3d(0,-20px,0)}to{opacity:1;transform:translateZ(0)}}@keyframes dialog-fade-out{0%{opacity:1;transform:translateZ(0)}to{opacity:0;transform:translate3d(0,-20px,0)}}.el-autocomplete{display:inline-block;position:relative}.el-autocomplete-suggestion{background-color:#fff;border:1px solid #e4e7ed;border-radius:7px;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-sizing:border-box;margin:5px 0}.el-autocomplete-suggestion__wrap{box-sizing:border-box;max-height:280px;padding:10px 0}.el-autocomplete-suggestion__list{margin:0;padding:0}.el-autocomplete-suggestion li{color:#606266;cursor:pointer;font-size:14px;line-height:34px;list-style:none;margin:0;overflow:hidden;padding:0 20px;text-overflow:ellipsis;white-space:nowrap}.el-autocomplete-suggestion li.highlighted,.el-autocomplete-suggestion li:hover{background-color:#f5f7fa}.el-autocomplete-suggestion li.divider{border-top:1px solid #000;margin-top:6px}.el-autocomplete-suggestion li.divider:last-child{margin-bottom:-6px}.el-autocomplete-suggestion.is-loading li{color:#999;font-size:20px;height:100px;line-height:100px;text-align:center}.el-autocomplete-suggestion.is-loading li:after{content:"";display:inline-block;height:100%;vertical-align:middle}.el-autocomplete-suggestion.is-loading li:hover{background-color:#fff}.el-autocomplete-suggestion.is-loading .el-icon-loading{vertical-align:middle}.el-dropdown{color:#606266;display:inline-block;font-size:14px;position:relative}.el-dropdown .el-button-group{display:block}.el-dropdown .el-button-group .el-button{float:none}.el-dropdown .el-dropdown__caret-button{border-left:none;padding-left:5px;padding-right:5px;position:relative}.el-dropdown .el-dropdown__caret-button:before{background:hsla(0,0%,100%,.5);bottom:5px;content:"";display:block;left:0;position:absolute;top:5px;width:1px}.el-dropdown .el-dropdown__caret-button.el-button--default:before{background:hsla(220,4%,86%,.5)}.el-dropdown .el-dropdown__caret-button:hover:not(.is-disabled):before{bottom:0;top:0}.el-dropdown .el-dropdown__caret-button .el-dropdown__icon{padding-left:0}.el-dropdown__icon{font-size:12px;margin:0 3px}.el-dropdown .el-dropdown-selfdefine:focus:active,.el-dropdown .el-dropdown-selfdefine:focus:not(.focusing){outline-width:0}.el-dropdown [disabled]{color:#bbb;cursor:not-allowed}.el-dropdown-menu{background-color:#fff;border:1px solid #ebeef5;border-radius:7px;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);left:0;margin:5px 0;padding:10px 0;position:absolute;top:0;z-index:10}.el-dropdown-menu__item{color:#606266;cursor:pointer;font-size:14px;line-height:36px;list-style:none;margin:0;outline:none;padding:0 20px}.el-dropdown-menu__item:focus,.el-dropdown-menu__item:not(.is-disabled):hover{background-color:#e8f2ff;color:#4898fc}.el-dropdown-menu__item i{margin-right:5px}.el-dropdown-menu__item--divided{border-top:1px solid #ebeef5;margin-top:6px;position:relative}.el-dropdown-menu__item--divided:before{background-color:#fff;content:"";display:block;height:6px;margin:0 -20px}.el-dropdown-menu__item.is-disabled{color:#bbb;cursor:default;pointer-events:none}.el-dropdown-menu--medium{padding:6px 0}.el-dropdown-menu--medium .el-dropdown-menu__item{font-size:14px;line-height:30px;padding:0 17px}.el-dropdown-menu--medium .el-dropdown-menu__item.el-dropdown-menu__item--divided{margin-top:6px}.el-dropdown-menu--medium .el-dropdown-menu__item.el-dropdown-menu__item--divided:before{height:6px;margin:0 -17px}.el-dropdown-menu--small{padding:6px 0}.el-dropdown-menu--small .el-dropdown-menu__item{font-size:13px;line-height:27px;padding:0 15px}.el-dropdown-menu--small .el-dropdown-menu__item.el-dropdown-menu__item--divided{margin-top:4px}.el-dropdown-menu--small .el-dropdown-menu__item.el-dropdown-menu__item--divided:before{height:4px;margin:0 -15px}.el-dropdown-menu--mini{padding:3px 0}.el-dropdown-menu--mini .el-dropdown-menu__item{font-size:12px;line-height:24px;padding:0 10px}.el-dropdown-menu--mini .el-dropdown-menu__item.el-dropdown-menu__item--divided{margin-top:3px}.el-dropdown-menu--mini .el-dropdown-menu__item.el-dropdown-menu__item--divided:before{height:3px;margin:0 -10px}.el-menu{background-color:#fff;border-right:1px solid #e6e6e6;list-style:none;margin:0;padding-left:0;position:relative}.el-menu:after,.el-menu:before{content:"";display:table}.el-menu:after{clear:both}.el-menu.el-menu--horizontal{border-bottom:1px solid #e6e6e6}.el-menu--horizontal{border-right:none}.el-menu--horizontal>.el-menu-item{border-bottom:2px solid transparent;color:#909399;float:left;height:60px;line-height:60px;margin:0}.el-menu--horizontal>.el-menu-item a,.el-menu--horizontal>.el-menu-item a:hover{color:inherit}.el-menu--horizontal>.el-menu-item:not(.is-disabled):focus,.el-menu--horizontal>.el-menu-item:not(.is-disabled):hover{background-color:#fff}.el-menu--horizontal>.el-submenu{float:left}.el-menu--horizontal>.el-submenu:focus,.el-menu--horizontal>.el-submenu:hover{outline:none}.el-menu--horizontal>.el-submenu:focus .el-submenu__title,.el-menu--horizontal>.el-submenu:hover .el-submenu__title{color:#303133}.el-menu--horizontal>.el-submenu.is-active .el-submenu__title{border-bottom:2px solid #1a7efb;color:#303133}.el-menu--horizontal>.el-submenu .el-submenu__title{border-bottom:2px solid transparent;color:#909399;height:60px;line-height:60px}.el-menu--horizontal>.el-submenu .el-submenu__title:hover{background-color:#fff}.el-menu--horizontal>.el-submenu .el-submenu__icon-arrow{margin-left:8px;margin-top:-3px;position:static;vertical-align:middle}.el-menu--horizontal .el-menu .el-menu-item,.el-menu--horizontal .el-menu .el-submenu__title{background-color:#fff;color:#909399;float:none;height:36px;line-height:36px;padding:0 10px}.el-menu--horizontal .el-menu .el-menu-item.is-active,.el-menu--horizontal .el-menu .el-submenu.is-active>.el-submenu__title{color:#303133}.el-menu--horizontal .el-menu-item:not(.is-disabled):focus,.el-menu--horizontal .el-menu-item:not(.is-disabled):hover{color:#303133;outline:none}.el-menu--horizontal>.el-menu-item.is-active{border-bottom:2px solid #1a7efb;color:#303133}.el-menu--collapse{width:64px}.el-menu--collapse>.el-menu-item [class^=el-icon-],.el-menu--collapse>.el-submenu>.el-submenu__title [class^=el-icon-]{margin:0;text-align:center;vertical-align:middle;width:24px}.el-menu--collapse>.el-menu-item .el-submenu__icon-arrow,.el-menu--collapse>.el-submenu>.el-submenu__title .el-submenu__icon-arrow{display:none}.el-menu--collapse>.el-menu-item span,.el-menu--collapse>.el-submenu>.el-submenu__title span{display:inline-block;height:0;overflow:hidden;visibility:hidden;width:0}.el-menu--collapse>.el-menu-item.is-active i{color:inherit}.el-menu--collapse .el-menu .el-submenu{min-width:200px}.el-menu--collapse .el-submenu{position:relative}.el-menu--collapse .el-submenu .el-menu{border:1px solid #e4e7ed;border-radius:4px;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);left:100%;margin-left:5px;position:absolute;top:0;z-index:10}.el-menu--collapse .el-submenu.is-opened>.el-submenu__title .el-submenu__icon-arrow{transform:none}.el-menu--popup{border:none;border-radius:4px;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);min-width:200px;padding:5px 0;z-index:100}.el-menu--popup-bottom-start{margin-top:5px}.el-menu--popup-right-start{margin-left:5px;margin-right:5px}.el-menu-item{box-sizing:border-box;color:#303133;cursor:pointer;font-size:14px;height:56px;line-height:56px;list-style:none;padding:0 20px;position:relative;transition:border-color .3s,background-color .3s,color .3s;white-space:nowrap}.el-menu-item *{vertical-align:middle}.el-menu-item i{color:#909399}.el-menu-item:focus,.el-menu-item:hover{background-color:#e8f2ff;outline:none}.el-menu-item.is-disabled{background:none!important;cursor:not-allowed;opacity:.25}.el-menu-item [class^=el-icon-]{font-size:18px;margin-right:5px;text-align:center;vertical-align:middle;width:24px}.el-menu-item.is-active{color:#1a7efb}.el-menu-item.is-active i{color:inherit}.el-submenu{list-style:none;margin:0;padding-left:0}.el-submenu__title{box-sizing:border-box;color:#303133;cursor:pointer;font-size:14px;height:56px;line-height:56px;list-style:none;padding:0 20px;position:relative;transition:border-color .3s,background-color .3s,color .3s;white-space:nowrap}.el-submenu__title *{vertical-align:middle}.el-submenu__title i{color:#909399}.el-submenu__title:focus,.el-submenu__title:hover{background-color:#e8f2ff;outline:none}.el-submenu__title.is-disabled{background:none!important;cursor:not-allowed;opacity:.25}.el-submenu__title:hover{background-color:#e8f2ff}.el-submenu .el-menu{border:none}.el-submenu .el-menu-item{height:50px;line-height:50px;min-width:200px;padding:0 45px}.el-submenu__icon-arrow{font-size:12px;margin-top:-7px;position:absolute;right:20px;top:50%;transition:transform .3s}.el-submenu.is-active .el-submenu__title{border-bottom-color:#1a7efb}.el-submenu.is-opened>.el-submenu__title .el-submenu__icon-arrow{transform:rotate(180deg)}.el-submenu.is-disabled .el-menu-item,.el-submenu.is-disabled .el-submenu__title{background:none!important;cursor:not-allowed;opacity:.25}.el-submenu [class^=el-icon-]{font-size:18px;margin-right:5px;text-align:center;vertical-align:middle;width:24px}.el-menu-item-group>ul{padding:0}.el-menu-item-group__title{color:#909399;font-size:12px;line-height:normal;padding:7px 0 7px 20px}.horizontal-collapse-transition .el-submenu__title .el-submenu__icon-arrow{opacity:0;transition:.2s}.el-radio-group{display:inline-block;font-size:0;line-height:1;vertical-align:middle}.el-radio-button,.el-radio-button__inner{display:inline-block;outline:none;position:relative}.el-radio-button__inner{-webkit-appearance:none;background:#fff;border:1px solid #dadbdd;border-left:0;border-radius:0;box-sizing:border-box;color:#606266;cursor:pointer;font-size:14px;font-weight:500;line-height:1;margin:0;padding:12px 20px;text-align:center;transition:all .3s cubic-bezier(.645,.045,.355,1);vertical-align:middle;white-space:nowrap}.el-radio-button__inner.is-round{padding:12px 20px}.el-radio-button__inner:hover{color:#1a7efb}.el-radio-button__inner [class*=el-icon-]{line-height:.9}.el-radio-button__inner [class*=el-icon-]+span{margin-left:5px}.el-radio-button:first-child .el-radio-button__inner{border-left:1px solid #dadbdd;border-radius:7px 0 0 7px;box-shadow:none!important}.el-radio-button__orig-radio{opacity:0;outline:none;position:absolute;z-index:-1}.el-radio-button__orig-radio:checked+.el-radio-button__inner{background-color:#1a7efb;border-color:#1a7efb;box-shadow:-1px 0 0 0 #1a7efb;color:#fff}.el-radio-button__orig-radio:disabled+.el-radio-button__inner{background-color:#fff;background-image:none;border-color:#ebeef5;box-shadow:none;color:#afb3ba;cursor:not-allowed}.el-radio-button__orig-radio:disabled:checked+.el-radio-button__inner{background-color:#f2f6fc}.el-radio-button:last-child .el-radio-button__inner{border-radius:0 7px 7px 0}.el-radio-button:first-child:last-child .el-radio-button__inner{border-radius:7px}.el-radio-button--medium .el-radio-button__inner{border-radius:0;font-size:14px;padding:10px 20px}.el-radio-button--medium .el-radio-button__inner.is-round{padding:10px 20px}.el-radio-button--small .el-radio-button__inner{border-radius:0;font-size:13px;padding:8px 11px}.el-radio-button--small .el-radio-button__inner.is-round{padding:8px 11px}.el-radio-button--mini .el-radio-button__inner{border-radius:0;font-size:12px;padding:7px 15px}.el-radio-button--mini .el-radio-button__inner.is-round{padding:7px 15px}.el-radio-button:focus:not(.is-focus):not(:active):not(.is-disabled){box-shadow:0 0 2px 2px #1a7efb}.el-switch{align-items:center;display:inline-flex;font-size:14px;height:20px;line-height:20px;position:relative;vertical-align:middle}.el-switch.is-disabled .el-switch__core,.el-switch.is-disabled .el-switch__label{cursor:not-allowed}.el-switch__label{color:#303133;cursor:pointer;display:inline-block;font-size:14px;font-weight:500;height:20px;transition:.2s;vertical-align:middle}.el-switch__label.is-active{color:#1a7efb}.el-switch__label--left{margin-right:10px}.el-switch__label--right{margin-left:10px}.el-switch__label *{display:inline-block;font-size:14px;line-height:1}.el-switch__input{height:0;margin:0;opacity:0;position:absolute;width:0}.el-switch__core{background:#edeae9;border:1px solid #edeae9;border-radius:10px;box-sizing:border-box;cursor:pointer;display:inline-block;height:20px;margin:0;outline:none;position:relative;transition:border-color .3s,background-color .3s;vertical-align:middle;width:40px}.el-switch__core:after{background-color:#fff;border-radius:100%;content:"";height:16px;left:1px;position:absolute;top:1px;transition:all .3s;width:16px}.el-switch.is-checked .el-switch__core{background-color:#00b27f;border-color:#00b27f}.el-switch.is-checked .el-switch__core:after{left:100%;margin-left:-17px}.el-switch.is-disabled{opacity:.6}.el-switch--wide .el-switch__label.el-switch__label--left span{left:10px}.el-switch--wide .el-switch__label.el-switch__label--right span{right:10px}.el-switch .label-fade-enter,.el-switch .label-fade-leave-active{opacity:0}.el-select-dropdown{background-color:#fff;border:1px solid #e4e7ed;border-radius:7px;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-sizing:border-box;margin:5px 0;position:absolute;z-index:1001}.el-select-dropdown.is-multiple .el-select-dropdown__item{padding-right:40px}.el-select-dropdown.is-multiple .el-select-dropdown__item.selected{background-color:#fff;color:#1a7efb}.el-select-dropdown.is-multiple .el-select-dropdown__item.selected.hover{background-color:#f5f7fa}.el-select-dropdown.is-multiple .el-select-dropdown__item.selected:after{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;content:"\e6da";font-family:element-icons;font-size:12px;font-weight:700;position:absolute;right:20px}.el-select-dropdown .el-scrollbar.is-empty .el-select-dropdown__list{padding:0}.el-select-dropdown__empty{color:#999;font-size:14px;margin:0;padding:10px 0;text-align:center}.el-select-dropdown__wrap{max-height:274px}.el-select-dropdown__list{box-sizing:border-box;list-style:none;margin:0;padding:6px 0}.el-select-dropdown__item{box-sizing:border-box;color:#606266;cursor:pointer;font-size:14px;height:34px;line-height:34px;overflow:hidden;padding:0 20px;position:relative;text-overflow:ellipsis;white-space:nowrap}.el-select-dropdown__item.is-disabled{color:#afb3ba;cursor:not-allowed}.el-select-dropdown__item.is-disabled:hover{background-color:#fff}.el-select-dropdown__item.hover,.el-select-dropdown__item:hover{background-color:#f5f7fa}.el-select-dropdown__item.selected{color:#1a7efb;font-weight:700}.el-select-group{margin:0;padding:0}.el-select-group__wrap{list-style:none;margin:0;padding:0;position:relative}.el-select-group__wrap:not(:last-of-type){padding-bottom:24px}.el-select-group__wrap:not(:last-of-type):after{background:#e4e7ed;bottom:12px;content:"";display:block;height:1px;left:20px;position:absolute;right:20px}.el-select-group__title{color:#4b4c4d;font-size:12px;line-height:30px;padding-left:20px}.el-select-group .el-select-dropdown__item{padding-left:20px}.el-select{display:inline-block;position:relative}.el-select .el-select__tags>span{display:contents}.el-select:hover .el-input__inner{border-color:#afb3ba}.el-select .el-input__inner{cursor:pointer;padding-right:35px}.el-select .el-input__inner:focus{border-color:#1a7efb}.el-select .el-input .el-select__caret{color:#afb3ba;cursor:pointer;font-size:14px;transform:rotate(180deg);transition:transform .3s}.el-select .el-input .el-select__caret.is-reverse{transform:rotate(0deg)}.el-select .el-input .el-select__caret.is-show-close{border-radius:100%;color:#afb3ba;font-size:14px;text-align:center;transform:rotate(180deg);transition:color .2s cubic-bezier(.645,.045,.355,1)}.el-select .el-input .el-select__caret.is-show-close:hover{color:#909399}.el-select .el-input.is-disabled .el-input__inner{cursor:not-allowed}.el-select .el-input.is-disabled .el-input__inner:hover{border-color:#e4e7ed}.el-select .el-input.is-focus .el-input__inner{border-color:#1a7efb}.el-select>.el-input{display:block}.el-select__input{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:transparent;border:none;color:#666;font-size:14px;height:28px;margin-left:15px;outline:none;padding:0}.el-select__input.is-mini{height:14px}.el-select__close{color:#afb3ba;cursor:pointer;font-size:14px;line-height:18px;position:absolute;right:25px;top:8px;z-index:1000}.el-select__close:hover{color:#909399}.el-select__tags{align-items:center;display:flex;flex-wrap:wrap;line-height:normal;position:absolute;top:50%;transform:translateY(-50%);white-space:normal;z-index:1}.el-select__tags-text{overflow:hidden;text-overflow:ellipsis}.el-select .el-tag{align-items:center;background-color:#f0f2f5;border-color:transparent;box-sizing:border-box;display:flex;margin:2px 0 2px 6px;max-width:100%}.el-select .el-tag__close.el-icon-close{background-color:#afb3ba;color:#fff;flex-shrink:0;top:0}.el-select .el-tag__close.el-icon-close:hover{background-color:#909399}.el-select .el-tag__close.el-icon-close:before{display:block;transform:translateY(.5px)}.el-table{background-color:#fff;box-sizing:border-box;color:#606266;flex:1;font-size:14px;max-width:100%;overflow:hidden;position:relative;width:100%}.el-table__empty-block{align-items:center;display:flex;justify-content:center;min-height:60px;text-align:center;width:100%}.el-table__empty-text{color:#909399;line-height:60px;width:50%}.el-table__expand-column .cell{padding:0;text-align:center}.el-table__expand-icon{color:#666;cursor:pointer;font-size:12px;height:20px;position:relative;transition:transform .2s ease-in-out}.el-table__expand-icon--expanded{transform:rotate(90deg)}.el-table__expand-icon>.el-icon{left:50%;margin-left:-5px;margin-top:-5px;position:absolute;top:50%}.el-table__expanded-cell{background-color:#fff}.el-table__expanded-cell[class*=cell]{padding:20px 50px}.el-table__expanded-cell:hover{background-color:transparent!important}.el-table__placeholder{display:inline-block;width:20px}.el-table__append-wrapper{overflow:hidden}.el-table--fit{border-bottom:0;border-right:0}.el-table--fit .el-table__cell.gutter{border-right-width:1px}.el-table--scrollable-x .el-table__body-wrapper{overflow-x:auto}.el-table--scrollable-y .el-table__body-wrapper{overflow-y:auto}.el-table thead{color:#909399;font-weight:500}.el-table thead.is-group th.el-table__cell{background:#f5f7fa}.el-table .el-table__cell{box-sizing:border-box;min-width:0;padding:12px 0;position:relative;text-align:left;text-overflow:ellipsis;vertical-align:middle}.el-table .el-table__cell.is-center{text-align:center}.el-table .el-table__cell.is-right{text-align:right}.el-table .el-table__cell.gutter{border-bottom-width:0;border-right-width:0;padding:0;width:15px}.el-table .el-table__cell.is-hidden>*{visibility:hidden}.el-table--medium .el-table__cell{padding:10px 0}.el-table--small{font-size:12px}.el-table--small .el-table__cell{padding:8px 0}.el-table--mini{font-size:12px}.el-table--mini .el-table__cell{padding:6px 0}.el-table tr{background-color:#fff}.el-table tr input[type=checkbox]{margin:0}.el-table td.el-table__cell,.el-table th.el-table__cell.is-leaf{border-bottom:1px solid #ececec}.el-table th.el-table__cell.is-sortable{cursor:pointer}.el-table th.el-table__cell{background-color:#fff;overflow:hidden;-webkit-user-select:none;-moz-user-select:none;user-select:none}.el-table th.el-table__cell>.cell{box-sizing:border-box;display:inline-block;padding-left:10px;padding-right:10px;position:relative;vertical-align:middle;width:100%}.el-table th.el-table__cell>.cell.highlight{color:#1a7efb}.el-table th.el-table__cell.required>div:before{background:#ff4d51;border-radius:50%;content:"";display:inline-block;height:8px;margin-right:5px;vertical-align:middle;width:8px}.el-table td.el-table__cell div{box-sizing:border-box}.el-table td.el-table__cell.gutter{width:0}.el-table .cell{box-sizing:border-box;line-height:23px;overflow:hidden;padding-left:10px;padding-right:10px;text-overflow:ellipsis;white-space:normal;word-break:break-all}.el-table .cell.el-tooltip{min-width:50px;white-space:nowrap}.el-table--border,.el-table--group{border:1px solid #ececec}.el-table--border:after,.el-table--group:after,.el-table:before{background-color:#ececec;content:"";position:absolute;z-index:1}.el-table--border:after,.el-table--group:after{height:100%;right:0;top:0;width:1px}.el-table:before{bottom:0;height:1px;left:0;width:100%}.el-table--border{border-bottom:none;border-right:none}.el-table--border.el-loading-parent--relative{border-color:transparent}.el-table--border .el-table__cell{border-right:1px solid #ececec}.el-table--border .el-table__cell:first-child .cell{padding-left:10px}.el-table--border th.el-table__cell,.el-table--border th.el-table__cell.gutter:last-of-type{border-bottom:1px solid #ececec}.el-table--hidden{visibility:hidden}.el-table__fixed,.el-table__fixed-right{box-shadow:0 0 10px rgba(0,0,0,.12);left:0;overflow-x:hidden;overflow-y:hidden;position:absolute;top:0}.el-table__fixed-right:before,.el-table__fixed:before{background-color:#ebeef5;bottom:0;content:"";height:1px;left:0;position:absolute;width:100%;z-index:4}.el-table__fixed-right-patch{background-color:#fff;border-bottom:1px solid #ececec;position:absolute;right:0;top:-1px}.el-table__fixed-right{left:auto;right:0;top:0}.el-table__fixed-right .el-table__fixed-body-wrapper,.el-table__fixed-right .el-table__fixed-footer-wrapper,.el-table__fixed-right .el-table__fixed-header-wrapper{left:auto;right:0}.el-table__fixed-header-wrapper{left:0;position:absolute;top:0;z-index:3}.el-table__fixed-footer-wrapper{bottom:0;left:0;position:absolute;z-index:3}.el-table__fixed-footer-wrapper tbody td.el-table__cell{background-color:#f5f7fa;border-top:1px solid #ececec;color:#606266}.el-table__fixed-body-wrapper{left:0;overflow:hidden;position:absolute;top:37px;z-index:3}.el-table__body-wrapper,.el-table__footer-wrapper,.el-table__header-wrapper{width:100%}.el-table__footer-wrapper{margin-top:-1px}.el-table__footer-wrapper td.el-table__cell{border-top:1px solid #ececec}.el-table__body,.el-table__footer,.el-table__header{border-collapse:separate;table-layout:fixed}.el-table__footer-wrapper,.el-table__header-wrapper{overflow:hidden}.el-table__footer-wrapper tbody td.el-table__cell,.el-table__header-wrapper tbody td.el-table__cell{background-color:#f5f7fa;color:#606266}.el-table__body-wrapper{overflow:hidden;position:relative}.el-table__body-wrapper.is-scrolling-left~.el-table__fixed,.el-table__body-wrapper.is-scrolling-none~.el-table__fixed,.el-table__body-wrapper.is-scrolling-none~.el-table__fixed-right,.el-table__body-wrapper.is-scrolling-right~.el-table__fixed-right{box-shadow:none}.el-table__body-wrapper .el-table--border.is-scrolling-right~.el-table__fixed-right{border-left:1px solid #ececec}.el-table__body-wrapper .el-table--border.is-scrolling-left~.el-table__fixed{border-right:1px solid #ececec}.el-table .caret-wrapper{align-items:center;cursor:pointer;display:inline-flex;flex-direction:column;height:34px;overflow:initial;position:relative;vertical-align:middle;width:24px}.el-table .sort-caret{border:5px solid transparent;height:0;left:7px;position:absolute;width:0}.el-table .sort-caret.ascending{border-bottom-color:#afb3ba;top:5px}.el-table .sort-caret.descending{border-top-color:#afb3ba;bottom:7px}.el-table .ascending .sort-caret.ascending{border-bottom-color:#1a7efb}.el-table .descending .sort-caret.descending{border-top-color:#1a7efb}.el-table .hidden-columns{position:absolute;visibility:hidden;z-index:-1}.el-table--striped .el-table__body tr.el-table__row--striped td.el-table__cell{background:#fafafa}.el-table--striped .el-table__body tr.el-table__row--striped.current-row td.el-table__cell{background-color:#e8f2ff}.el-table__body tr.hover-row.current-row>td.el-table__cell,.el-table__body tr.hover-row.el-table__row--striped.current-row>td.el-table__cell,.el-table__body tr.hover-row.el-table__row--striped>td.el-table__cell,.el-table__body tr.hover-row>td.el-table__cell{background-color:#f5f7fa}.el-table__body tr.current-row>td.el-table__cell{background-color:#e8f2ff}.el-table__column-resize-proxy{border-left:1px solid #ececec;bottom:0;left:200px;position:absolute;top:0;width:0;z-index:10}.el-table__column-filter-trigger{cursor:pointer;display:inline-block;line-height:34px}.el-table__column-filter-trigger i{color:#4b4c4d;font-size:12px;transform:scale(.75)}.el-table--enable-row-transition .el-table__body td.el-table__cell{transition:background-color .25s ease}.el-table--enable-row-hover .el-table__body tr:hover>td.el-table__cell{background-color:#f5f7fa}.el-table--fluid-height .el-table__fixed,.el-table--fluid-height .el-table__fixed-right{bottom:0;overflow:hidden}.el-table [class*=el-table__row--level] .el-table__expand-icon{display:inline-block;height:20px;line-height:20px;margin-right:3px;text-align:center;width:20px}.el-table-column--selection .cell{padding-left:14px;padding-right:14px}.el-table-filter{background-color:#fff;border:1px solid #ebeef5;border-radius:2px;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-sizing:border-box;margin:2px 0}.el-table-filter__list{list-style:none;margin:0;min-width:100px;padding:5px 0}.el-table-filter__list-item{cursor:pointer;font-size:14px;line-height:36px;padding:0 10px}.el-table-filter__list-item:hover{background-color:#e8f2ff;color:#4898fc}.el-table-filter__list-item.is-active{background-color:#1a7efb;color:#fff}.el-table-filter__content{min-width:100px}.el-table-filter__bottom{border-top:1px solid #ebeef5;padding:8px}.el-table-filter__bottom button{background:transparent;border:none;color:#606266;cursor:pointer;font-size:13px;padding:0 3px}.el-table-filter__bottom button:hover{color:#1a7efb}.el-table-filter__bottom button:focus{outline:none}.el-table-filter__bottom button.is-disabled{color:#afb3ba;cursor:not-allowed}.el-table-filter__wrap{max-height:280px}.el-table-filter__checkbox-group{padding:10px}.el-table-filter__checkbox-group label.el-checkbox{display:block;margin-bottom:8px;margin-left:5px;margin-right:5px}.el-table-filter__checkbox-group .el-checkbox:last-child{margin-bottom:0}.el-date-table{font-size:12px;-webkit-user-select:none;-moz-user-select:none;user-select:none}.el-date-table.is-week-mode .el-date-table__row:hover div{background-color:#f2f6fc}.el-date-table.is-week-mode .el-date-table__row:hover td.available:hover{color:#606266}.el-date-table.is-week-mode .el-date-table__row:hover td:first-child div{border-bottom-left-radius:15px;border-top-left-radius:15px;margin-left:5px}.el-date-table.is-week-mode .el-date-table__row:hover td:last-child div{border-bottom-right-radius:15px;border-top-right-radius:15px;margin-right:5px}.el-date-table.is-week-mode .el-date-table__row.current div{background-color:#f2f6fc}.el-date-table td{box-sizing:border-box;cursor:pointer;height:30px;padding:4px 0;position:relative;text-align:center;width:32px}.el-date-table td div{box-sizing:border-box;height:30px;padding:3px 0}.el-date-table td span{border-radius:50%;display:block;height:24px;left:50%;line-height:24px;margin:0 auto;position:absolute;transform:translateX(-50%);width:24px}.el-date-table td.next-month,.el-date-table td.prev-month{color:#afb3ba}.el-date-table td.today{position:relative}.el-date-table td.today span{color:#1a7efb;font-weight:700}.el-date-table td.today.end-date span,.el-date-table td.today.start-date span{color:#fff}.el-date-table td.available:hover{color:#1a7efb}.el-date-table td.in-range div,.el-date-table td.in-range div:hover{background-color:#f2f6fc}.el-date-table td.current:not(.disabled) span{background-color:#1a7efb;color:#fff}.el-date-table td.end-date div,.el-date-table td.start-date div{color:#fff}.el-date-table td.end-date span,.el-date-table td.start-date span{background-color:#1a7efb}.el-date-table td.start-date div{border-bottom-left-radius:15px;border-top-left-radius:15px;margin-left:5px}.el-date-table td.end-date div{border-bottom-right-radius:15px;border-top-right-radius:15px;margin-right:5px}.el-date-table td.disabled div{background-color:#f5f7fa;color:#afb3ba;cursor:not-allowed;opacity:1}.el-date-table td.selected div{background-color:#f2f6fc;border-radius:15px;margin-left:5px;margin-right:5px}.el-date-table td.selected div:hover{background-color:#f2f6fc}.el-date-table td.selected span{background-color:#1a7efb;border-radius:15px;color:#fff}.el-date-table td.week{color:#606266;font-size:80%}.el-date-table th{border-bottom:1px solid #ebeef5;color:#606266;font-weight:400;padding:5px}.el-month-table{border-collapse:collapse;font-size:12px;margin:-1px}.el-month-table td{cursor:pointer;padding:8px 0;text-align:center}.el-month-table td div{box-sizing:border-box;height:48px;padding:6px 0}.el-month-table td.today .cell{color:#1a7efb;font-weight:700}.el-month-table td.today.end-date .cell,.el-month-table td.today.start-date .cell{color:#fff}.el-month-table td.disabled .cell{background-color:#f5f7fa;color:#afb3ba;cursor:not-allowed}.el-month-table td.disabled .cell:hover{color:#afb3ba}.el-month-table td .cell{border-radius:18px;color:#606266;display:block;height:36px;line-height:36px;margin:0 auto;width:60px}.el-month-table td .cell:hover{color:#1a7efb}.el-month-table td.in-range div,.el-month-table td.in-range div:hover{background-color:#f2f6fc}.el-month-table td.end-date div,.el-month-table td.start-date div{color:#fff}.el-month-table td.end-date .cell,.el-month-table td.start-date .cell{background-color:#1a7efb;color:#fff}.el-month-table td.start-date div{border-bottom-left-radius:24px;border-top-left-radius:24px}.el-month-table td.end-date div{border-bottom-right-radius:24px;border-top-right-radius:24px}.el-month-table td.current:not(.disabled) .cell{color:#1a7efb}.el-year-table{border-collapse:collapse;font-size:12px;margin:-1px}.el-year-table .el-icon{color:#303133}.el-year-table td{cursor:pointer;padding:20px 3px;text-align:center}.el-year-table td.today .cell{color:#1a7efb;font-weight:700}.el-year-table td.disabled .cell{background-color:#f5f7fa;color:#afb3ba;cursor:not-allowed}.el-year-table td.disabled .cell:hover{color:#afb3ba}.el-year-table td .cell{color:#606266;display:block;height:32px;line-height:32px;margin:0 auto;width:48px}.el-year-table td .cell:hover,.el-year-table td.current:not(.disabled) .cell{color:#1a7efb}.el-date-range-picker{width:646px}.el-date-range-picker.has-sidebar{width:756px}.el-date-range-picker table{table-layout:fixed;width:100%}.el-date-range-picker .el-picker-panel__body{min-width:513px}.el-date-range-picker .el-picker-panel__content{margin:0}.el-date-range-picker__header{height:28px;position:relative;text-align:center}.el-date-range-picker__header [class*=arrow-left]{float:left}.el-date-range-picker__header [class*=arrow-right]{float:right}.el-date-range-picker__header div{font-size:16px;font-weight:500;margin-right:50px}.el-date-range-picker__content{box-sizing:border-box;float:left;margin:0;padding:16px;width:50%}.el-date-range-picker__content.is-left{border-right:1px solid #e4e4e4}.el-date-range-picker__content .el-date-range-picker__header div{margin-left:50px;margin-right:50px}.el-date-range-picker__editors-wrap{box-sizing:border-box;display:table-cell}.el-date-range-picker__editors-wrap.is-right{text-align:right}.el-date-range-picker__time-header{border-bottom:1px solid #e4e4e4;box-sizing:border-box;display:table;font-size:12px;padding:8px 5px 5px;position:relative;width:100%}.el-date-range-picker__time-header>.el-icon-arrow-right{color:#303133;display:table-cell;font-size:20px;vertical-align:middle}.el-date-range-picker__time-picker-wrap{display:table-cell;padding:0 5px;position:relative}.el-date-range-picker__time-picker-wrap .el-picker-panel{background:#fff;position:absolute;right:0;top:13px;z-index:1}.el-date-picker{width:322px}.el-date-picker.has-sidebar.has-time{width:434px}.el-date-picker.has-sidebar{width:438px}.el-date-picker.has-time .el-picker-panel__body-wrapper{position:relative}.el-date-picker .el-picker-panel__content{width:292px}.el-date-picker table{table-layout:fixed;width:100%}.el-date-picker__editor-wrap{display:table-cell;padding:0 5px;position:relative}.el-date-picker__time-header{border-bottom:1px solid #e4e4e4;box-sizing:border-box;display:table;font-size:12px;padding:8px 5px 5px;position:relative;width:100%}.el-date-picker__header{margin:12px;text-align:center}.el-date-picker__header--bordered{border-bottom:1px solid #ebeef5;margin-bottom:0;padding-bottom:12px}.el-date-picker__header--bordered+.el-picker-panel__content{margin-top:0}.el-date-picker__header-label{color:#606266;cursor:pointer;font-size:16px;font-weight:500;line-height:22px;padding:0 5px;text-align:center}.el-date-picker__header-label.active,.el-date-picker__header-label:hover{color:#1a7efb}.el-date-picker__prev-btn{float:left}.el-date-picker__next-btn{float:right}.el-date-picker__time-wrap{padding:10px;text-align:center}.el-date-picker__time-label{cursor:pointer;float:left;line-height:30px;margin-left:10px}.time-select{margin:5px 0;min-width:0}.time-select .el-picker-panel__content{margin:0;max-height:200px}.time-select-item{font-size:14px;line-height:20px;padding:8px 10px}.time-select-item.selected:not(.disabled){color:#1a7efb;font-weight:700}.time-select-item.disabled{color:#e4e7ed;cursor:not-allowed}.time-select-item:hover{background-color:#f5f7fa;cursor:pointer;font-weight:700}.el-date-editor{display:inline-block;position:relative;text-align:left}.el-date-editor.el-input,.el-date-editor.el-input__inner{width:220px}.el-date-editor--monthrange.el-input,.el-date-editor--monthrange.el-input__inner{width:300px}.el-date-editor--daterange.el-input,.el-date-editor--daterange.el-input__inner,.el-date-editor--timerange.el-input,.el-date-editor--timerange.el-input__inner{width:350px}.el-date-editor--datetimerange.el-input,.el-date-editor--datetimerange.el-input__inner{width:400px}.el-date-editor--dates .el-input__inner{text-overflow:ellipsis;white-space:nowrap}.el-date-editor .el-icon-circle-close{cursor:pointer}.el-date-editor .el-range__icon{color:#afb3ba;float:left;font-size:14px;line-height:32px;margin-left:-5px}.el-date-editor .el-range-input{-webkit-appearance:none;-moz-appearance:none;appearance:none;border:none;color:#606266;display:inline-block;font-size:14px;height:100%;margin:0;outline:none;padding:0;text-align:center;width:39%}.el-date-editor .el-range-input::-moz-placeholder{color:#afb3ba}.el-date-editor .el-range-input::placeholder{color:#afb3ba}.el-date-editor .el-range-separator{color:#303133;display:inline-block;font-size:14px;height:100%;line-height:32px;margin:0;padding:0 5px;text-align:center;width:5%}.el-date-editor .el-range__close-icon{color:#afb3ba;display:inline-block;float:right;font-size:14px;line-height:32px;width:25px}.el-range-editor.el-input__inner{align-items:center;display:inline-flex;padding:3px 10px}.el-range-editor .el-range-input{line-height:1}.el-range-editor.is-active,.el-range-editor.is-active:hover{border-color:#1a7efb}.el-range-editor--medium.el-input__inner{height:36px}.el-range-editor--medium .el-range-separator{font-size:14px;line-height:28px}.el-range-editor--medium .el-range-input{font-size:14px}.el-range-editor--medium .el-range__close-icon,.el-range-editor--medium .el-range__icon{line-height:28px}.el-range-editor--small.el-input__inner{height:32px}.el-range-editor--small .el-range-separator{font-size:13px;line-height:24px}.el-range-editor--small .el-range-input{font-size:13px}.el-range-editor--small .el-range__close-icon,.el-range-editor--small .el-range__icon{line-height:24px}.el-range-editor--mini.el-input__inner{height:28px}.el-range-editor--mini .el-range-separator{font-size:12px;line-height:20px}.el-range-editor--mini .el-range-input{font-size:12px}.el-range-editor--mini .el-range__close-icon,.el-range-editor--mini .el-range__icon{line-height:20px}.el-range-editor.is-disabled{background-color:#f5f7fa;border-color:#e4e7ed;color:#afb3ba;cursor:not-allowed}.el-range-editor.is-disabled:focus,.el-range-editor.is-disabled:hover{border-color:#e4e7ed}.el-range-editor.is-disabled input{background-color:#f5f7fa;color:#afb3ba;cursor:not-allowed}.el-range-editor.is-disabled input::-moz-placeholder{color:#afb3ba}.el-range-editor.is-disabled input::placeholder{color:#afb3ba}.el-range-editor.is-disabled .el-range-separator{color:#afb3ba}.el-picker-panel{background:#fff;border:1px solid #e4e7ed;border-radius:7px;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);color:#606266;line-height:30px;margin:5px 0}.el-picker-panel__body-wrapper:after,.el-picker-panel__body:after{clear:both;content:"";display:table}.el-picker-panel__content{margin:15px;position:relative}.el-picker-panel__footer{background-color:#fff;border-top:1px solid #e4e4e4;font-size:0;padding:4px;position:relative;text-align:right}.el-picker-panel__shortcut{background-color:transparent;border:0;color:#606266;cursor:pointer;display:block;font-size:14px;line-height:28px;outline:none;padding-left:12px;text-align:left;width:100%}.el-picker-panel__shortcut:hover{color:#1a7efb}.el-picker-panel__shortcut.active{background-color:#e6f1fe;color:#1a7efb}.el-picker-panel__btn{background-color:transparent;border:1px solid #dcdcdc;border-radius:2px;color:#333;cursor:pointer;font-size:12px;line-height:24px;outline:none;padding:0 20px}.el-picker-panel__btn[disabled]{color:#ccc;cursor:not-allowed}.el-picker-panel__icon-btn{background:transparent;border:0;color:#303133;cursor:pointer;font-size:12px;margin-top:8px;outline:none}.el-picker-panel__icon-btn:hover{color:#1a7efb}.el-picker-panel__icon-btn.is-disabled{color:#bbb}.el-picker-panel__icon-btn.is-disabled:hover{cursor:not-allowed}.el-picker-panel__link-btn{vertical-align:middle}.el-picker-panel [slot=sidebar],.el-picker-panel__sidebar{background-color:#fff;border-right:1px solid #e4e4e4;bottom:0;box-sizing:border-box;overflow:auto;padding-top:6px;position:absolute;top:0;width:110px}.el-picker-panel [slot=sidebar]+.el-picker-panel__body,.el-picker-panel__sidebar+.el-picker-panel__body{margin-left:110px}.el-time-spinner.has-seconds .el-time-spinner__wrapper{width:33.3%}.el-time-spinner__wrapper{display:inline-block;max-height:190px;overflow:auto;position:relative;vertical-align:top;width:50%}.el-time-spinner__wrapper .el-scrollbar__wrap:not(.el-scrollbar__wrap--hidden-default){padding-bottom:15px}.el-time-spinner__wrapper.is-arrow{box-sizing:border-box;overflow:hidden;text-align:center}.el-time-spinner__wrapper.is-arrow .el-time-spinner__list{transform:translateY(-32px)}.el-time-spinner__wrapper.is-arrow .el-time-spinner__item:hover:not(.disabled):not(.active){background:#fff;cursor:default}.el-time-spinner__arrow{color:#909399;cursor:pointer;font-size:12px;height:30px;left:0;line-height:30px;position:absolute;text-align:center;width:100%;z-index:1}.el-time-spinner__arrow:hover{color:#1a7efb}.el-time-spinner__arrow.el-icon-arrow-up{top:10px}.el-time-spinner__arrow.el-icon-arrow-down{bottom:10px}.el-time-spinner__input.el-input{width:70%}.el-time-spinner__input.el-input .el-input__inner,.el-time-spinner__list{padding:0;text-align:center}.el-time-spinner__list{list-style:none;margin:0}.el-time-spinner__list:after,.el-time-spinner__list:before{content:"";display:block;height:80px;width:100%}.el-time-spinner__item{color:#606266;font-size:12px;height:32px;line-height:32px}.el-time-spinner__item:hover:not(.disabled):not(.active){background:#f5f7fa;cursor:pointer}.el-time-spinner__item.active:not(.disabled){color:#303133;font-weight:700}.el-time-spinner__item.disabled{color:#afb3ba;cursor:not-allowed}.el-time-panel{background-color:#fff;border:1px solid #e4e7ed;border-radius:2px;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-sizing:content-box;left:0;margin:5px 0;position:absolute;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:180px;z-index:1000}.el-time-panel__content{font-size:0;overflow:hidden;position:relative}.el-time-panel__content:after,.el-time-panel__content:before{border-bottom:1px solid #e4e7ed;border-top:1px solid #e4e7ed;box-sizing:border-box;content:"";height:32px;left:0;margin-top:-15px;padding-top:6px;position:absolute;right:0;text-align:left;top:50%;z-index:-1}.el-time-panel__content:after{left:50%;margin-left:12%;margin-right:12%}.el-time-panel__content:before{margin-left:12%;margin-right:12%;padding-left:50%}.el-time-panel__content.has-seconds:after{left:66.6666666667%}.el-time-panel__content.has-seconds:before{padding-left:33.3333333333%}.el-time-panel__footer{border-top:1px solid #e4e4e4;box-sizing:border-box;height:36px;line-height:25px;padding:4px;text-align:right}.el-time-panel__btn{background-color:transparent;border:none;color:#303133;cursor:pointer;font-size:12px;line-height:28px;margin:0 5px;outline:none;padding:0 5px}.el-time-panel__btn.confirm{color:#1a7efb;font-weight:800}.el-time-range-picker{overflow:visible;width:354px}.el-time-range-picker__content{padding:10px;position:relative;text-align:center}.el-time-range-picker__cell{box-sizing:border-box;display:inline-block;margin:0;padding:4px 7px 7px;width:50%}.el-time-range-picker__header{font-size:14px;margin-bottom:5px;text-align:center}.el-time-range-picker__body{border:1px solid #e4e7ed;border-radius:2px}.el-popover{background:#fff;border:1px solid #ebeef5;border-radius:4px;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);color:#606266;font-size:14px;line-height:1.4;min-width:150px;padding:12px;position:absolute;text-align:justify;word-break:break-all;z-index:2000}.el-popover--plain{padding:18px 20px}.el-popover__title{color:#303133;font-size:16px;line-height:1;margin-bottom:12px}.el-popover:focus,.el-popover:focus:active,.el-popover__reference:focus:hover,.el-popover__reference:focus:not(.focusing){outline-width:0}.v-modal-enter{animation:v-modal-in .2s ease}.v-modal-leave{animation:v-modal-out .2s ease forwards}@keyframes v-modal-in{0%{opacity:0}}@keyframes v-modal-out{to{opacity:0}}.v-modal{background:#000;height:100%;left:0;opacity:.5;position:fixed;top:0;width:100%}.el-popup-parent--hidden{overflow:hidden}.el-message-box{backface-visibility:hidden;background-color:#fff;border:1px solid #ebeef5;border-radius:4px;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);display:inline-block;font-size:18px;overflow:hidden;padding-bottom:10px;text-align:left;vertical-align:middle;width:420px}.el-message-box__wrapper{bottom:0;left:0;position:fixed;right:0;text-align:center;top:0}.el-message-box__wrapper:after{content:"";display:inline-block;height:100%;vertical-align:middle;width:0}.el-message-box__header{padding:15px 15px 10px;position:relative}.el-message-box__title{color:#303133;font-size:18px;line-height:1;margin-bottom:0;padding-left:0}.el-message-box__headerbtn{background:transparent;border:none;cursor:pointer;font-size:16px;outline:none;padding:0;position:absolute;right:15px;top:15px}.el-message-box__headerbtn .el-message-box__close{color:#4b4c4d}.el-message-box__headerbtn:focus .el-message-box__close,.el-message-box__headerbtn:hover .el-message-box__close{color:#1a7efb}.el-message-box__content{color:#606266;font-size:14px;padding:10px 15px}.el-message-box__container{position:relative}.el-message-box__input{padding-top:15px}.el-message-box__input input.invalid,.el-message-box__input input.invalid:focus{border-color:#ff6154}.el-message-box__status{font-size:24px!important;position:absolute;top:50%;transform:translateY(-50%)}.el-message-box__status:before{padding-left:1px}.el-message-box__status+.el-message-box__message{padding-left:36px;padding-right:12px}.el-message-box__status.el-icon-success{color:#00b27f}.el-message-box__status.el-icon-info{color:#4b4c4d}.el-message-box__status.el-icon-warning{color:#fcbe2d}.el-message-box__status.el-icon-error{color:#ff6154}.el-message-box__message{margin:0}.el-message-box__message p{line-height:24px;margin:0}.el-message-box__errormsg{color:#ff6154;font-size:12px;margin-top:2px;min-height:18px}.el-message-box__btns{padding:5px 15px 0;text-align:right}.el-message-box__btns button:nth-child(2){margin-left:10px}.el-message-box__btns-reverse{flex-direction:row-reverse}.el-message-box--center{padding-bottom:30px}.el-message-box--center .el-message-box__header{padding-top:30px}.el-message-box--center .el-message-box__title{align-items:center;display:flex;justify-content:center;position:relative}.el-message-box--center .el-message-box__status{padding-right:5px;position:relative;text-align:center;top:auto;transform:translateY(-1px)}.el-message-box--center .el-message-box__message{margin-left:0}.el-message-box--center .el-message-box__btns,.el-message-box--center .el-message-box__content{text-align:center}.el-message-box--center .el-message-box__content{padding-left:27px;padding-right:27px}.msgbox-fade-enter-active{animation:msgbox-fade-in .3s}.msgbox-fade-leave-active{animation:msgbox-fade-out .3s}@keyframes msgbox-fade-in{0%{opacity:0;transform:translate3d(0,-20px,0)}to{opacity:1;transform:translateZ(0)}}@keyframes msgbox-fade-out{0%{opacity:1;transform:translateZ(0)}to{opacity:0;transform:translate3d(0,-20px,0)}}.el-breadcrumb{font-size:14px;line-height:1}.el-breadcrumb:after,.el-breadcrumb:before{content:"";display:table}.el-breadcrumb:after{clear:both}.el-breadcrumb__separator{color:#afb3ba;font-weight:700;margin:0 9px}.el-breadcrumb__separator[class*=icon]{font-weight:400;margin:0 6px}.el-breadcrumb__item{float:left}.el-breadcrumb__inner{color:#606266}.el-breadcrumb__inner a,.el-breadcrumb__inner.is-link{color:#303133;font-weight:700;text-decoration:none;transition:color .2s cubic-bezier(.645,.045,.355,1)}.el-breadcrumb__inner a:hover,.el-breadcrumb__inner.is-link:hover{color:#1a7efb;cursor:pointer}.el-breadcrumb__item:last-child .el-breadcrumb__inner,.el-breadcrumb__item:last-child .el-breadcrumb__inner a,.el-breadcrumb__item:last-child .el-breadcrumb__inner a:hover,.el-breadcrumb__item:last-child .el-breadcrumb__inner:hover{color:#606266;cursor:text;font-weight:400}.el-breadcrumb__item:last-child .el-breadcrumb__separator{display:none}.el-form--label-left .el-form-item__label{text-align:left}.el-form--label-top .el-form-item__label{display:inline-block;float:none;padding:0 0 10px;text-align:left}.el-form--inline .el-form-item{display:inline-block;margin-right:10px;vertical-align:top}.el-form--inline .el-form-item__label{display:inline-block;float:none}.el-form--inline .el-form-item__content{display:inline-block;vertical-align:top}.el-form--inline.el-form--label-top .el-form-item__content{display:block}.el-form-item{margin-bottom:22px}.el-form-item:after,.el-form-item:before{content:"";display:table}.el-form-item:after{clear:both}.el-form-item .el-form-item{margin-bottom:0}.el-form-item .el-input__validateIcon{display:none}.el-form-item--medium .el-form-item__content,.el-form-item--medium .el-form-item__label{line-height:36px}.el-form-item--small .el-form-item__content,.el-form-item--small .el-form-item__label{line-height:32px}.el-form-item--small.el-form-item{margin-bottom:18px}.el-form-item--small .el-form-item__error{padding-top:2px}.el-form-item--mini .el-form-item__content,.el-form-item--mini .el-form-item__label{line-height:28px}.el-form-item--mini.el-form-item{margin-bottom:18px}.el-form-item--mini .el-form-item__error{padding-top:1px}.el-form-item__label-wrap{float:left}.el-form-item__label-wrap .el-form-item__label{display:inline-block;float:none}.el-form-item__label{box-sizing:border-box;color:#606266;float:left;font-size:14px;line-height:40px;padding:0 12px 0 0;text-align:right;vertical-align:middle}.el-form-item__content{font-size:14px;line-height:40px;position:relative}.el-form-item__content:after,.el-form-item__content:before{content:"";display:table}.el-form-item__content:after{clear:both}.el-form-item__content .el-input-group{vertical-align:top}.el-form-item__error{color:#ff6154;font-size:12px;left:0;line-height:1;padding-top:4px;position:absolute;top:100%}.el-form-item__error--inline{display:inline-block;left:auto;margin-left:10px;position:relative;top:auto}.el-form-item.is-required:not(.is-no-asterisk) .el-form-item__label-wrap>.el-form-item__label:before,.el-form-item.is-required:not(.is-no-asterisk)>.el-form-item__label:before{color:#ff6154;content:"*";margin-right:4px}.el-form-item.is-error .el-input__inner,.el-form-item.is-error .el-input__inner:focus,.el-form-item.is-error .el-textarea__inner,.el-form-item.is-error .el-textarea__inner:focus{border-color:#ff6154}.el-form-item.is-error .el-input-group__append .el-input__inner,.el-form-item.is-error .el-input-group__prepend .el-input__inner{border-color:transparent}.el-form-item.is-error .el-input__validateIcon{color:#ff6154}.el-form-item--feedback .el-input__validateIcon{display:inline-block}.el-tabs__header{margin:0 0 15px;padding:0;position:relative}.el-tabs__active-bar{background-color:#1a7efb;bottom:0;height:2px;left:0;list-style:none;position:absolute;transition:transform .3s cubic-bezier(.645,.045,.355,1);z-index:1}.el-tabs__new-tab{border:1px solid #d3dce6;border-radius:3px;color:#d3dce6;cursor:pointer;float:right;font-size:12px;height:18px;line-height:18px;margin:12px 0 9px 10px;text-align:center;transition:all .15s;width:18px}.el-tabs__new-tab .el-icon-plus{transform:scale(.8)}.el-tabs__new-tab:hover{color:#1a7efb}.el-tabs__nav-wrap{margin-bottom:-1px;overflow:hidden;position:relative}.el-tabs__nav-wrap:after{background-color:#e4e7ed;bottom:0;content:"";height:2px;left:0;position:absolute;width:100%;z-index:1}.el-tabs__nav-wrap.is-scrollable{box-sizing:border-box;padding:0 20px}.el-tabs__nav-scroll{overflow:hidden}.el-tabs__nav-next,.el-tabs__nav-prev{color:#909399;cursor:pointer;font-size:12px;line-height:44px;position:absolute}.el-tabs__nav-next{right:0}.el-tabs__nav-prev{left:0}.el-tabs__nav{float:left;position:relative;transition:transform .3s;white-space:nowrap;z-index:2}.el-tabs__nav.is-stretch{display:flex;min-width:100%}.el-tabs__nav.is-stretch>*{flex:1;text-align:center}.el-tabs__item{box-sizing:border-box;color:#303133;display:inline-block;font-size:14px;font-weight:500;height:40px;line-height:40px;list-style:none;padding:0 20px;position:relative}.el-tabs__item:focus,.el-tabs__item:focus:active{outline:none}.el-tabs__item:focus.is-active.is-focus:not(:active){border-radius:3px;box-shadow:inset 0 0 2px 2px #1a7efb}.el-tabs__item .el-icon-close{border-radius:50%;margin-left:5px;text-align:center;transition:all .3s cubic-bezier(.645,.045,.355,1)}.el-tabs__item .el-icon-close:before{display:inline-block;transform:scale(.9)}.el-tabs__item .el-icon-close:hover{background-color:#afb3ba;color:#fff}.el-tabs__item.is-active{color:#1a7efb}.el-tabs__item:hover{color:#1a7efb;cursor:pointer}.el-tabs__item.is-disabled{color:#afb3ba;cursor:default}.el-tabs__content{overflow:hidden;position:relative}.el-tabs--card>.el-tabs__header{border-bottom:1px solid #e4e7ed}.el-tabs--card>.el-tabs__header .el-tabs__nav-wrap:after{content:none}.el-tabs--card>.el-tabs__header .el-tabs__nav{border:1px solid #e4e7ed;border-bottom:none;border-radius:4px 4px 0 0;box-sizing:border-box}.el-tabs--card>.el-tabs__header .el-tabs__active-bar{display:none}.el-tabs--card>.el-tabs__header .el-tabs__item .el-icon-close{font-size:12px;height:14px;line-height:15px;overflow:hidden;position:relative;right:-2px;top:-1px;transform-origin:100% 50%;vertical-align:middle;width:0}.el-tabs--card>.el-tabs__header .el-tabs__item{border-bottom:1px solid transparent;border-left:1px solid #e4e7ed;transition:color .3s cubic-bezier(.645,.045,.355,1),padding .3s cubic-bezier(.645,.045,.355,1)}.el-tabs--card>.el-tabs__header .el-tabs__item:first-child{border-left:none}.el-tabs--card>.el-tabs__header .el-tabs__item.is-closable:hover{padding-left:13px;padding-right:13px}.el-tabs--card>.el-tabs__header .el-tabs__item.is-closable:hover .el-icon-close{width:14px}.el-tabs--card>.el-tabs__header .el-tabs__item.is-active{border-bottom-color:#fff}.el-tabs--card>.el-tabs__header .el-tabs__item.is-active.is-closable{padding-left:20px;padding-right:20px}.el-tabs--card>.el-tabs__header .el-tabs__item.is-active.is-closable .el-icon-close{width:14px}.el-tabs--border-card{background:#fff;border:1px solid #dadbdd;box-shadow:0 2px 4px 0 rgba(0,0,0,.12),0 0 6px 0 rgba(0,0,0,.04)}.el-tabs--border-card>.el-tabs__content{padding:15px}.el-tabs--border-card>.el-tabs__header{background-color:#f5f7fa;border-bottom:1px solid #e4e7ed;margin:0}.el-tabs--border-card>.el-tabs__header .el-tabs__nav-wrap:after{content:none}.el-tabs--border-card>.el-tabs__header .el-tabs__item{border:1px solid transparent;color:#909399;margin-top:-1px;transition:all .3s cubic-bezier(.645,.045,.355,1)}.el-tabs--border-card>.el-tabs__header .el-tabs__item+.el-tabs__item,.el-tabs--border-card>.el-tabs__header .el-tabs__item:first-child{margin-left:-1px}.el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active{background-color:#fff;border-left-color:#dadbdd;border-right-color:#dadbdd;color:#1a7efb}.el-tabs--border-card>.el-tabs__header .el-tabs__item:not(.is-disabled):hover{color:#1a7efb}.el-tabs--border-card>.el-tabs__header .el-tabs__item.is-disabled{color:#afb3ba}.el-tabs--border-card>.el-tabs__header .is-scrollable .el-tabs__item:first-child{margin-left:0}.el-tabs--bottom .el-tabs__item.is-bottom:nth-child(2),.el-tabs--bottom .el-tabs__item.is-top:nth-child(2),.el-tabs--top .el-tabs__item.is-bottom:nth-child(2),.el-tabs--top .el-tabs__item.is-top:nth-child(2){padding-left:0}.el-tabs--bottom .el-tabs__item.is-bottom:last-child,.el-tabs--bottom .el-tabs__item.is-top:last-child,.el-tabs--top .el-tabs__item.is-bottom:last-child,.el-tabs--top .el-tabs__item.is-top:last-child{padding-right:0}.el-tabs--bottom .el-tabs--left>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--bottom .el-tabs--right>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--bottom.el-tabs--border-card>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--bottom.el-tabs--card>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--top .el-tabs--left>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--top .el-tabs--right>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--top.el-tabs--border-card>.el-tabs__header .el-tabs__item:nth-child(2),.el-tabs--top.el-tabs--card>.el-tabs__header .el-tabs__item:nth-child(2){padding-left:20px}.el-tabs--bottom .el-tabs--left>.el-tabs__header .el-tabs__item:last-child,.el-tabs--bottom .el-tabs--right>.el-tabs__header .el-tabs__item:last-child,.el-tabs--bottom.el-tabs--border-card>.el-tabs__header .el-tabs__item:last-child,.el-tabs--bottom.el-tabs--card>.el-tabs__header .el-tabs__item:last-child,.el-tabs--top .el-tabs--left>.el-tabs__header .el-tabs__item:last-child,.el-tabs--top .el-tabs--right>.el-tabs__header .el-tabs__item:last-child,.el-tabs--top.el-tabs--border-card>.el-tabs__header .el-tabs__item:last-child,.el-tabs--top.el-tabs--card>.el-tabs__header .el-tabs__item:last-child{padding-right:20px}.el-tabs--bottom .el-tabs__header.is-bottom{margin-bottom:0;margin-top:10px}.el-tabs--bottom.el-tabs--border-card .el-tabs__header.is-bottom{border-bottom:0;border-top:1px solid #dadbdd}.el-tabs--bottom.el-tabs--border-card .el-tabs__nav-wrap.is-bottom{margin-bottom:0;margin-top:-1px}.el-tabs--bottom.el-tabs--border-card .el-tabs__item.is-bottom:not(.is-active){border:1px solid transparent}.el-tabs--bottom.el-tabs--border-card .el-tabs__item.is-bottom{margin:0 -1px -1px}.el-tabs--left,.el-tabs--right{overflow:hidden}.el-tabs--left .el-tabs__header.is-left,.el-tabs--left .el-tabs__header.is-right,.el-tabs--left .el-tabs__nav-scroll,.el-tabs--left .el-tabs__nav-wrap.is-left,.el-tabs--left .el-tabs__nav-wrap.is-right,.el-tabs--right .el-tabs__header.is-left,.el-tabs--right .el-tabs__header.is-right,.el-tabs--right .el-tabs__nav-scroll,.el-tabs--right .el-tabs__nav-wrap.is-left,.el-tabs--right .el-tabs__nav-wrap.is-right{height:100%}.el-tabs--left .el-tabs__active-bar.is-left,.el-tabs--left .el-tabs__active-bar.is-right,.el-tabs--right .el-tabs__active-bar.is-left,.el-tabs--right .el-tabs__active-bar.is-right{bottom:auto;height:auto;top:0;width:2px}.el-tabs--left .el-tabs__nav-wrap.is-left,.el-tabs--left .el-tabs__nav-wrap.is-right,.el-tabs--right .el-tabs__nav-wrap.is-left,.el-tabs--right .el-tabs__nav-wrap.is-right{margin-bottom:0}.el-tabs--left .el-tabs__nav-wrap.is-left>.el-tabs__nav-next,.el-tabs--left .el-tabs__nav-wrap.is-left>.el-tabs__nav-prev,.el-tabs--left .el-tabs__nav-wrap.is-right>.el-tabs__nav-next,.el-tabs--left .el-tabs__nav-wrap.is-right>.el-tabs__nav-prev,.el-tabs--right .el-tabs__nav-wrap.is-left>.el-tabs__nav-next,.el-tabs--right .el-tabs__nav-wrap.is-left>.el-tabs__nav-prev,.el-tabs--right .el-tabs__nav-wrap.is-right>.el-tabs__nav-next,.el-tabs--right .el-tabs__nav-wrap.is-right>.el-tabs__nav-prev{cursor:pointer;height:30px;line-height:30px;text-align:center;width:100%}.el-tabs--left .el-tabs__nav-wrap.is-left>.el-tabs__nav-next i,.el-tabs--left .el-tabs__nav-wrap.is-left>.el-tabs__nav-prev i,.el-tabs--left .el-tabs__nav-wrap.is-right>.el-tabs__nav-next i,.el-tabs--left .el-tabs__nav-wrap.is-right>.el-tabs__nav-prev i,.el-tabs--right .el-tabs__nav-wrap.is-left>.el-tabs__nav-next i,.el-tabs--right .el-tabs__nav-wrap.is-left>.el-tabs__nav-prev i,.el-tabs--right .el-tabs__nav-wrap.is-right>.el-tabs__nav-next i,.el-tabs--right .el-tabs__nav-wrap.is-right>.el-tabs__nav-prev i{transform:rotate(90deg)}.el-tabs--left .el-tabs__nav-wrap.is-left>.el-tabs__nav-prev,.el-tabs--left .el-tabs__nav-wrap.is-right>.el-tabs__nav-prev,.el-tabs--right .el-tabs__nav-wrap.is-left>.el-tabs__nav-prev,.el-tabs--right .el-tabs__nav-wrap.is-right>.el-tabs__nav-prev{left:auto;top:0}.el-tabs--left .el-tabs__nav-wrap.is-left>.el-tabs__nav-next,.el-tabs--left .el-tabs__nav-wrap.is-right>.el-tabs__nav-next,.el-tabs--right .el-tabs__nav-wrap.is-left>.el-tabs__nav-next,.el-tabs--right .el-tabs__nav-wrap.is-right>.el-tabs__nav-next{bottom:0;right:auto}.el-tabs--left .el-tabs__nav-wrap.is-left.is-scrollable,.el-tabs--left .el-tabs__nav-wrap.is-right.is-scrollable,.el-tabs--right .el-tabs__nav-wrap.is-left.is-scrollable,.el-tabs--right .el-tabs__nav-wrap.is-right.is-scrollable{padding:30px 0}.el-tabs--left .el-tabs__nav-wrap.is-left:after,.el-tabs--left .el-tabs__nav-wrap.is-right:after,.el-tabs--right .el-tabs__nav-wrap.is-left:after,.el-tabs--right .el-tabs__nav-wrap.is-right:after{bottom:auto;height:100%;top:0;width:2px}.el-tabs--left .el-tabs__nav.is-left,.el-tabs--left .el-tabs__nav.is-right,.el-tabs--right .el-tabs__nav.is-left,.el-tabs--right .el-tabs__nav.is-right{float:none}.el-tabs--left .el-tabs__item.is-left,.el-tabs--left .el-tabs__item.is-right,.el-tabs--right .el-tabs__item.is-left,.el-tabs--right .el-tabs__item.is-right{display:block}.el-tabs--left .el-tabs__header.is-left{float:left;margin-bottom:0;margin-right:10px}.el-tabs--left .el-tabs__nav-wrap.is-left{margin-right:-1px}.el-tabs--left .el-tabs__active-bar.is-left,.el-tabs--left .el-tabs__nav-wrap.is-left:after{left:auto;right:0}.el-tabs--left .el-tabs__item.is-left{text-align:right}.el-tabs--left.el-tabs--card .el-tabs__active-bar.is-left{display:none}.el-tabs--left.el-tabs--card .el-tabs__item.is-left{border:1px solid #e4e7ed;border-bottom:none;border-left:none;text-align:left}.el-tabs--left.el-tabs--card .el-tabs__item.is-left:first-child{border-right:1px solid #e4e7ed;border-top:none}.el-tabs--left.el-tabs--card .el-tabs__item.is-left.is-active{border:none;border-right:1px solid #fff;border-top:1px solid #e4e7ed}.el-tabs--left.el-tabs--card .el-tabs__item.is-left.is-active:first-child{border-top:none}.el-tabs--left.el-tabs--card .el-tabs__item.is-left.is-active:last-child{border-bottom:none}.el-tabs--left.el-tabs--card .el-tabs__nav{border-bottom:1px solid #e4e7ed;border-radius:4px 0 0 4px;border-right:none}.el-tabs--left.el-tabs--card .el-tabs__new-tab{float:none}.el-tabs--left.el-tabs--border-card .el-tabs__header.is-left{border-right:1px solid #dfe4ed}.el-tabs--left.el-tabs--border-card .el-tabs__item.is-left{border:1px solid transparent;margin:-1px 0 -1px -1px}.el-tabs--left.el-tabs--border-card .el-tabs__item.is-left.is-active{border-color:#d1dbe5 transparent}.el-tabs--right .el-tabs__header.is-right{float:right;margin-bottom:0;margin-left:10px}.el-tabs--right .el-tabs__nav-wrap.is-right{margin-left:-1px}.el-tabs--right .el-tabs__nav-wrap.is-right:after{left:0;right:auto}.el-tabs--right .el-tabs__active-bar.is-right{left:0}.el-tabs--right.el-tabs--card .el-tabs__active-bar.is-right{display:none}.el-tabs--right.el-tabs--card .el-tabs__item.is-right{border-bottom:none;border-top:1px solid #e4e7ed}.el-tabs--right.el-tabs--card .el-tabs__item.is-right:first-child{border-left:1px solid #e4e7ed;border-top:none}.el-tabs--right.el-tabs--card .el-tabs__item.is-right.is-active{border:none;border-left:1px solid #fff;border-top:1px solid #e4e7ed}.el-tabs--right.el-tabs--card .el-tabs__item.is-right.is-active:first-child{border-top:none}.el-tabs--right.el-tabs--card .el-tabs__item.is-right.is-active:last-child{border-bottom:none}.el-tabs--right.el-tabs--card .el-tabs__nav{border-bottom:1px solid #e4e7ed;border-left:none;border-radius:0 4px 4px 0}.el-tabs--right.el-tabs--border-card .el-tabs__header.is-right{border-left:1px solid #dfe4ed}.el-tabs--right.el-tabs--border-card .el-tabs__item.is-right{border:1px solid transparent;margin:-1px -1px -1px 0}.el-tabs--right.el-tabs--border-card .el-tabs__item.is-right.is-active{border-color:#d1dbe5 transparent}.slideInLeft-transition,.slideInRight-transition{display:inline-block}.slideInRight-enter{animation:slideInRight-enter .3s}.slideInRight-leave{animation:slideInRight-leave .3s;left:0;position:absolute;right:0}.slideInLeft-enter{animation:slideInLeft-enter .3s}.slideInLeft-leave{animation:slideInLeft-leave .3s;left:0;position:absolute;right:0}@keyframes slideInRight-enter{0%{opacity:0;transform:translateX(100%);transform-origin:0 0}to{opacity:1;transform:translateX(0);transform-origin:0 0}}@keyframes slideInRight-leave{0%{opacity:1;transform:translateX(0);transform-origin:0 0}to{opacity:0;transform:translateX(100%);transform-origin:0 0}}@keyframes slideInLeft-enter{0%{opacity:0;transform:translateX(-100%);transform-origin:0 0}to{opacity:1;transform:translateX(0);transform-origin:0 0}}@keyframes slideInLeft-leave{0%{opacity:1;transform:translateX(0);transform-origin:0 0}to{opacity:0;transform:translateX(-100%);transform-origin:0 0}}.el-tree{background:#fff;color:#606266;cursor:default;position:relative}.el-tree__empty-block{height:100%;min-height:60px;position:relative;text-align:center;width:100%}.el-tree__empty-text{color:#909399;font-size:14px;left:50%;position:absolute;top:50%;transform:translate(-50%,-50%)}.el-tree__drop-indicator{background-color:#1a7efb;height:1px;left:0;position:absolute;right:0}.el-tree-node{outline:none;white-space:nowrap}.el-tree-node:focus>.el-tree-node__content{background-color:#f5f7fa}.el-tree-node.is-drop-inner>.el-tree-node__content .el-tree-node__label{background-color:#1a7efb;color:#fff}.el-tree-node__content{align-items:center;cursor:pointer;display:flex;height:26px}.el-tree-node__content>.el-tree-node__expand-icon{padding:6px}.el-tree-node__content>label.el-checkbox{margin-right:8px}.el-tree-node__content:hover{background-color:#f5f7fa}.el-tree.is-dragging .el-tree-node__content{cursor:move}.el-tree.is-dragging .el-tree-node__content *{pointer-events:none}.el-tree.is-dragging.is-drop-not-allow .el-tree-node__content{cursor:not-allowed}.el-tree-node__expand-icon{color:#afb3ba;cursor:pointer;font-size:12px;transform:rotate(0deg);transition:transform .3s ease-in-out}.el-tree-node__expand-icon.expanded{transform:rotate(90deg)}.el-tree-node__expand-icon.is-leaf{color:transparent;cursor:default}.el-tree-node__label{font-size:14px}.el-tree-node__loading-icon{color:#afb3ba;font-size:14px;margin-right:8px}.el-tree-node>.el-tree-node__children{background-color:transparent;overflow:hidden}.el-tree-node.is-expanded>.el-tree-node__children{display:block}.el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content{background-color:#edf5ff}.el-alert{align-items:center;background-color:#fff;border-radius:7px;box-sizing:border-box;display:flex;margin:0;opacity:1;overflow:hidden;padding:8px 16px;position:relative;transition:opacity .2s;width:100%}.el-alert.is-light .el-alert__closebtn{color:#afb3ba}.el-alert.is-dark .el-alert__closebtn,.el-alert.is-dark .el-alert__description{color:#fff}.el-alert.is-center{justify-content:center}.el-alert--success.is-light{background-color:#e6ffeb;color:#00b27f}.el-alert--success.is-light .el-alert__description{color:#00b27f}.el-alert--success.is-dark{background-color:#00b27f;color:#fff}.el-alert--info.is-light{background-color:#ededed;color:#4b4c4d}.el-alert--info.is-dark{background-color:#4b4c4d;color:#fff}.el-alert--info .el-alert__description{color:#4b4c4d}.el-alert--warning.is-light{background-color:#fff9ea;color:#fcbe2d}.el-alert--warning.is-light .el-alert__description{color:#fcbe2d}.el-alert--warning.is-dark{background-color:#fcbe2d;color:#fff}.el-alert--error.is-light{background-color:#ffefee;color:#ff6154}.el-alert--error.is-light .el-alert__description{color:#ff6154}.el-alert--error.is-dark{background-color:#ff6154;color:#fff}.el-alert__content{display:table-cell;padding:0 8px}.el-alert__icon{font-size:16px;width:16px}.el-alert__icon.is-big{font-size:28px;width:28px}.el-alert__title{font-size:13px;line-height:18px}.el-alert__title.is-bold{font-weight:700}.el-alert .el-alert__description{font-size:12px;margin:5px 0 0}.el-alert__closebtn{cursor:pointer;font-size:12px;opacity:1;position:absolute;right:15px;top:12px}.el-alert__closebtn.is-customed{font-size:13px;font-style:normal;top:9px}.el-alert-fade-enter,.el-alert-fade-leave-active{opacity:0}.el-notification{background-color:#fff;border:1px solid #ebeef5;border-radius:8px;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-sizing:border-box;display:flex;overflow:hidden;padding:14px 26px 14px 13px;position:fixed;transition:opacity .3s,transform .3s,left .3s,right .3s,top .4s,bottom .3s;width:330px}.el-notification.right{right:16px}.el-notification.left{left:16px}.el-notification__group{margin-left:13px;margin-right:8px}.el-notification__title{color:#303133;font-size:16px;font-weight:700;margin:0}.el-notification__content{color:#606266;font-size:14px;line-height:21px;margin:6px 0 0;text-align:justify}.el-notification__content p{margin:0}.el-notification__icon{font-size:24px;height:24px;width:24px}.el-notification__closeBtn{color:#909399;cursor:pointer;font-size:16px;position:absolute;right:15px;top:18px}.el-notification__closeBtn:hover{color:#606266}.el-notification .el-icon-success{color:#00b27f}.el-notification .el-icon-error{color:#ff6154}.el-notification .el-icon-info{color:#4b4c4d}.el-notification .el-icon-warning{color:#fcbe2d}.el-notification-fade-enter.right{right:0;transform:translateX(100%)}.el-notification-fade-enter.left{left:0;transform:translateX(-100%)}.el-notification-fade-leave-active{opacity:0}.el-input-number{display:inline-block;line-height:38px;position:relative;width:180px}.el-input-number .el-input{display:block}.el-input-number .el-input__inner{-webkit-appearance:none;padding-left:50px;padding-right:50px;text-align:center}.el-input-number__decrease,.el-input-number__increase{background:#f5f7fa;color:#606266;cursor:pointer;font-size:13px;height:auto;position:absolute;text-align:center;top:1px;width:40px;z-index:1}.el-input-number__decrease:hover,.el-input-number__increase:hover{color:#1a7efb}.el-input-number__decrease:hover:not(.is-disabled)~.el-input .el-input__inner:not(.is-disabled),.el-input-number__increase:hover:not(.is-disabled)~.el-input .el-input__inner:not(.is-disabled){border-color:#1a7efb}.el-input-number__decrease.is-disabled,.el-input-number__increase.is-disabled{color:#afb3ba;cursor:not-allowed}.el-input-number__increase{border-left:1px solid #dadbdd;border-radius:0 7px 7px 0;right:1px}.el-input-number__decrease{border-radius:7px 0 0 7px;border-right:1px solid #dadbdd;left:1px}.el-input-number.is-disabled .el-input-number__decrease,.el-input-number.is-disabled .el-input-number__increase{border-color:#e4e7ed;color:#e4e7ed}.el-input-number.is-disabled .el-input-number__decrease:hover,.el-input-number.is-disabled .el-input-number__increase:hover{color:#e4e7ed;cursor:not-allowed}.el-input-number--medium{line-height:34px;width:200px}.el-input-number--medium .el-input-number__decrease,.el-input-number--medium .el-input-number__increase{font-size:14px;width:36px}.el-input-number--medium .el-input__inner{padding-left:43px;padding-right:43px}.el-input-number--small{line-height:30px;width:130px}.el-input-number--small .el-input-number__decrease,.el-input-number--small .el-input-number__increase{font-size:13px;width:32px}.el-input-number--small .el-input-number__decrease [class*=el-icon],.el-input-number--small .el-input-number__increase [class*=el-icon]{transform:scale(.9)}.el-input-number--small .el-input__inner{padding-left:39px;padding-right:39px}.el-input-number--mini{line-height:26px;width:130px}.el-input-number--mini .el-input-number__decrease,.el-input-number--mini .el-input-number__increase{font-size:12px;width:28px}.el-input-number--mini .el-input-number__decrease [class*=el-icon],.el-input-number--mini .el-input-number__increase [class*=el-icon]{transform:scale(.8)}.el-input-number--mini .el-input__inner{padding-left:35px;padding-right:35px}.el-input-number.is-without-controls .el-input__inner{padding-left:15px;padding-right:15px}.el-input-number.is-controls-right .el-input__inner{padding-left:15px;padding-right:50px}.el-input-number.is-controls-right .el-input-number__decrease,.el-input-number.is-controls-right .el-input-number__increase{height:auto;line-height:19px}.el-input-number.is-controls-right .el-input-number__decrease [class*=el-icon],.el-input-number.is-controls-right .el-input-number__increase [class*=el-icon]{transform:scale(.8)}.el-input-number.is-controls-right .el-input-number__increase{border-bottom:1px solid #dadbdd;border-radius:0 7px 0 0}.el-input-number.is-controls-right .el-input-number__decrease{border-left:1px solid #dadbdd;border-radius:0 0 7px 0;border-right:none;bottom:1px;left:auto;right:1px;top:auto}.el-input-number.is-controls-right[class*=medium] [class*=decrease],.el-input-number.is-controls-right[class*=medium] [class*=increase]{line-height:17px}.el-input-number.is-controls-right[class*=small] [class*=decrease],.el-input-number.is-controls-right[class*=small] [class*=increase]{line-height:15px}.el-input-number.is-controls-right[class*=mini] [class*=decrease],.el-input-number.is-controls-right[class*=mini] [class*=increase]{line-height:13px}.el-tooltip:focus:hover,.el-tooltip:focus:not(.focusing){outline-width:0}.el-tooltip__popper{word-wrap:break-word;border-radius:4px;font-size:12px;line-height:1.2;min-width:10px;padding:10px;position:absolute;z-index:2000}.el-tooltip__popper .popper__arrow,.el-tooltip__popper .popper__arrow:after{border-color:transparent;border-style:solid;display:block;height:0;position:absolute;width:0}.el-tooltip__popper .popper__arrow{border-width:6px}.el-tooltip__popper .popper__arrow:after{border-width:5px;content:" "}.el-tooltip__popper[x-placement^=top]{margin-bottom:12px}.el-tooltip__popper[x-placement^=top] .popper__arrow{border-bottom-width:0;border-top-color:#303133;bottom:-6px}.el-tooltip__popper[x-placement^=top] .popper__arrow:after{border-bottom-width:0;border-top-color:#303133;bottom:1px;margin-left:-5px}.el-tooltip__popper[x-placement^=bottom]{margin-top:12px}.el-tooltip__popper[x-placement^=bottom] .popper__arrow{border-bottom-color:#303133;border-top-width:0;top:-6px}.el-tooltip__popper[x-placement^=bottom] .popper__arrow:after{border-bottom-color:#303133;border-top-width:0;margin-left:-5px;top:1px}.el-tooltip__popper[x-placement^=right]{margin-left:12px}.el-tooltip__popper[x-placement^=right] .popper__arrow{border-left-width:0;border-right-color:#303133;left:-6px}.el-tooltip__popper[x-placement^=right] .popper__arrow:after{border-left-width:0;border-right-color:#303133;bottom:-5px;left:1px}.el-tooltip__popper[x-placement^=left]{margin-right:12px}.el-tooltip__popper[x-placement^=left] .popper__arrow{border-left-color:#303133;border-right-width:0;right:-6px}.el-tooltip__popper[x-placement^=left] .popper__arrow:after{border-left-color:#303133;border-right-width:0;bottom:-5px;margin-left:-5px;right:1px}.el-tooltip__popper.is-dark{background:#303133;color:#fff}.el-tooltip__popper.is-light{background:#fff;border:1px solid #303133}.el-tooltip__popper.is-light[x-placement^=top] .popper__arrow{border-top-color:#303133}.el-tooltip__popper.is-light[x-placement^=top] .popper__arrow:after{border-top-color:#fff}.el-tooltip__popper.is-light[x-placement^=bottom] .popper__arrow{border-bottom-color:#303133}.el-tooltip__popper.is-light[x-placement^=bottom] .popper__arrow:after{border-bottom-color:#fff}.el-tooltip__popper.is-light[x-placement^=left] .popper__arrow{border-left-color:#303133}.el-tooltip__popper.is-light[x-placement^=left] .popper__arrow:after{border-left-color:#fff}.el-tooltip__popper.is-light[x-placement^=right] .popper__arrow{border-right-color:#303133}.el-tooltip__popper.is-light[x-placement^=right] .popper__arrow:after{border-right-color:#fff}.el-slider:after,.el-slider:before{content:"";display:table}.el-slider:after{clear:both}.el-slider__runway{background-color:#e4e7ed;border-radius:3px;cursor:pointer;height:6px;margin:16px 0;position:relative;vertical-align:middle;width:100%}.el-slider__runway.show-input{margin-right:160px;width:auto}.el-slider__runway.disabled{cursor:default}.el-slider__runway.disabled .el-slider__bar{background-color:#afb3ba}.el-slider__runway.disabled .el-slider__button{border-color:#afb3ba}.el-slider__runway.disabled .el-slider__button-wrapper.dragging,.el-slider__runway.disabled .el-slider__button-wrapper.hover,.el-slider__runway.disabled .el-slider__button-wrapper:hover{cursor:not-allowed}.el-slider__runway.disabled .el-slider__button.dragging,.el-slider__runway.disabled .el-slider__button.hover,.el-slider__runway.disabled .el-slider__button:hover{transform:scale(1)}.el-slider__runway.disabled .el-slider__button.dragging,.el-slider__runway.disabled .el-slider__button.hover,.el-slider__runway.disabled .el-slider__button:hover{cursor:not-allowed}.el-slider__input{float:right;margin-top:3px;width:130px}.el-slider__input.el-input-number--mini{margin-top:5px}.el-slider__input.el-input-number--medium{margin-top:0}.el-slider__input.el-input-number--large{margin-top:-2px}.el-slider__bar{background-color:#1a7efb;border-bottom-left-radius:3px;border-top-left-radius:3px;height:6px;position:absolute}.el-slider__button-wrapper{background-color:transparent;height:36px;line-height:normal;position:absolute;text-align:center;top:-15px;transform:translateX(-50%);-webkit-user-select:none;-moz-user-select:none;user-select:none;width:36px;z-index:1001}.el-slider__button-wrapper:after{content:"";height:100%}.el-slider__button-wrapper .el-tooltip,.el-slider__button-wrapper:after{display:inline-block;vertical-align:middle}.el-slider__button-wrapper.hover,.el-slider__button-wrapper:hover{cursor:grab}.el-slider__button-wrapper.dragging{cursor:grabbing}.el-slider__button{background-color:#fff;border:2px solid #1a7efb;border-radius:50%;height:16px;transition:.2s;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:16px}.el-slider__button.dragging,.el-slider__button.hover,.el-slider__button:hover{transform:scale(1.2)}.el-slider__button.hover,.el-slider__button:hover{cursor:grab}.el-slider__button.dragging{cursor:grabbing}.el-slider__stop{background-color:#fff;border-radius:100%;height:6px;position:absolute;transform:translateX(-50%);width:6px}.el-slider__marks{height:100%;left:12px;top:0;width:18px}.el-slider__marks-text{color:#4b4c4d;font-size:14px;margin-top:15px;position:absolute;transform:translateX(-50%)}.el-slider.is-vertical{position:relative}.el-slider.is-vertical .el-slider__runway{height:100%;margin:0 16px;width:6px}.el-slider.is-vertical .el-slider__bar{border-radius:0 0 3px 3px;height:auto;width:6px}.el-slider.is-vertical .el-slider__button-wrapper{left:-15px;top:auto;transform:translateY(50%)}.el-slider.is-vertical .el-slider__stop{transform:translateY(50%)}.el-slider.is-vertical.el-slider--with-input{padding-bottom:58px}.el-slider.is-vertical.el-slider--with-input .el-slider__input{bottom:22px;float:none;margin-top:15px;overflow:visible;position:absolute;width:36px}.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input__inner{padding-left:5px;padding-right:5px;text-align:center}.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__decrease,.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__increase{border:1px solid #dadbdd;box-sizing:border-box;line-height:20px;margin-top:-1px;top:32px;transition:border-color .2s cubic-bezier(.645,.045,.355,1)}.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__decrease{border-bottom-left-radius:7px;right:18px;width:18px}.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__increase{border-bottom-right-radius:7px;width:19px}.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__increase~.el-input .el-input__inner{border-bottom-left-radius:0;border-bottom-right-radius:0}.el-slider.is-vertical.el-slider--with-input .el-slider__input:hover .el-input-number__decrease,.el-slider.is-vertical.el-slider--with-input .el-slider__input:hover .el-input-number__increase{border-color:#afb3ba}.el-slider.is-vertical.el-slider--with-input .el-slider__input:active .el-input-number__decrease,.el-slider.is-vertical.el-slider--with-input .el-slider__input:active .el-input-number__increase{border-color:#1a7efb}.el-slider.is-vertical .el-slider__marks-text{left:15px;margin-top:0;transform:translateY(50%)}.el-loading-parent--relative{position:relative!important}.el-loading-parent--hidden{overflow:hidden!important}.el-loading-mask{background-color:hsla(0,0%,100%,.9);bottom:0;left:0;margin:0;position:absolute;right:0;top:0;transition:opacity .3s;z-index:2000}.el-loading-mask.is-fullscreen{position:fixed}.el-loading-mask.is-fullscreen .el-loading-spinner{margin-top:-25px}.el-loading-mask.is-fullscreen .el-loading-spinner .circular{height:50px;width:50px}.el-loading-spinner{margin-top:-21px;position:absolute;text-align:center;top:50%;width:100%}.el-loading-spinner .el-loading-text{color:#1a7efb;font-size:14px;margin:3px 0}.el-loading-spinner .circular{animation:loading-rotate 2s linear infinite;height:42px;width:42px}.el-loading-spinner .path{stroke-dasharray:90,150;stroke-dashoffset:0;stroke-width:2;stroke:#1a7efb;stroke-linecap:round;animation:loading-dash 1.5s ease-in-out infinite}.el-loading-spinner i{color:#1a7efb}.el-loading-fade-enter,.el-loading-fade-leave-active{opacity:0}@keyframes loading-rotate{to{transform:rotate(1turn)}}@keyframes loading-dash{0%{stroke-dasharray:1,200;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-40px}to{stroke-dasharray:90,150;stroke-dashoffset:-120px}}.el-row{box-sizing:border-box;position:relative}.el-row:after,.el-row:before{content:"";display:table}.el-row:after{clear:both}.el-row--flex{display:flex}.el-row--flex:after,.el-row--flex:before{display:none}.el-row--flex.is-justify-center{justify-content:center}.el-row--flex.is-justify-end{justify-content:flex-end}.el-row--flex.is-justify-space-between{justify-content:space-between}.el-row--flex.is-justify-space-around{justify-content:space-around}.el-row--flex.is-align-top{align-items:flex-start}.el-row--flex.is-align-middle{align-items:center}.el-row--flex.is-align-bottom{align-items:flex-end}[class*=el-col-]{box-sizing:border-box;float:left}.el-col-0{display:none;width:0}.el-col-offset-0{margin-left:0}.el-col-pull-0{position:relative;right:0}.el-col-push-0{left:0;position:relative}.el-col-1{width:4.1666666667%}.el-col-offset-1{margin-left:4.1666666667%}.el-col-pull-1{position:relative;right:4.1666666667%}.el-col-push-1{left:4.1666666667%;position:relative}.el-col-2{width:8.3333333333%}.el-col-offset-2{margin-left:8.3333333333%}.el-col-pull-2{position:relative;right:8.3333333333%}.el-col-push-2{left:8.3333333333%;position:relative}.el-col-3{width:12.5%}.el-col-offset-3{margin-left:12.5%}.el-col-pull-3{position:relative;right:12.5%}.el-col-push-3{left:12.5%;position:relative}.el-col-4{width:16.6666666667%}.el-col-offset-4{margin-left:16.6666666667%}.el-col-pull-4{position:relative;right:16.6666666667%}.el-col-push-4{left:16.6666666667%;position:relative}.el-col-5{width:20.8333333333%}.el-col-offset-5{margin-left:20.8333333333%}.el-col-pull-5{position:relative;right:20.8333333333%}.el-col-push-5{left:20.8333333333%;position:relative}.el-col-6{width:25%}.el-col-offset-6{margin-left:25%}.el-col-pull-6{position:relative;right:25%}.el-col-push-6{left:25%;position:relative}.el-col-7{width:29.1666666667%}.el-col-offset-7{margin-left:29.1666666667%}.el-col-pull-7{position:relative;right:29.1666666667%}.el-col-push-7{left:29.1666666667%;position:relative}.el-col-8{width:33.3333333333%}.el-col-offset-8{margin-left:33.3333333333%}.el-col-pull-8{position:relative;right:33.3333333333%}.el-col-push-8{left:33.3333333333%;position:relative}.el-col-9{width:37.5%}.el-col-offset-9{margin-left:37.5%}.el-col-pull-9{position:relative;right:37.5%}.el-col-push-9{left:37.5%;position:relative}.el-col-10{width:41.6666666667%}.el-col-offset-10{margin-left:41.6666666667%}.el-col-pull-10{position:relative;right:41.6666666667%}.el-col-push-10{left:41.6666666667%;position:relative}.el-col-11{width:45.8333333333%}.el-col-offset-11{margin-left:45.8333333333%}.el-col-pull-11{position:relative;right:45.8333333333%}.el-col-push-11{left:45.8333333333%;position:relative}.el-col-12{width:50%}.el-col-offset-12{margin-left:50%}.el-col-pull-12{position:relative;right:50%}.el-col-push-12{left:50%;position:relative}.el-col-13{width:54.1666666667%}.el-col-offset-13{margin-left:54.1666666667%}.el-col-pull-13{position:relative;right:54.1666666667%}.el-col-push-13{left:54.1666666667%;position:relative}.el-col-14{width:58.3333333333%}.el-col-offset-14{margin-left:58.3333333333%}.el-col-pull-14{position:relative;right:58.3333333333%}.el-col-push-14{left:58.3333333333%;position:relative}.el-col-15{width:62.5%}.el-col-offset-15{margin-left:62.5%}.el-col-pull-15{position:relative;right:62.5%}.el-col-push-15{left:62.5%;position:relative}.el-col-16{width:66.6666666667%}.el-col-offset-16{margin-left:66.6666666667%}.el-col-pull-16{position:relative;right:66.6666666667%}.el-col-push-16{left:66.6666666667%;position:relative}.el-col-17{width:70.8333333333%}.el-col-offset-17{margin-left:70.8333333333%}.el-col-pull-17{position:relative;right:70.8333333333%}.el-col-push-17{left:70.8333333333%;position:relative}.el-col-18{width:75%}.el-col-offset-18{margin-left:75%}.el-col-pull-18{position:relative;right:75%}.el-col-push-18{left:75%;position:relative}.el-col-19{width:79.1666666667%}.el-col-offset-19{margin-left:79.1666666667%}.el-col-pull-19{position:relative;right:79.1666666667%}.el-col-push-19{left:79.1666666667%;position:relative}.el-col-20{width:83.3333333333%}.el-col-offset-20{margin-left:83.3333333333%}.el-col-pull-20{position:relative;right:83.3333333333%}.el-col-push-20{left:83.3333333333%;position:relative}.el-col-21{width:87.5%}.el-col-offset-21{margin-left:87.5%}.el-col-pull-21{position:relative;right:87.5%}.el-col-push-21{left:87.5%;position:relative}.el-col-22{width:91.6666666667%}.el-col-offset-22{margin-left:91.6666666667%}.el-col-pull-22{position:relative;right:91.6666666667%}.el-col-push-22{left:91.6666666667%;position:relative}.el-col-23{width:95.8333333333%}.el-col-offset-23{margin-left:95.8333333333%}.el-col-pull-23{position:relative;right:95.8333333333%}.el-col-push-23{left:95.8333333333%;position:relative}.el-col-24{width:100%}.el-col-offset-24{margin-left:100%}.el-col-pull-24{position:relative;right:100%}.el-col-push-24{left:100%;position:relative}@media only screen and (max-width:767px){.el-col-xs-0{display:none;width:0}.el-col-xs-offset-0{margin-left:0}.el-col-xs-pull-0{position:relative;right:0}.el-col-xs-push-0{left:0;position:relative}.el-col-xs-1{width:4.1666666667%}.el-col-xs-offset-1{margin-left:4.1666666667%}.el-col-xs-pull-1{position:relative;right:4.1666666667%}.el-col-xs-push-1{left:4.1666666667%;position:relative}.el-col-xs-2{width:8.3333333333%}.el-col-xs-offset-2{margin-left:8.3333333333%}.el-col-xs-pull-2{position:relative;right:8.3333333333%}.el-col-xs-push-2{left:8.3333333333%;position:relative}.el-col-xs-3{width:12.5%}.el-col-xs-offset-3{margin-left:12.5%}.el-col-xs-pull-3{position:relative;right:12.5%}.el-col-xs-push-3{left:12.5%;position:relative}.el-col-xs-4{width:16.6666666667%}.el-col-xs-offset-4{margin-left:16.6666666667%}.el-col-xs-pull-4{position:relative;right:16.6666666667%}.el-col-xs-push-4{left:16.6666666667%;position:relative}.el-col-xs-5{width:20.8333333333%}.el-col-xs-offset-5{margin-left:20.8333333333%}.el-col-xs-pull-5{position:relative;right:20.8333333333%}.el-col-xs-push-5{left:20.8333333333%;position:relative}.el-col-xs-6{width:25%}.el-col-xs-offset-6{margin-left:25%}.el-col-xs-pull-6{position:relative;right:25%}.el-col-xs-push-6{left:25%;position:relative}.el-col-xs-7{width:29.1666666667%}.el-col-xs-offset-7{margin-left:29.1666666667%}.el-col-xs-pull-7{position:relative;right:29.1666666667%}.el-col-xs-push-7{left:29.1666666667%;position:relative}.el-col-xs-8{width:33.3333333333%}.el-col-xs-offset-8{margin-left:33.3333333333%}.el-col-xs-pull-8{position:relative;right:33.3333333333%}.el-col-xs-push-8{left:33.3333333333%;position:relative}.el-col-xs-9{width:37.5%}.el-col-xs-offset-9{margin-left:37.5%}.el-col-xs-pull-9{position:relative;right:37.5%}.el-col-xs-push-9{left:37.5%;position:relative}.el-col-xs-10{width:41.6666666667%}.el-col-xs-offset-10{margin-left:41.6666666667%}.el-col-xs-pull-10{position:relative;right:41.6666666667%}.el-col-xs-push-10{left:41.6666666667%;position:relative}.el-col-xs-11{width:45.8333333333%}.el-col-xs-offset-11{margin-left:45.8333333333%}.el-col-xs-pull-11{position:relative;right:45.8333333333%}.el-col-xs-push-11{left:45.8333333333%;position:relative}.el-col-xs-12{width:50%}.el-col-xs-offset-12{margin-left:50%}.el-col-xs-pull-12{position:relative;right:50%}.el-col-xs-push-12{left:50%;position:relative}.el-col-xs-13{width:54.1666666667%}.el-col-xs-offset-13{margin-left:54.1666666667%}.el-col-xs-pull-13{position:relative;right:54.1666666667%}.el-col-xs-push-13{left:54.1666666667%;position:relative}.el-col-xs-14{width:58.3333333333%}.el-col-xs-offset-14{margin-left:58.3333333333%}.el-col-xs-pull-14{position:relative;right:58.3333333333%}.el-col-xs-push-14{left:58.3333333333%;position:relative}.el-col-xs-15{width:62.5%}.el-col-xs-offset-15{margin-left:62.5%}.el-col-xs-pull-15{position:relative;right:62.5%}.el-col-xs-push-15{left:62.5%;position:relative}.el-col-xs-16{width:66.6666666667%}.el-col-xs-offset-16{margin-left:66.6666666667%}.el-col-xs-pull-16{position:relative;right:66.6666666667%}.el-col-xs-push-16{left:66.6666666667%;position:relative}.el-col-xs-17{width:70.8333333333%}.el-col-xs-offset-17{margin-left:70.8333333333%}.el-col-xs-pull-17{position:relative;right:70.8333333333%}.el-col-xs-push-17{left:70.8333333333%;position:relative}.el-col-xs-18{width:75%}.el-col-xs-offset-18{margin-left:75%}.el-col-xs-pull-18{position:relative;right:75%}.el-col-xs-push-18{left:75%;position:relative}.el-col-xs-19{width:79.1666666667%}.el-col-xs-offset-19{margin-left:79.1666666667%}.el-col-xs-pull-19{position:relative;right:79.1666666667%}.el-col-xs-push-19{left:79.1666666667%;position:relative}.el-col-xs-20{width:83.3333333333%}.el-col-xs-offset-20{margin-left:83.3333333333%}.el-col-xs-pull-20{position:relative;right:83.3333333333%}.el-col-xs-push-20{left:83.3333333333%;position:relative}.el-col-xs-21{width:87.5%}.el-col-xs-offset-21{margin-left:87.5%}.el-col-xs-pull-21{position:relative;right:87.5%}.el-col-xs-push-21{left:87.5%;position:relative}.el-col-xs-22{width:91.6666666667%}.el-col-xs-offset-22{margin-left:91.6666666667%}.el-col-xs-pull-22{position:relative;right:91.6666666667%}.el-col-xs-push-22{left:91.6666666667%;position:relative}.el-col-xs-23{width:95.8333333333%}.el-col-xs-offset-23{margin-left:95.8333333333%}.el-col-xs-pull-23{position:relative;right:95.8333333333%}.el-col-xs-push-23{left:95.8333333333%;position:relative}.el-col-xs-24{width:100%}.el-col-xs-offset-24{margin-left:100%}.el-col-xs-pull-24{position:relative;right:100%}.el-col-xs-push-24{left:100%;position:relative}}@media only screen and (min-width:768px){.el-col-sm-0{display:none;width:0}.el-col-sm-offset-0{margin-left:0}.el-col-sm-pull-0{position:relative;right:0}.el-col-sm-push-0{left:0;position:relative}.el-col-sm-1{width:4.1666666667%}.el-col-sm-offset-1{margin-left:4.1666666667%}.el-col-sm-pull-1{position:relative;right:4.1666666667%}.el-col-sm-push-1{left:4.1666666667%;position:relative}.el-col-sm-2{width:8.3333333333%}.el-col-sm-offset-2{margin-left:8.3333333333%}.el-col-sm-pull-2{position:relative;right:8.3333333333%}.el-col-sm-push-2{left:8.3333333333%;position:relative}.el-col-sm-3{width:12.5%}.el-col-sm-offset-3{margin-left:12.5%}.el-col-sm-pull-3{position:relative;right:12.5%}.el-col-sm-push-3{left:12.5%;position:relative}.el-col-sm-4{width:16.6666666667%}.el-col-sm-offset-4{margin-left:16.6666666667%}.el-col-sm-pull-4{position:relative;right:16.6666666667%}.el-col-sm-push-4{left:16.6666666667%;position:relative}.el-col-sm-5{width:20.8333333333%}.el-col-sm-offset-5{margin-left:20.8333333333%}.el-col-sm-pull-5{position:relative;right:20.8333333333%}.el-col-sm-push-5{left:20.8333333333%;position:relative}.el-col-sm-6{width:25%}.el-col-sm-offset-6{margin-left:25%}.el-col-sm-pull-6{position:relative;right:25%}.el-col-sm-push-6{left:25%;position:relative}.el-col-sm-7{width:29.1666666667%}.el-col-sm-offset-7{margin-left:29.1666666667%}.el-col-sm-pull-7{position:relative;right:29.1666666667%}.el-col-sm-push-7{left:29.1666666667%;position:relative}.el-col-sm-8{width:33.3333333333%}.el-col-sm-offset-8{margin-left:33.3333333333%}.el-col-sm-pull-8{position:relative;right:33.3333333333%}.el-col-sm-push-8{left:33.3333333333%;position:relative}.el-col-sm-9{width:37.5%}.el-col-sm-offset-9{margin-left:37.5%}.el-col-sm-pull-9{position:relative;right:37.5%}.el-col-sm-push-9{left:37.5%;position:relative}.el-col-sm-10{width:41.6666666667%}.el-col-sm-offset-10{margin-left:41.6666666667%}.el-col-sm-pull-10{position:relative;right:41.6666666667%}.el-col-sm-push-10{left:41.6666666667%;position:relative}.el-col-sm-11{width:45.8333333333%}.el-col-sm-offset-11{margin-left:45.8333333333%}.el-col-sm-pull-11{position:relative;right:45.8333333333%}.el-col-sm-push-11{left:45.8333333333%;position:relative}.el-col-sm-12{width:50%}.el-col-sm-offset-12{margin-left:50%}.el-col-sm-pull-12{position:relative;right:50%}.el-col-sm-push-12{left:50%;position:relative}.el-col-sm-13{width:54.1666666667%}.el-col-sm-offset-13{margin-left:54.1666666667%}.el-col-sm-pull-13{position:relative;right:54.1666666667%}.el-col-sm-push-13{left:54.1666666667%;position:relative}.el-col-sm-14{width:58.3333333333%}.el-col-sm-offset-14{margin-left:58.3333333333%}.el-col-sm-pull-14{position:relative;right:58.3333333333%}.el-col-sm-push-14{left:58.3333333333%;position:relative}.el-col-sm-15{width:62.5%}.el-col-sm-offset-15{margin-left:62.5%}.el-col-sm-pull-15{position:relative;right:62.5%}.el-col-sm-push-15{left:62.5%;position:relative}.el-col-sm-16{width:66.6666666667%}.el-col-sm-offset-16{margin-left:66.6666666667%}.el-col-sm-pull-16{position:relative;right:66.6666666667%}.el-col-sm-push-16{left:66.6666666667%;position:relative}.el-col-sm-17{width:70.8333333333%}.el-col-sm-offset-17{margin-left:70.8333333333%}.el-col-sm-pull-17{position:relative;right:70.8333333333%}.el-col-sm-push-17{left:70.8333333333%;position:relative}.el-col-sm-18{width:75%}.el-col-sm-offset-18{margin-left:75%}.el-col-sm-pull-18{position:relative;right:75%}.el-col-sm-push-18{left:75%;position:relative}.el-col-sm-19{width:79.1666666667%}.el-col-sm-offset-19{margin-left:79.1666666667%}.el-col-sm-pull-19{position:relative;right:79.1666666667%}.el-col-sm-push-19{left:79.1666666667%;position:relative}.el-col-sm-20{width:83.3333333333%}.el-col-sm-offset-20{margin-left:83.3333333333%}.el-col-sm-pull-20{position:relative;right:83.3333333333%}.el-col-sm-push-20{left:83.3333333333%;position:relative}.el-col-sm-21{width:87.5%}.el-col-sm-offset-21{margin-left:87.5%}.el-col-sm-pull-21{position:relative;right:87.5%}.el-col-sm-push-21{left:87.5%;position:relative}.el-col-sm-22{width:91.6666666667%}.el-col-sm-offset-22{margin-left:91.6666666667%}.el-col-sm-pull-22{position:relative;right:91.6666666667%}.el-col-sm-push-22{left:91.6666666667%;position:relative}.el-col-sm-23{width:95.8333333333%}.el-col-sm-offset-23{margin-left:95.8333333333%}.el-col-sm-pull-23{position:relative;right:95.8333333333%}.el-col-sm-push-23{left:95.8333333333%;position:relative}.el-col-sm-24{width:100%}.el-col-sm-offset-24{margin-left:100%}.el-col-sm-pull-24{position:relative;right:100%}.el-col-sm-push-24{left:100%;position:relative}}@media only screen and (min-width:992px){.el-col-md-0{display:none;width:0}.el-col-md-offset-0{margin-left:0}.el-col-md-pull-0{position:relative;right:0}.el-col-md-push-0{left:0;position:relative}.el-col-md-1{width:4.1666666667%}.el-col-md-offset-1{margin-left:4.1666666667%}.el-col-md-pull-1{position:relative;right:4.1666666667%}.el-col-md-push-1{left:4.1666666667%;position:relative}.el-col-md-2{width:8.3333333333%}.el-col-md-offset-2{margin-left:8.3333333333%}.el-col-md-pull-2{position:relative;right:8.3333333333%}.el-col-md-push-2{left:8.3333333333%;position:relative}.el-col-md-3{width:12.5%}.el-col-md-offset-3{margin-left:12.5%}.el-col-md-pull-3{position:relative;right:12.5%}.el-col-md-push-3{left:12.5%;position:relative}.el-col-md-4{width:16.6666666667%}.el-col-md-offset-4{margin-left:16.6666666667%}.el-col-md-pull-4{position:relative;right:16.6666666667%}.el-col-md-push-4{left:16.6666666667%;position:relative}.el-col-md-5{width:20.8333333333%}.el-col-md-offset-5{margin-left:20.8333333333%}.el-col-md-pull-5{position:relative;right:20.8333333333%}.el-col-md-push-5{left:20.8333333333%;position:relative}.el-col-md-6{width:25%}.el-col-md-offset-6{margin-left:25%}.el-col-md-pull-6{position:relative;right:25%}.el-col-md-push-6{left:25%;position:relative}.el-col-md-7{width:29.1666666667%}.el-col-md-offset-7{margin-left:29.1666666667%}.el-col-md-pull-7{position:relative;right:29.1666666667%}.el-col-md-push-7{left:29.1666666667%;position:relative}.el-col-md-8{width:33.3333333333%}.el-col-md-offset-8{margin-left:33.3333333333%}.el-col-md-pull-8{position:relative;right:33.3333333333%}.el-col-md-push-8{left:33.3333333333%;position:relative}.el-col-md-9{width:37.5%}.el-col-md-offset-9{margin-left:37.5%}.el-col-md-pull-9{position:relative;right:37.5%}.el-col-md-push-9{left:37.5%;position:relative}.el-col-md-10{width:41.6666666667%}.el-col-md-offset-10{margin-left:41.6666666667%}.el-col-md-pull-10{position:relative;right:41.6666666667%}.el-col-md-push-10{left:41.6666666667%;position:relative}.el-col-md-11{width:45.8333333333%}.el-col-md-offset-11{margin-left:45.8333333333%}.el-col-md-pull-11{position:relative;right:45.8333333333%}.el-col-md-push-11{left:45.8333333333%;position:relative}.el-col-md-12{width:50%}.el-col-md-offset-12{margin-left:50%}.el-col-md-pull-12{position:relative;right:50%}.el-col-md-push-12{left:50%;position:relative}.el-col-md-13{width:54.1666666667%}.el-col-md-offset-13{margin-left:54.1666666667%}.el-col-md-pull-13{position:relative;right:54.1666666667%}.el-col-md-push-13{left:54.1666666667%;position:relative}.el-col-md-14{width:58.3333333333%}.el-col-md-offset-14{margin-left:58.3333333333%}.el-col-md-pull-14{position:relative;right:58.3333333333%}.el-col-md-push-14{left:58.3333333333%;position:relative}.el-col-md-15{width:62.5%}.el-col-md-offset-15{margin-left:62.5%}.el-col-md-pull-15{position:relative;right:62.5%}.el-col-md-push-15{left:62.5%;position:relative}.el-col-md-16{width:66.6666666667%}.el-col-md-offset-16{margin-left:66.6666666667%}.el-col-md-pull-16{position:relative;right:66.6666666667%}.el-col-md-push-16{left:66.6666666667%;position:relative}.el-col-md-17{width:70.8333333333%}.el-col-md-offset-17{margin-left:70.8333333333%}.el-col-md-pull-17{position:relative;right:70.8333333333%}.el-col-md-push-17{left:70.8333333333%;position:relative}.el-col-md-18{width:75%}.el-col-md-offset-18{margin-left:75%}.el-col-md-pull-18{position:relative;right:75%}.el-col-md-push-18{left:75%;position:relative}.el-col-md-19{width:79.1666666667%}.el-col-md-offset-19{margin-left:79.1666666667%}.el-col-md-pull-19{position:relative;right:79.1666666667%}.el-col-md-push-19{left:79.1666666667%;position:relative}.el-col-md-20{width:83.3333333333%}.el-col-md-offset-20{margin-left:83.3333333333%}.el-col-md-pull-20{position:relative;right:83.3333333333%}.el-col-md-push-20{left:83.3333333333%;position:relative}.el-col-md-21{width:87.5%}.el-col-md-offset-21{margin-left:87.5%}.el-col-md-pull-21{position:relative;right:87.5%}.el-col-md-push-21{left:87.5%;position:relative}.el-col-md-22{width:91.6666666667%}.el-col-md-offset-22{margin-left:91.6666666667%}.el-col-md-pull-22{position:relative;right:91.6666666667%}.el-col-md-push-22{left:91.6666666667%;position:relative}.el-col-md-23{width:95.8333333333%}.el-col-md-offset-23{margin-left:95.8333333333%}.el-col-md-pull-23{position:relative;right:95.8333333333%}.el-col-md-push-23{left:95.8333333333%;position:relative}.el-col-md-24{width:100%}.el-col-md-offset-24{margin-left:100%}.el-col-md-pull-24{position:relative;right:100%}.el-col-md-push-24{left:100%;position:relative}}@media only screen and (min-width:1200px){.el-col-lg-0{display:none;width:0}.el-col-lg-offset-0{margin-left:0}.el-col-lg-pull-0{position:relative;right:0}.el-col-lg-push-0{left:0;position:relative}.el-col-lg-1{width:4.1666666667%}.el-col-lg-offset-1{margin-left:4.1666666667%}.el-col-lg-pull-1{position:relative;right:4.1666666667%}.el-col-lg-push-1{left:4.1666666667%;position:relative}.el-col-lg-2{width:8.3333333333%}.el-col-lg-offset-2{margin-left:8.3333333333%}.el-col-lg-pull-2{position:relative;right:8.3333333333%}.el-col-lg-push-2{left:8.3333333333%;position:relative}.el-col-lg-3{width:12.5%}.el-col-lg-offset-3{margin-left:12.5%}.el-col-lg-pull-3{position:relative;right:12.5%}.el-col-lg-push-3{left:12.5%;position:relative}.el-col-lg-4{width:16.6666666667%}.el-col-lg-offset-4{margin-left:16.6666666667%}.el-col-lg-pull-4{position:relative;right:16.6666666667%}.el-col-lg-push-4{left:16.6666666667%;position:relative}.el-col-lg-5{width:20.8333333333%}.el-col-lg-offset-5{margin-left:20.8333333333%}.el-col-lg-pull-5{position:relative;right:20.8333333333%}.el-col-lg-push-5{left:20.8333333333%;position:relative}.el-col-lg-6{width:25%}.el-col-lg-offset-6{margin-left:25%}.el-col-lg-pull-6{position:relative;right:25%}.el-col-lg-push-6{left:25%;position:relative}.el-col-lg-7{width:29.1666666667%}.el-col-lg-offset-7{margin-left:29.1666666667%}.el-col-lg-pull-7{position:relative;right:29.1666666667%}.el-col-lg-push-7{left:29.1666666667%;position:relative}.el-col-lg-8{width:33.3333333333%}.el-col-lg-offset-8{margin-left:33.3333333333%}.el-col-lg-pull-8{position:relative;right:33.3333333333%}.el-col-lg-push-8{left:33.3333333333%;position:relative}.el-col-lg-9{width:37.5%}.el-col-lg-offset-9{margin-left:37.5%}.el-col-lg-pull-9{position:relative;right:37.5%}.el-col-lg-push-9{left:37.5%;position:relative}.el-col-lg-10{width:41.6666666667%}.el-col-lg-offset-10{margin-left:41.6666666667%}.el-col-lg-pull-10{position:relative;right:41.6666666667%}.el-col-lg-push-10{left:41.6666666667%;position:relative}.el-col-lg-11{width:45.8333333333%}.el-col-lg-offset-11{margin-left:45.8333333333%}.el-col-lg-pull-11{position:relative;right:45.8333333333%}.el-col-lg-push-11{left:45.8333333333%;position:relative}.el-col-lg-12{width:50%}.el-col-lg-offset-12{margin-left:50%}.el-col-lg-pull-12{position:relative;right:50%}.el-col-lg-push-12{left:50%;position:relative}.el-col-lg-13{width:54.1666666667%}.el-col-lg-offset-13{margin-left:54.1666666667%}.el-col-lg-pull-13{position:relative;right:54.1666666667%}.el-col-lg-push-13{left:54.1666666667%;position:relative}.el-col-lg-14{width:58.3333333333%}.el-col-lg-offset-14{margin-left:58.3333333333%}.el-col-lg-pull-14{position:relative;right:58.3333333333%}.el-col-lg-push-14{left:58.3333333333%;position:relative}.el-col-lg-15{width:62.5%}.el-col-lg-offset-15{margin-left:62.5%}.el-col-lg-pull-15{position:relative;right:62.5%}.el-col-lg-push-15{left:62.5%;position:relative}.el-col-lg-16{width:66.6666666667%}.el-col-lg-offset-16{margin-left:66.6666666667%}.el-col-lg-pull-16{position:relative;right:66.6666666667%}.el-col-lg-push-16{left:66.6666666667%;position:relative}.el-col-lg-17{width:70.8333333333%}.el-col-lg-offset-17{margin-left:70.8333333333%}.el-col-lg-pull-17{position:relative;right:70.8333333333%}.el-col-lg-push-17{left:70.8333333333%;position:relative}.el-col-lg-18{width:75%}.el-col-lg-offset-18{margin-left:75%}.el-col-lg-pull-18{position:relative;right:75%}.el-col-lg-push-18{left:75%;position:relative}.el-col-lg-19{width:79.1666666667%}.el-col-lg-offset-19{margin-left:79.1666666667%}.el-col-lg-pull-19{position:relative;right:79.1666666667%}.el-col-lg-push-19{left:79.1666666667%;position:relative}.el-col-lg-20{width:83.3333333333%}.el-col-lg-offset-20{margin-left:83.3333333333%}.el-col-lg-pull-20{position:relative;right:83.3333333333%}.el-col-lg-push-20{left:83.3333333333%;position:relative}.el-col-lg-21{width:87.5%}.el-col-lg-offset-21{margin-left:87.5%}.el-col-lg-pull-21{position:relative;right:87.5%}.el-col-lg-push-21{left:87.5%;position:relative}.el-col-lg-22{width:91.6666666667%}.el-col-lg-offset-22{margin-left:91.6666666667%}.el-col-lg-pull-22{position:relative;right:91.6666666667%}.el-col-lg-push-22{left:91.6666666667%;position:relative}.el-col-lg-23{width:95.8333333333%}.el-col-lg-offset-23{margin-left:95.8333333333%}.el-col-lg-pull-23{position:relative;right:95.8333333333%}.el-col-lg-push-23{left:95.8333333333%;position:relative}.el-col-lg-24{width:100%}.el-col-lg-offset-24{margin-left:100%}.el-col-lg-pull-24{position:relative;right:100%}.el-col-lg-push-24{left:100%;position:relative}}@media only screen and (min-width:1920px){.el-col-xl-0{display:none;width:0}.el-col-xl-offset-0{margin-left:0}.el-col-xl-pull-0{position:relative;right:0}.el-col-xl-push-0{left:0;position:relative}.el-col-xl-1{width:4.1666666667%}.el-col-xl-offset-1{margin-left:4.1666666667%}.el-col-xl-pull-1{position:relative;right:4.1666666667%}.el-col-xl-push-1{left:4.1666666667%;position:relative}.el-col-xl-2{width:8.3333333333%}.el-col-xl-offset-2{margin-left:8.3333333333%}.el-col-xl-pull-2{position:relative;right:8.3333333333%}.el-col-xl-push-2{left:8.3333333333%;position:relative}.el-col-xl-3{width:12.5%}.el-col-xl-offset-3{margin-left:12.5%}.el-col-xl-pull-3{position:relative;right:12.5%}.el-col-xl-push-3{left:12.5%;position:relative}.el-col-xl-4{width:16.6666666667%}.el-col-xl-offset-4{margin-left:16.6666666667%}.el-col-xl-pull-4{position:relative;right:16.6666666667%}.el-col-xl-push-4{left:16.6666666667%;position:relative}.el-col-xl-5{width:20.8333333333%}.el-col-xl-offset-5{margin-left:20.8333333333%}.el-col-xl-pull-5{position:relative;right:20.8333333333%}.el-col-xl-push-5{left:20.8333333333%;position:relative}.el-col-xl-6{width:25%}.el-col-xl-offset-6{margin-left:25%}.el-col-xl-pull-6{position:relative;right:25%}.el-col-xl-push-6{left:25%;position:relative}.el-col-xl-7{width:29.1666666667%}.el-col-xl-offset-7{margin-left:29.1666666667%}.el-col-xl-pull-7{position:relative;right:29.1666666667%}.el-col-xl-push-7{left:29.1666666667%;position:relative}.el-col-xl-8{width:33.3333333333%}.el-col-xl-offset-8{margin-left:33.3333333333%}.el-col-xl-pull-8{position:relative;right:33.3333333333%}.el-col-xl-push-8{left:33.3333333333%;position:relative}.el-col-xl-9{width:37.5%}.el-col-xl-offset-9{margin-left:37.5%}.el-col-xl-pull-9{position:relative;right:37.5%}.el-col-xl-push-9{left:37.5%;position:relative}.el-col-xl-10{width:41.6666666667%}.el-col-xl-offset-10{margin-left:41.6666666667%}.el-col-xl-pull-10{position:relative;right:41.6666666667%}.el-col-xl-push-10{left:41.6666666667%;position:relative}.el-col-xl-11{width:45.8333333333%}.el-col-xl-offset-11{margin-left:45.8333333333%}.el-col-xl-pull-11{position:relative;right:45.8333333333%}.el-col-xl-push-11{left:45.8333333333%;position:relative}.el-col-xl-12{width:50%}.el-col-xl-offset-12{margin-left:50%}.el-col-xl-pull-12{position:relative;right:50%}.el-col-xl-push-12{left:50%;position:relative}.el-col-xl-13{width:54.1666666667%}.el-col-xl-offset-13{margin-left:54.1666666667%}.el-col-xl-pull-13{position:relative;right:54.1666666667%}.el-col-xl-push-13{left:54.1666666667%;position:relative}.el-col-xl-14{width:58.3333333333%}.el-col-xl-offset-14{margin-left:58.3333333333%}.el-col-xl-pull-14{position:relative;right:58.3333333333%}.el-col-xl-push-14{left:58.3333333333%;position:relative}.el-col-xl-15{width:62.5%}.el-col-xl-offset-15{margin-left:62.5%}.el-col-xl-pull-15{position:relative;right:62.5%}.el-col-xl-push-15{left:62.5%;position:relative}.el-col-xl-16{width:66.6666666667%}.el-col-xl-offset-16{margin-left:66.6666666667%}.el-col-xl-pull-16{position:relative;right:66.6666666667%}.el-col-xl-push-16{left:66.6666666667%;position:relative}.el-col-xl-17{width:70.8333333333%}.el-col-xl-offset-17{margin-left:70.8333333333%}.el-col-xl-pull-17{position:relative;right:70.8333333333%}.el-col-xl-push-17{left:70.8333333333%;position:relative}.el-col-xl-18{width:75%}.el-col-xl-offset-18{margin-left:75%}.el-col-xl-pull-18{position:relative;right:75%}.el-col-xl-push-18{left:75%;position:relative}.el-col-xl-19{width:79.1666666667%}.el-col-xl-offset-19{margin-left:79.1666666667%}.el-col-xl-pull-19{position:relative;right:79.1666666667%}.el-col-xl-push-19{left:79.1666666667%;position:relative}.el-col-xl-20{width:83.3333333333%}.el-col-xl-offset-20{margin-left:83.3333333333%}.el-col-xl-pull-20{position:relative;right:83.3333333333%}.el-col-xl-push-20{left:83.3333333333%;position:relative}.el-col-xl-21{width:87.5%}.el-col-xl-offset-21{margin-left:87.5%}.el-col-xl-pull-21{position:relative;right:87.5%}.el-col-xl-push-21{left:87.5%;position:relative}.el-col-xl-22{width:91.6666666667%}.el-col-xl-offset-22{margin-left:91.6666666667%}.el-col-xl-pull-22{position:relative;right:91.6666666667%}.el-col-xl-push-22{left:91.6666666667%;position:relative}.el-col-xl-23{width:95.8333333333%}.el-col-xl-offset-23{margin-left:95.8333333333%}.el-col-xl-pull-23{position:relative;right:95.8333333333%}.el-col-xl-push-23{left:95.8333333333%;position:relative}.el-col-xl-24{width:100%}.el-col-xl-offset-24{margin-left:100%}.el-col-xl-pull-24{position:relative;right:100%}.el-col-xl-push-24{left:100%;position:relative}}.el-upload{cursor:pointer;display:inline-block;outline:none;text-align:center}.el-upload__input{display:none}.el-upload__tip{color:#606266;font-size:12px;margin-top:7px}.el-upload iframe{filter:alpha(opacity=0);left:0;opacity:0;position:absolute;top:0;z-index:-1}.el-upload--picture-card{background-color:#fbfdff;border:1px dashed #c0ccda;border-radius:6px;box-sizing:border-box;cursor:pointer;height:148px;line-height:146px;vertical-align:top;width:148px}.el-upload--picture-card i{color:#8c939d;font-size:28px}.el-upload--picture-card:hover,.el-upload:focus{border-color:#1a7efb;color:#1a7efb}.el-upload:focus .el-upload-dragger{border-color:#1a7efb}.el-upload-dragger{background-color:#fff;border:1px dashed #d9d9d9;border-radius:6px;box-sizing:border-box;cursor:pointer;height:180px;overflow:hidden;position:relative;text-align:center;width:360px}.el-upload-dragger .el-icon-upload{color:#afb3ba;font-size:67px;line-height:50px;margin:40px 0 16px}.el-upload-dragger+.el-upload__tip{text-align:center}.el-upload-dragger~.el-upload__files{border-top:1px solid #dadbdd;margin-top:7px;padding-top:5px}.el-upload-dragger .el-upload__text{color:#606266;font-size:14px;text-align:center}.el-upload-dragger .el-upload__text em{color:#1a7efb;font-style:normal}.el-upload-dragger:hover{border-color:#1a7efb}.el-upload-dragger.is-dragover{background-color:rgba(32,159,255,.06);border:2px dashed #1a7efb}.el-upload-list{list-style:none;margin:0;padding:0}.el-upload-list__item{border-radius:4px;box-sizing:border-box;color:#606266;font-size:14px;line-height:1.8;margin-top:5px;position:relative;transition:all .5s cubic-bezier(.55,0,.1,1);width:100%}.el-upload-list__item .el-progress{position:absolute;top:20px;width:100%}.el-upload-list__item .el-progress__text{position:absolute;right:0;top:-13px}.el-upload-list__item .el-progress-bar{margin-right:0;padding-right:0}.el-upload-list__item:first-child{margin-top:10px}.el-upload-list__item .el-icon-upload-success{color:#00b27f}.el-upload-list__item .el-icon-close{color:#606266;cursor:pointer;display:none;opacity:.75;position:absolute;right:5px;top:5px}.el-upload-list__item .el-icon-close:hover{opacity:1}.el-upload-list__item .el-icon-close-tip{color:#1a7efb;cursor:pointer;display:none;font-size:12px;opacity:1;position:absolute;right:5px;top:5px}.el-upload-list__item:hover{background-color:#f5f7fa}.el-upload-list__item:hover .el-icon-close{display:inline-block}.el-upload-list__item:hover .el-progress__text{display:none}.el-upload-list__item.is-success .el-upload-list__item-status-label{display:block}.el-upload-list__item.is-success .el-upload-list__item-name:focus,.el-upload-list__item.is-success .el-upload-list__item-name:hover{color:#1a7efb;cursor:pointer}.el-upload-list__item.is-success:focus:not(:hover) .el-icon-close-tip{display:inline-block}.el-upload-list__item.is-success:active,.el-upload-list__item.is-success:not(.focusing):focus{outline-width:0}.el-upload-list__item.is-success:active .el-icon-close-tip,.el-upload-list__item.is-success:focus .el-upload-list__item-status-label,.el-upload-list__item.is-success:hover .el-upload-list__item-status-label,.el-upload-list__item.is-success:not(.focusing):focus .el-icon-close-tip{display:none}.el-upload-list.is-disabled .el-upload-list__item:hover .el-upload-list__item-status-label{display:block}.el-upload-list__item-name{color:#606266;display:block;margin-right:40px;overflow:hidden;padding-left:4px;text-overflow:ellipsis;transition:color .3s;white-space:nowrap}.el-upload-list__item-name [class^=el-icon]{color:#909399;height:100%;line-height:inherit;margin-right:7px}.el-upload-list__item-status-label{display:none;line-height:inherit;position:absolute;right:5px;top:0}.el-upload-list__item-delete{color:#606266;display:none;font-size:12px;position:absolute;right:10px;top:0}.el-upload-list__item-delete:hover{color:#1a7efb}.el-upload-list--picture-card{display:inline;margin:0;vertical-align:top}.el-upload-list--picture-card .el-upload-list__item{background-color:#fff;border:1px solid #c0ccda;border-radius:6px;box-sizing:border-box;display:inline-block;height:148px;margin:0 8px 8px 0;overflow:hidden;width:148px}.el-upload-list--picture-card .el-upload-list__item .el-icon-check,.el-upload-list--picture-card .el-upload-list__item .el-icon-circle-check{color:#fff}.el-upload-list--picture-card .el-upload-list__item .el-icon-close,.el-upload-list--picture-card .el-upload-list__item:hover .el-upload-list__item-status-label{display:none}.el-upload-list--picture-card .el-upload-list__item:hover .el-progress__text{display:block}.el-upload-list--picture-card .el-upload-list__item-name{display:none}.el-upload-list--picture-card .el-upload-list__item-thumbnail{height:100%;width:100%}.el-upload-list--picture-card .el-upload-list__item-status-label{background:#13ce66;box-shadow:0 0 1pc 1px rgba(0,0,0,.2);height:24px;position:absolute;right:-15px;text-align:center;top:-6px;transform:rotate(45deg);width:40px}.el-upload-list--picture-card .el-upload-list__item-status-label i{font-size:12px;margin-top:11px;transform:rotate(-45deg)}.el-upload-list--picture-card .el-upload-list__item-actions{background-color:rgba(0,0,0,.5);color:#fff;cursor:default;font-size:20px;height:100%;left:0;opacity:0;position:absolute;text-align:center;top:0;transition:opacity .3s;width:100%}.el-upload-list--picture-card .el-upload-list__item-actions:after{content:"";display:inline-block;height:100%;vertical-align:middle}.el-upload-list--picture-card .el-upload-list__item-actions span{cursor:pointer;display:none}.el-upload-list--picture-card .el-upload-list__item-actions span+span{margin-left:15px}.el-upload-list--picture-card .el-upload-list__item-actions .el-upload-list__item-delete{color:inherit;font-size:inherit;position:static}.el-upload-list--picture-card .el-upload-list__item-actions:hover{opacity:1}.el-upload-list--picture-card .el-upload-list__item-actions:hover span{display:inline-block}.el-upload-list--picture-card .el-progress{bottom:auto;left:50%;top:50%;transform:translate(-50%,-50%);width:126px}.el-upload-list--picture-card .el-progress .el-progress__text{top:50%}.el-upload-list--picture .el-upload-list__item{background-color:#fff;border:1px solid #c0ccda;border-radius:6px;box-sizing:border-box;height:92px;margin-top:10px;overflow:hidden;padding:10px 10px 10px 90px;z-index:0}.el-upload-list--picture .el-upload-list__item .el-icon-check,.el-upload-list--picture .el-upload-list__item .el-icon-circle-check{color:#fff}.el-upload-list--picture .el-upload-list__item:hover .el-upload-list__item-status-label{background:transparent;box-shadow:none;right:-12px;top:-2px}.el-upload-list--picture .el-upload-list__item:hover .el-progress__text{display:block}.el-upload-list--picture .el-upload-list__item.is-success .el-upload-list__item-name{line-height:70px;margin-top:0}.el-upload-list--picture .el-upload-list__item.is-success .el-upload-list__item-name i{display:none}.el-upload-list--picture .el-upload-list__item-thumbnail{background-color:#fff;display:inline-block;float:left;height:70px;margin-left:-80px;position:relative;vertical-align:middle;width:70px;z-index:1}.el-upload-list--picture .el-upload-list__item-name{display:block;margin-top:20px}.el-upload-list--picture .el-upload-list__item-name i{font-size:70px;left:9px;line-height:1;position:absolute;top:10px}.el-upload-list--picture .el-upload-list__item-status-label{background:#13ce66;box-shadow:0 1px 1px #ccc;height:26px;position:absolute;right:-17px;text-align:center;top:-7px;transform:rotate(45deg);width:46px}.el-upload-list--picture .el-upload-list__item-status-label i{font-size:12px;margin-top:12px;transform:rotate(-45deg)}.el-upload-list--picture .el-progress{position:relative;top:-7px}.el-upload-cover{cursor:default;height:100%;left:0;overflow:hidden;position:absolute;top:0;width:100%;z-index:10}.el-upload-cover:after{content:"";display:inline-block;height:100%;vertical-align:middle}.el-upload-cover img{display:block;height:100%;width:100%}.el-upload-cover__label{background:#13ce66;box-shadow:0 0 1pc 1px rgba(0,0,0,.2);height:24px;position:absolute;right:-15px;text-align:center;top:-6px;transform:rotate(45deg);width:40px}.el-upload-cover__label i{color:#fff;font-size:12px;margin-top:11px;transform:rotate(-45deg)}.el-upload-cover__progress{display:inline-block;position:static;vertical-align:middle;width:243px}.el-upload-cover__progress+.el-upload__inner{opacity:0}.el-upload-cover__content{height:100%;left:0;position:absolute;top:0;width:100%}.el-upload-cover__interact{background-color:rgba(0,0,0,.72);bottom:0;height:100%;left:0;position:absolute;text-align:center;width:100%}.el-upload-cover__interact .btn{color:#fff;cursor:pointer;display:inline-block;font-size:14px;margin-top:60px;transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1);vertical-align:middle}.el-upload-cover__interact .btn i{margin-top:0}.el-upload-cover__interact .btn span{opacity:0;transition:opacity .15s linear}.el-upload-cover__interact .btn:not(:first-child){margin-left:35px}.el-upload-cover__interact .btn:hover{transform:translateY(-13px)}.el-upload-cover__interact .btn:hover span{opacity:1}.el-upload-cover__interact .btn i{color:#fff;display:block;font-size:24px;line-height:inherit;margin:0 auto 5px}.el-upload-cover__title{background-color:#fff;bottom:0;color:#303133;font-size:14px;font-weight:400;height:36px;left:0;line-height:36px;margin:0;overflow:hidden;padding:0 10px;position:absolute;text-align:left;text-overflow:ellipsis;white-space:nowrap;width:100%}.el-upload-cover+.el-upload__inner{opacity:0;position:relative;z-index:1}.el-progress{line-height:1;position:relative}.el-progress__text{color:#606266;display:inline-block;font-size:14px;line-height:1;margin-left:10px;vertical-align:middle}.el-progress__text i{display:block;vertical-align:middle}.el-progress--circle,.el-progress--dashboard{display:inline-block}.el-progress--circle .el-progress__text,.el-progress--dashboard .el-progress__text{left:0;margin:0;position:absolute;text-align:center;top:50%;transform:translateY(-50%);width:100%}.el-progress--circle .el-progress__text i,.el-progress--dashboard .el-progress__text i{display:inline-block;vertical-align:middle}.el-progress--without-text .el-progress__text{display:none}.el-progress--without-text .el-progress-bar{display:block;margin-right:0;padding-right:0}.el-progress--text-inside .el-progress-bar{margin-right:0;padding-right:0}.el-progress.is-success .el-progress-bar__inner{background-color:#00b27f}.el-progress.is-success .el-progress__text{color:#00b27f}.el-progress.is-warning .el-progress-bar__inner{background-color:#fcbe2d}.el-progress.is-warning .el-progress__text{color:#fcbe2d}.el-progress.is-exception .el-progress-bar__inner{background-color:#ff6154}.el-progress.is-exception .el-progress__text{color:#ff6154}.el-progress-bar{box-sizing:border-box;display:inline-block;margin-right:-55px;padding-right:50px;vertical-align:middle;width:100%}.el-progress-bar__outer{background-color:#ebeef5;border-radius:100px;height:6px;overflow:hidden;position:relative;vertical-align:middle}.el-progress-bar__inner{background-color:#1a7efb;border-radius:100px;height:100%;left:0;line-height:1;position:absolute;text-align:right;top:0;transition:width .6s ease;white-space:nowrap}.el-progress-bar__inner:after{content:"";display:inline-block;height:100%;vertical-align:middle}.el-progress-bar__innerText{color:#fff;display:inline-block;font-size:12px;margin:0 5px;vertical-align:middle}@keyframes progress{0%{background-position:0 0}to{background-position:32px 0}}.el-time-spinner{white-space:nowrap;width:100%}.el-spinner{display:inline-block;vertical-align:middle}.el-spinner-inner{animation:rotate 2s linear infinite;height:50px;width:50px}.el-spinner-inner .path{stroke:#ececec;stroke-linecap:round;animation:dash 1.5s ease-in-out infinite}@keyframes rotate{to{transform:rotate(1turn)}}@keyframes dash{0%{stroke-dasharray:1,150;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-35}to{stroke-dasharray:90,150;stroke-dashoffset:-124}}.el-message{align-items:center;background-color:#edf2fc;border:1px solid #ebeef5;border-radius:7px;box-sizing:border-box;display:flex;left:50%;min-width:380px;overflow:hidden;padding:15px 15px 15px 20px;position:fixed;top:20px;transform:translateX(-50%);transition:opacity .3s,transform .4s,top .4s}.el-message.is-center{justify-content:center}.el-message.is-closable .el-message__content{padding-right:16px}.el-message p{margin:0}.el-message--info .el-message__content{color:#4b4c4d}.el-message--success{background-color:#e6ffeb;border-color:#ccf0e5}.el-message--success .el-message__content{color:#00b27f}.el-message--warning{background-color:#fff9ea;border-color:#fef2d5}.el-message--warning .el-message__content{color:#fcbe2d}.el-message--error{background-color:#ffefee;border-color:#ffdfdd}.el-message--error .el-message__content{color:#ff6154}.el-message__icon{margin-right:10px}.el-message__content{font-size:14px;line-height:1;padding:0}.el-message__content:focus{outline-width:0}.el-message__closeBtn{color:#afb3ba;cursor:pointer;font-size:16px;position:absolute;right:15px;top:50%;transform:translateY(-50%)}.el-message__closeBtn:focus{outline-width:0}.el-message__closeBtn:hover{color:#909399}.el-message .el-icon-success{color:#00b27f}.el-message .el-icon-error{color:#ff6154}.el-message .el-icon-info{color:#4b4c4d}.el-message .el-icon-warning{color:#fcbe2d}.el-message-fade-enter,.el-message-fade-leave-active{opacity:0;transform:translate(-50%,-100%)}.el-badge{display:inline-block;position:relative;vertical-align:middle}.el-badge__content{background-color:#ff6154;border:1px solid #fff;border-radius:10px;color:#fff;display:inline-block;font-size:12px;height:18px;line-height:18px;padding:0 6px;text-align:center;white-space:nowrap}.el-badge__content.is-fixed{position:absolute;right:10px;top:0;transform:translateY(-50%) translateX(100%)}.el-badge__content.is-fixed.is-dot{right:5px}.el-badge__content.is-dot{border-radius:50%;height:8px;padding:0;right:0;width:8px}.el-badge__content--primary{background-color:#1a7efb}.el-badge__content--success{background-color:#00b27f}.el-badge__content--warning{background-color:#fcbe2d}.el-badge__content--info{background-color:#4b4c4d}.el-badge__content--danger{background-color:#ff6154}.el-card{background-color:#fff;border:1px solid #ebeef5;border-radius:4px;color:#303133;overflow:hidden;transition:.3s}.el-card.is-always-shadow,.el-card.is-hover-shadow:focus,.el-card.is-hover-shadow:hover{box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.el-card__header{border-bottom:1px solid #ebeef5;box-sizing:border-box;padding:18px 20px}.el-card__body{padding:20px}.el-rate{height:20px;line-height:1}.el-rate:active,.el-rate:focus{outline-width:0}.el-rate__item{font-size:0;vertical-align:middle}.el-rate__icon,.el-rate__item{display:inline-block;position:relative}.el-rate__icon{color:#afb3ba;font-size:18px;margin-right:6px;transition:.3s}.el-rate__icon.hover{transform:scale(1.15)}.el-rate__decimal,.el-rate__icon .path2{left:0;position:absolute;top:0}.el-rate__decimal{display:inline-block;overflow:hidden}.el-rate__text{font-size:14px;vertical-align:middle}.el-steps{display:flex}.el-steps--simple{background:#f5f7fa;border-radius:4px;padding:13px 8%}.el-steps--horizontal{white-space:nowrap}.el-steps--vertical{flex-flow:column;height:100%}.el-step{flex-shrink:1;position:relative}.el-step:last-of-type .el-step__line{display:none}.el-step:last-of-type.is-flex{flex-basis:auto!important;flex-grow:0;flex-shrink:0}.el-step:last-of-type .el-step__description,.el-step:last-of-type .el-step__main{padding-right:0}.el-step__head{position:relative;width:100%}.el-step__head.is-process{border-color:#303133;color:#303133}.el-step__head.is-wait{border-color:#afb3ba;color:#afb3ba}.el-step__head.is-success{border-color:#00b27f;color:#00b27f}.el-step__head.is-error{border-color:#ff6154;color:#ff6154}.el-step__head.is-finish{border-color:#1a7efb;color:#1a7efb}.el-step__icon{align-items:center;background:#fff;box-sizing:border-box;display:inline-flex;font-size:14px;height:24px;justify-content:center;position:relative;transition:.15s ease-out;width:24px;z-index:1}.el-step__icon.is-text{border:2px solid;border-color:inherit;border-radius:50%}.el-step__icon.is-icon{width:40px}.el-step__icon-inner{color:inherit;display:inline-block;font-weight:700;line-height:1;text-align:center;-webkit-user-select:none;-moz-user-select:none;user-select:none}.el-step__icon-inner[class*=el-icon]:not(.is-status){font-size:25px;font-weight:400}.el-step__icon-inner.is-status{transform:translateY(1px)}.el-step__line{background-color:#afb3ba;border-color:inherit;position:absolute}.el-step__line-inner{border:1px solid;border-color:inherit;box-sizing:border-box;display:block;height:0;transition:.15s ease-out;width:0}.el-step__main{text-align:left;white-space:normal}.el-step__title{font-size:16px;line-height:38px}.el-step__title.is-process{color:#303133;font-weight:700}.el-step__title.is-wait{color:#afb3ba}.el-step__title.is-success{color:#00b27f}.el-step__title.is-error{color:#ff6154}.el-step__title.is-finish{color:#1a7efb}.el-step__description{font-size:12px;font-weight:400;line-height:20px;margin-top:-5px;padding-right:10%}.el-step__description.is-process{color:#303133}.el-step__description.is-wait{color:#afb3ba}.el-step__description.is-success{color:#00b27f}.el-step__description.is-error{color:#ff6154}.el-step__description.is-finish{color:#1a7efb}.el-step.is-horizontal{display:inline-block}.el-step.is-horizontal .el-step__line{height:2px;left:0;right:0;top:11px}.el-step.is-vertical{display:flex}.el-step.is-vertical .el-step__head{flex-grow:0;width:24px}.el-step.is-vertical .el-step__main{flex-grow:1;padding-left:10px}.el-step.is-vertical .el-step__title{line-height:24px;padding-bottom:8px}.el-step.is-vertical .el-step__line{bottom:0;left:11px;top:0;width:2px}.el-step.is-vertical .el-step__icon.is-icon{width:24px}.el-step.is-center .el-step__head,.el-step.is-center .el-step__main{text-align:center}.el-step.is-center .el-step__description{padding-left:20%;padding-right:20%}.el-step.is-center .el-step__line{left:50%;right:-50%}.el-step.is-simple{align-items:center;display:flex}.el-step.is-simple .el-step__head{font-size:0;padding-right:10px;width:auto}.el-step.is-simple .el-step__icon{background:transparent;font-size:12px;height:16px;width:16px}.el-step.is-simple .el-step__icon-inner[class*=el-icon]:not(.is-status){font-size:18px}.el-step.is-simple .el-step__icon-inner.is-status{transform:scale(.8) translateY(1px)}.el-step.is-simple .el-step__main{align-items:stretch;display:flex;flex-grow:1;position:relative}.el-step.is-simple .el-step__title{font-size:16px;line-height:20px}.el-step.is-simple:not(:last-of-type) .el-step__title{max-width:50%;word-break:break-all}.el-step.is-simple .el-step__arrow{align-items:center;display:flex;flex-grow:1;justify-content:center}.el-step.is-simple .el-step__arrow:after,.el-step.is-simple .el-step__arrow:before{background:#afb3ba;content:"";display:inline-block;height:15px;position:absolute;width:1px}.el-step.is-simple .el-step__arrow:before{transform:rotate(-45deg) translateY(-4px);transform-origin:0 0}.el-step.is-simple .el-step__arrow:after{transform:rotate(45deg) translateY(4px);transform-origin:100% 100%}.el-step.is-simple:last-of-type .el-step__arrow{display:none}.el-carousel{position:relative}.el-carousel--horizontal{overflow-x:hidden}.el-carousel--vertical{overflow-y:hidden}.el-carousel__container{height:300px;position:relative}.el-carousel__arrow{background-color:rgba(31,45,61,.11);border:none;border-radius:50%;color:#fff;cursor:pointer;font-size:12px;height:36px;margin:0;outline:none;padding:0;position:absolute;text-align:center;top:50%;transform:translateY(-50%);transition:.3s;width:36px;z-index:10}.el-carousel__arrow--left{left:16px}.el-carousel__arrow--right{right:16px}.el-carousel__arrow:hover{background-color:rgba(31,45,61,.23)}.el-carousel__arrow i{cursor:pointer}.el-carousel__indicators{list-style:none;margin:0;padding:0;position:absolute;z-index:2}.el-carousel__indicators--horizontal{bottom:0;left:50%;transform:translateX(-50%)}.el-carousel__indicators--vertical{right:0;top:50%;transform:translateY(-50%)}.el-carousel__indicators--outside{bottom:26px;position:static;text-align:center;transform:none}.el-carousel__indicators--outside .el-carousel__indicator:hover button{opacity:.64}.el-carousel__indicators--outside button{background-color:#afb3ba;opacity:.24}.el-carousel__indicators--labels{left:0;right:0;text-align:center;transform:none}.el-carousel__indicators--labels .el-carousel__button{font-size:12px;height:auto;padding:2px 18px;width:auto}.el-carousel__indicators--labels .el-carousel__indicator{padding:6px 4px}.el-carousel__indicator{background-color:transparent;cursor:pointer}.el-carousel__indicator:hover button{opacity:.72}.el-carousel__indicator--horizontal{display:inline-block;padding:12px 4px}.el-carousel__indicator--vertical{padding:4px 12px}.el-carousel__indicator--vertical .el-carousel__button{height:15px;width:2px}.el-carousel__indicator.is-active button{opacity:1}.el-carousel__button{background-color:#fff;border:none;cursor:pointer;display:block;height:2px;margin:0;opacity:.48;outline:none;padding:0;transition:.3s;width:30px}.carousel-arrow-left-enter,.carousel-arrow-left-leave-active{opacity:0;transform:translateY(-50%) translateX(-10px)}.carousel-arrow-right-enter,.carousel-arrow-right-leave-active{opacity:0;transform:translateY(-50%) translateX(10px)}.el-carousel__item{display:inline-block;height:100%;left:0;overflow:hidden;position:absolute;top:0;width:100%;z-index:0}.el-carousel__item.is-active{z-index:2}.el-carousel__item--card,.el-carousel__item.is-animating{transition:transform .4s ease-in-out}.el-carousel__item--card{width:50%}.el-carousel__item--card.is-in-stage{cursor:pointer;z-index:1}.el-carousel__item--card.is-in-stage.is-hover .el-carousel__mask,.el-carousel__item--card.is-in-stage:hover .el-carousel__mask{opacity:.12}.el-carousel__item--card.is-active{z-index:2}.el-carousel__mask{background-color:#fff;height:100%;left:0;opacity:.24;position:absolute;top:0;transition:.2s;width:100%}.fade-in-linear-enter-active,.fade-in-linear-leave-active{transition:opacity .2s linear}.fade-in-linear-enter,.fade-in-linear-leave,.fade-in-linear-leave-active{opacity:0}.el-fade-in-linear-enter-active,.el-fade-in-linear-leave-active{transition:opacity .2s linear}.el-fade-in-linear-enter,.el-fade-in-linear-leave,.el-fade-in-linear-leave-active{opacity:0}.el-fade-in-enter-active,.el-fade-in-leave-active{transition:all .3s cubic-bezier(.55,0,.1,1)}.el-fade-in-enter,.el-fade-in-leave-active{opacity:0}.el-zoom-in-center-enter-active,.el-zoom-in-center-leave-active{transition:all .3s cubic-bezier(.55,0,.1,1)}.el-zoom-in-center-enter,.el-zoom-in-center-leave-active{opacity:0;transform:scaleX(0)}.el-zoom-in-top-enter-active,.el-zoom-in-top-leave-active{opacity:1;transform:scaleY(1);transform-origin:center top;transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1)}.el-zoom-in-top-enter,.el-zoom-in-top-leave-active{opacity:0;transform:scaleY(0)}.el-zoom-in-bottom-enter-active,.el-zoom-in-bottom-leave-active{opacity:1;transform:scaleY(1);transform-origin:center bottom;transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1)}.el-zoom-in-bottom-enter,.el-zoom-in-bottom-leave-active{opacity:0;transform:scaleY(0)}.el-zoom-in-left-enter-active,.el-zoom-in-left-leave-active{opacity:1;transform:scale(1);transform-origin:top left;transition:transform .3s cubic-bezier(.23,1,.32,1),opacity .3s cubic-bezier(.23,1,.32,1)}.el-zoom-in-left-enter,.el-zoom-in-left-leave-active{opacity:0;transform:scale(.45)}.collapse-transition{transition:height .3s ease-in-out,padding-top .3s ease-in-out,padding-bottom .3s ease-in-out}.horizontal-collapse-transition{transition:width .3s ease-in-out,padding-left .3s ease-in-out,padding-right .3s ease-in-out}.el-list-enter-active,.el-list-leave-active{transition:all 1s}.el-list-enter,.el-list-leave-active{opacity:0;transform:translateY(-30px)}.el-opacity-transition{transition:opacity .3s cubic-bezier(.55,0,.1,1)}.el-collapse{border-bottom:1px solid #ebeef5;border-top:1px solid #ebeef5}.el-collapse-item.is-disabled .el-collapse-item__header{color:#bbb;cursor:not-allowed}.el-collapse-item__header{align-items:center;background-color:#fff;border-bottom:1px solid #ebeef5;color:#303133;cursor:pointer;display:flex;font-size:13px;font-weight:500;height:48px;line-height:48px;outline:none;transition:border-bottom-color .3s}.el-collapse-item__arrow{font-weight:300;margin:0 8px 0 auto;transition:transform .3s}.el-collapse-item__arrow.is-active{transform:rotate(90deg)}.el-collapse-item__header.focusing:focus:not(:hover){color:#1a7efb}.el-collapse-item__header.is-active{border-bottom-color:transparent}.el-collapse-item__wrap{background-color:#fff;border-bottom:1px solid #ebeef5;box-sizing:border-box;overflow:hidden;will-change:height}.el-collapse-item__content{color:#303133;font-size:13px;line-height:1.7692307692;padding-bottom:25px}.el-collapse-item:last-child{margin-bottom:-1px}.el-popper .popper__arrow,.el-popper .popper__arrow:after{border-color:transparent;border-style:solid;display:block;height:0;position:absolute;width:0}.el-popper .popper__arrow{border-width:6px;filter:drop-shadow(0 2px 12px rgba(0,0,0,.03))}.el-popper .popper__arrow:after{border-width:6px;content:" "}.el-popper[x-placement^=top]{margin-bottom:12px}.el-popper[x-placement^=top] .popper__arrow{border-bottom-width:0;border-top-color:#ebeef5;bottom:-6px;left:50%;margin-right:3px}.el-popper[x-placement^=top] .popper__arrow:after{border-bottom-width:0;border-top-color:#fff;bottom:1px;margin-left:-6px}.el-popper[x-placement^=bottom]{margin-top:12px}.el-popper[x-placement^=bottom] .popper__arrow{border-bottom-color:#ebeef5;border-top-width:0;left:50%;margin-right:3px;top:-6px}.el-popper[x-placement^=bottom] .popper__arrow:after{border-bottom-color:#fff;border-top-width:0;margin-left:-6px;top:1px}.el-popper[x-placement^=right]{margin-left:12px}.el-popper[x-placement^=right] .popper__arrow{border-left-width:0;border-right-color:#ebeef5;left:-6px;margin-bottom:3px;top:50%}.el-popper[x-placement^=right] .popper__arrow:after{border-left-width:0;border-right-color:#fff;bottom:-6px;left:1px}.el-popper[x-placement^=left]{margin-right:12px}.el-popper[x-placement^=left] .popper__arrow{border-left-color:#ebeef5;border-right-width:0;margin-bottom:3px;right:-6px;top:50%}.el-popper[x-placement^=left] .popper__arrow:after{border-left-color:#fff;border-right-width:0;bottom:-6px;margin-left:-6px;right:1px}.el-tag{background-color:#e8f2ff;border:1px solid #d1e5fe;border-radius:4px;box-sizing:border-box;color:#1a7efb;display:inline-block;font-size:12px;height:32px;line-height:30px;padding:0 10px;white-space:nowrap}.el-tag.is-hit{border-color:#1a7efb}.el-tag .el-tag__close{color:#1a7efb}.el-tag .el-tag__close:hover{background-color:#1a7efb;color:#fff}.el-tag.el-tag--info{background-color:#ededed;border-color:#dbdbdb;color:#4b4c4d}.el-tag.el-tag--info.is-hit{border-color:#4b4c4d}.el-tag.el-tag--info .el-tag__close{color:#4b4c4d}.el-tag.el-tag--info .el-tag__close:hover{background-color:#4b4c4d;color:#fff}.el-tag.el-tag--success{background-color:#e6f7f2;border-color:#ccf0e5;color:#00b27f}.el-tag.el-tag--success.is-hit{border-color:#00b27f}.el-tag.el-tag--success .el-tag__close{color:#00b27f}.el-tag.el-tag--success .el-tag__close:hover{background-color:#00b27f;color:#fff}.el-tag.el-tag--warning{background-color:#fff9ea;border-color:#fef2d5;color:#fcbe2d}.el-tag.el-tag--warning.is-hit{border-color:#fcbe2d}.el-tag.el-tag--warning .el-tag__close{color:#fcbe2d}.el-tag.el-tag--warning .el-tag__close:hover{background-color:#fcbe2d;color:#fff}.el-tag.el-tag--danger{background-color:#ffefee;border-color:#ffdfdd;color:#ff6154}.el-tag.el-tag--danger.is-hit{border-color:#ff6154}.el-tag.el-tag--danger .el-tag__close{color:#ff6154}.el-tag.el-tag--danger .el-tag__close:hover{background-color:#ff6154;color:#fff}.el-tag .el-icon-close{border-radius:50%;cursor:pointer;font-size:12px;height:16px;line-height:16px;position:relative;right:-5px;text-align:center;top:-1px;vertical-align:middle;width:16px}.el-tag .el-icon-close:before{display:block}.el-tag--dark{background-color:#1a7efb;color:#fff}.el-tag--dark,.el-tag--dark.is-hit{border-color:#1a7efb}.el-tag--dark .el-tag__close{color:#fff}.el-tag--dark .el-tag__close:hover{background-color:#4898fc;color:#fff}.el-tag--dark.el-tag--info{background-color:#4b4c4d;border-color:#4b4c4d;color:#fff}.el-tag--dark.el-tag--info.is-hit{border-color:#4b4c4d}.el-tag--dark.el-tag--info .el-tag__close{color:#fff}.el-tag--dark.el-tag--info .el-tag__close:hover{background-color:#6f7071;color:#fff}.el-tag--dark.el-tag--success{background-color:#00b27f;border-color:#00b27f;color:#fff}.el-tag--dark.el-tag--success.is-hit{border-color:#00b27f}.el-tag--dark.el-tag--success .el-tag__close{color:#fff}.el-tag--dark.el-tag--success .el-tag__close:hover{background-color:#33c199;color:#fff}.el-tag--dark.el-tag--warning{background-color:#fcbe2d;border-color:#fcbe2d;color:#fff}.el-tag--dark.el-tag--warning.is-hit{border-color:#fcbe2d}.el-tag--dark.el-tag--warning .el-tag__close{color:#fff}.el-tag--dark.el-tag--warning .el-tag__close:hover{background-color:#fdcb57;color:#fff}.el-tag--dark.el-tag--danger{background-color:#ff6154;border-color:#ff6154;color:#fff}.el-tag--dark.el-tag--danger.is-hit{border-color:#ff6154}.el-tag--dark.el-tag--danger .el-tag__close{color:#fff}.el-tag--dark.el-tag--danger .el-tag__close:hover{background-color:#ff8176;color:#fff}.el-tag--plain{background-color:#fff;border-color:#a3cbfd;color:#1a7efb}.el-tag--plain.is-hit{border-color:#1a7efb}.el-tag--plain .el-tag__close{color:#1a7efb}.el-tag--plain .el-tag__close:hover{background-color:#1a7efb;color:#fff}.el-tag--plain.el-tag--info{background-color:#fff;border-color:#b7b7b8;color:#4b4c4d}.el-tag--plain.el-tag--info.is-hit{border-color:#4b4c4d}.el-tag--plain.el-tag--info .el-tag__close{color:#4b4c4d}.el-tag--plain.el-tag--info .el-tag__close:hover{background-color:#4b4c4d;color:#fff}.el-tag--plain.el-tag--success{background-color:#fff;border-color:#99e0cc;color:#00b27f}.el-tag--plain.el-tag--success.is-hit{border-color:#00b27f}.el-tag--plain.el-tag--success .el-tag__close{color:#00b27f}.el-tag--plain.el-tag--success .el-tag__close:hover{background-color:#00b27f;color:#fff}.el-tag--plain.el-tag--warning{background-color:#fff;border-color:#fee5ab;color:#fcbe2d}.el-tag--plain.el-tag--warning.is-hit{border-color:#fcbe2d}.el-tag--plain.el-tag--warning .el-tag__close{color:#fcbe2d}.el-tag--plain.el-tag--warning .el-tag__close:hover{background-color:#fcbe2d;color:#fff}.el-tag--plain.el-tag--danger{background-color:#fff;border-color:#ffc0bb;color:#ff6154}.el-tag--plain.el-tag--danger.is-hit{border-color:#ff6154}.el-tag--plain.el-tag--danger .el-tag__close{color:#ff6154}.el-tag--plain.el-tag--danger .el-tag__close:hover{background-color:#ff6154;color:#fff}.el-tag--medium{height:28px;line-height:26px}.el-tag--medium .el-icon-close{transform:scale(.8)}.el-tag--small{height:24px;line-height:22px;padding:0 8px}.el-tag--small .el-icon-close{transform:scale(.8)}.el-tag--mini{height:20px;line-height:19px;padding:0 5px}.el-tag--mini .el-icon-close{margin-left:-3px;transform:scale(.7)}.el-cascader{display:inline-block;font-size:14px;line-height:40px;position:relative}.el-cascader:not(.is-disabled):hover .el-input__inner{border-color:#afb3ba;cursor:pointer}.el-cascader .el-input{cursor:pointer}.el-cascader .el-input .el-input__inner{text-overflow:ellipsis}.el-cascader .el-input .el-input__inner:focus{border-color:#1a7efb}.el-cascader .el-input .el-icon-arrow-down{font-size:14px;transition:transform .3s}.el-cascader .el-input .el-icon-arrow-down.is-reverse{transform:rotate(180deg)}.el-cascader .el-input .el-icon-circle-close:hover{color:#909399}.el-cascader .el-input.is-focus .el-input__inner{border-color:#1a7efb}.el-cascader--medium{font-size:14px;line-height:36px}.el-cascader--small{font-size:13px;line-height:32px}.el-cascader--mini{font-size:12px;line-height:28px}.el-cascader.is-disabled .el-cascader__label{color:#afb3ba;z-index:2}.el-cascader__dropdown{background:#fff;border:1px solid #e4e7ed;border-radius:7px;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);font-size:14px;margin:5px 0}.el-cascader__tags{box-sizing:border-box;display:flex;flex-wrap:wrap;left:0;line-height:normal;position:absolute;right:30px;text-align:left;top:50%;transform:translateY(-50%)}.el-cascader__tags .el-tag{align-items:center;background:#f0f2f5;display:inline-flex;margin:2px 0 2px 6px;max-width:100%;text-overflow:ellipsis}.el-cascader__tags .el-tag:not(.is-hit){border-color:transparent}.el-cascader__tags .el-tag>span{flex:1;overflow:hidden;text-overflow:ellipsis}.el-cascader__tags .el-tag .el-icon-close{background-color:#afb3ba;color:#fff;flex:none}.el-cascader__tags .el-tag .el-icon-close:hover{background-color:#909399}.el-cascader__suggestion-panel{border-radius:7px}.el-cascader__suggestion-list{color:#606266;font-size:14px;margin:0;max-height:204px;padding:6px 0;text-align:center}.el-cascader__suggestion-item{align-items:center;cursor:pointer;display:flex;height:34px;justify-content:space-between;outline:none;padding:0 15px;text-align:left}.el-cascader__suggestion-item:focus,.el-cascader__suggestion-item:hover{background:#f5f7fa}.el-cascader__suggestion-item.is-checked{color:#1a7efb;font-weight:700}.el-cascader__suggestion-item>span{margin-right:10px}.el-cascader__empty-text{color:#afb3ba;margin:10px 0}.el-cascader__search-input{border:none;box-sizing:border-box;color:#606266;flex:1;height:24px;margin:2px 0 2px 15px;min-width:60px;outline:none;padding:0}.el-cascader__search-input::-moz-placeholder{color:#afb3ba}.el-cascader__search-input::placeholder{color:#afb3ba}.el-color-predefine{display:flex;font-size:12px;margin-top:8px;width:280px}.el-color-predefine__colors{display:flex;flex:1;flex-wrap:wrap}.el-color-predefine__color-selector{border-radius:4px;cursor:pointer;height:20px;margin:0 0 8px 8px;width:20px}.el-color-predefine__color-selector:nth-child(10n+1){margin-left:0}.el-color-predefine__color-selector.selected{box-shadow:0 0 3px 2px #1a7efb}.el-color-predefine__color-selector>div{border-radius:3px;display:flex;height:100%}.el-color-predefine__color-selector.is-alpha{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.el-color-hue-slider{background-color:red;box-sizing:border-box;height:12px;padding:0 2px;position:relative;width:280px}.el-color-hue-slider__bar{background:linear-gradient(90deg,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red);height:100%;position:relative}.el-color-hue-slider__thumb{background:#fff;border:1px solid #f0f0f0;border-radius:1px;box-shadow:0 0 2px rgba(0,0,0,.6);box-sizing:border-box;cursor:pointer;height:100%;left:0;position:absolute;top:0;width:4px;z-index:1}.el-color-hue-slider.is-vertical{height:180px;padding:2px 0;width:12px}.el-color-hue-slider.is-vertical .el-color-hue-slider__bar{background:linear-gradient(180deg,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red)}.el-color-hue-slider.is-vertical .el-color-hue-slider__thumb{height:4px;left:0;top:0;width:100%}.el-color-svpanel{height:180px;position:relative;width:280px}.el-color-svpanel__black,.el-color-svpanel__white{bottom:0;left:0;position:absolute;right:0;top:0}.el-color-svpanel__white{background:linear-gradient(90deg,#fff,hsla(0,0%,100%,0))}.el-color-svpanel__black{background:linear-gradient(0deg,#000,transparent)}.el-color-svpanel__cursor{position:absolute}.el-color-svpanel__cursor>div{border-radius:50%;box-shadow:0 0 0 1.5px #fff,inset 0 0 1px 1px rgba(0,0,0,.3),0 0 1px 2px rgba(0,0,0,.4);cursor:head;height:4px;transform:translate(-2px,-2px);width:4px}.el-color-alpha-slider{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);box-sizing:border-box;height:12px;position:relative;width:280px}.el-color-alpha-slider__bar{background:linear-gradient(90deg,hsla(0,0%,100%,0) 0,#fff);height:100%;position:relative}.el-color-alpha-slider__thumb{background:#fff;border:1px solid #f0f0f0;border-radius:1px;box-shadow:0 0 2px rgba(0,0,0,.6);box-sizing:border-box;cursor:pointer;height:100%;left:0;position:absolute;top:0;width:4px;z-index:1}.el-color-alpha-slider.is-vertical{height:180px;width:20px}.el-color-alpha-slider.is-vertical .el-color-alpha-slider__bar{background:linear-gradient(180deg,hsla(0,0%,100%,0) 0,#fff)}.el-color-alpha-slider.is-vertical .el-color-alpha-slider__thumb{height:4px;left:0;top:0;width:100%}.el-color-dropdown{width:300px}.el-color-dropdown__main-wrapper{margin-bottom:6px}.el-color-dropdown__main-wrapper:after{clear:both;content:"";display:table}.el-color-dropdown__btns{margin-top:6px;text-align:right}.el-color-dropdown__value{color:#000;float:left;font-size:12px;line-height:26px;width:160px}.el-color-dropdown__btn{background-color:transparent;border:1px solid #dcdcdc;border-radius:2px;color:#333;cursor:pointer;font-size:12px;line-height:24px;outline:none;padding:0 20px}.el-color-dropdown__btn[disabled]{color:#ccc;cursor:not-allowed}.el-color-dropdown__btn:hover{border-color:#1a7efb;color:#1a7efb}.el-color-dropdown__link-btn{color:#1a7efb;cursor:pointer;font-size:12px;padding:15px;text-decoration:none}.el-color-dropdown__link-btn:hover{color:tint(#1a7efb,20%)}.el-color-picker{display:inline-block;height:40px;line-height:normal;position:relative}.el-color-picker.is-disabled .el-color-picker__trigger{cursor:not-allowed}.el-color-picker--medium{height:36px}.el-color-picker--medium .el-color-picker__trigger{height:36px;width:36px}.el-color-picker--medium .el-color-picker__mask{height:34px;width:34px}.el-color-picker--small{height:32px}.el-color-picker--small .el-color-picker__trigger{height:32px;width:32px}.el-color-picker--small .el-color-picker__mask{height:30px;width:30px}.el-color-picker--small .el-color-picker__empty,.el-color-picker--small .el-color-picker__icon{transform:translate3d(-50%,-50%,0) scale(.8)}.el-color-picker--mini{height:28px}.el-color-picker--mini .el-color-picker__trigger{height:28px;width:28px}.el-color-picker--mini .el-color-picker__mask{height:26px;width:26px}.el-color-picker--mini .el-color-picker__empty,.el-color-picker--mini .el-color-picker__icon{transform:translate3d(-50%,-50%,0) scale(.8)}.el-color-picker__mask{background-color:hsla(0,0%,100%,.7);border-radius:4px;cursor:not-allowed;height:38px;left:1px;position:absolute;top:1px;width:38px;z-index:1}.el-color-picker__trigger{border:1px solid #e6e6e6;border-radius:4px;box-sizing:border-box;cursor:pointer;display:inline-block;font-size:0;height:40px;padding:4px;position:relative;width:40px}.el-color-picker__color{border:1px solid #999;border-radius:4px;box-sizing:border-box;display:block;height:100%;position:relative;text-align:center;width:100%}.el-color-picker__color.is-alpha{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.el-color-picker__color-inner{bottom:0;left:0;position:absolute;right:0;top:0}.el-color-picker__empty{color:#999}.el-color-picker__empty,.el-color-picker__icon{font-size:12px;left:50%;position:absolute;top:50%;transform:translate3d(-50%,-50%,0)}.el-color-picker__icon{color:#fff;display:inline-block;text-align:center;width:100%}.el-color-picker__panel{background-color:#fff;border:1px solid #ebeef5;border-radius:7px;box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-sizing:content-box;padding:6px;position:absolute;z-index:10}.el-textarea{display:inline-block;font-size:14px;position:relative;vertical-align:bottom;width:100%}.el-textarea__inner{background-color:#fff;background-image:none;border:1px solid #dadbdd;border-radius:7px;box-sizing:border-box;color:#606266;display:block;font-size:inherit;line-height:1.5;padding:5px 15px;resize:vertical;transition:border-color .2s cubic-bezier(.645,.045,.355,1);width:100%}.el-textarea__inner::-moz-placeholder{color:#afb3ba}.el-textarea__inner::placeholder{color:#afb3ba}.el-textarea__inner:hover{border-color:#afb3ba}.el-textarea__inner:focus{border-color:#1a7efb;outline:none}.el-textarea .el-input__count{background:#fff;bottom:5px;color:#4b4c4d;font-size:12px;position:absolute;right:10px}.el-textarea.is-disabled .el-textarea__inner{background-color:#f5f7fa;border-color:#e4e7ed;color:#afb3ba;cursor:not-allowed}.el-textarea.is-disabled .el-textarea__inner::-moz-placeholder{color:#afb3ba}.el-textarea.is-disabled .el-textarea__inner::placeholder{color:#afb3ba}.el-textarea.is-exceed .el-textarea__inner{border-color:#ff6154}.el-textarea.is-exceed .el-input__count{color:#ff6154}.el-input{display:inline-block;font-size:14px;position:relative;width:100%}.el-input::-webkit-scrollbar{width:6px;z-index:11}.el-input::-webkit-scrollbar:horizontal{height:6px}.el-input::-webkit-scrollbar-thumb{background:#b4bccc;border-radius:5px;width:6px}.el-input::-webkit-scrollbar-corner,.el-input::-webkit-scrollbar-track{background:#fff}.el-input::-webkit-scrollbar-track-piece{background:#fff;width:6px}.el-input .el-input__clear{color:#afb3ba;cursor:pointer;font-size:14px;transition:color .2s cubic-bezier(.645,.045,.355,1)}.el-input .el-input__clear:hover{color:#909399}.el-input .el-input__count{align-items:center;color:#4b4c4d;display:inline-flex;font-size:12px;height:100%}.el-input .el-input__count .el-input__count-inner{background:#fff;display:inline-block;line-height:normal;padding:0 5px}.el-input__inner{-webkit-appearance:none;background-color:#fff;background-image:none;border:1px solid #dadbdd;border-radius:7px;box-sizing:border-box;color:#606266;display:inline-block;font-size:inherit;height:40px;line-height:40px;outline:none;padding:0 15px;transition:border-color .2s cubic-bezier(.645,.045,.355,1);width:100%}.el-input__inner::-ms-reveal{display:none}.el-input__inner::-moz-placeholder{color:#afb3ba}.el-input__inner::placeholder{color:#afb3ba}.el-input__inner:hover{border-color:#afb3ba}.el-input__inner:focus{border-color:#1a7efb;outline:none}.el-input__suffix{color:#afb3ba;height:100%;pointer-events:none;position:absolute;right:5px;text-align:center;top:0;transition:all .3s}.el-input__suffix-inner{pointer-events:all}.el-input__prefix{color:#afb3ba;left:5px;position:absolute;top:0}.el-input__icon,.el-input__prefix{height:100%;text-align:center;transition:all .3s}.el-input__icon{line-height:40px;width:25px}.el-input__icon:after{content:"";display:inline-block;height:100%;vertical-align:middle;width:0}.el-input__validateIcon{pointer-events:none}.el-input.is-active .el-input__inner{border-color:#1a7efb;outline:none}.el-input.is-disabled .el-input__inner{background-color:#f5f7fa;border-color:#e4e7ed;color:#afb3ba;cursor:not-allowed}.el-input.is-disabled .el-input__inner::-moz-placeholder{color:#afb3ba}.el-input.is-disabled .el-input__inner::placeholder{color:#afb3ba}.el-input.is-disabled .el-input__icon{cursor:not-allowed}.el-input.is-exceed .el-input__inner{border-color:#ff6154}.el-input.is-exceed .el-input__suffix .el-input__count{color:#ff6154}.el-input--suffix .el-input__inner{padding-right:30px}.el-input--prefix .el-input__inner{padding-left:30px}.el-input--medium{font-size:14px}.el-input--medium .el-input__inner{height:36px;line-height:36px}.el-input--medium .el-input__icon{line-height:36px}.el-input--small{font-size:13px}.el-input--small .el-input__inner{height:32px;line-height:32px}.el-input--small .el-input__icon{line-height:32px}.el-input--mini{font-size:12px}.el-input--mini .el-input__inner{height:28px;line-height:28px}.el-input--mini .el-input__icon{line-height:28px}.el-input-group{border-collapse:separate;border-spacing:0;display:inline-table;line-height:normal;width:100%}.el-input-group>.el-input__inner{display:table-cell;vertical-align:middle}.el-input-group__append,.el-input-group__prepend{background-color:#f5f7fa;border:1px solid #dadbdd;border-radius:7px;color:#4b4c4d;display:table-cell;padding:0 20px;position:relative;vertical-align:middle;white-space:nowrap;width:1px}.el-input-group__append:focus,.el-input-group__prepend:focus{outline:none}.el-input-group__append .el-button,.el-input-group__append .el-select,.el-input-group__prepend .el-button,.el-input-group__prepend .el-select{display:inline-block;margin:-10px -20px}.el-input-group__append button.el-button,.el-input-group__append div.el-select .el-input__inner,.el-input-group__append div.el-select:hover .el-input__inner,.el-input-group__prepend button.el-button,.el-input-group__prepend div.el-select .el-input__inner,.el-input-group__prepend div.el-select:hover .el-input__inner{background-color:transparent;border-color:transparent;border-bottom:0;border-top:0;color:inherit}.el-input-group__append .el-button,.el-input-group__append .el-input,.el-input-group__prepend .el-button,.el-input-group__prepend .el-input{font-size:inherit}.el-input-group__prepend{border-bottom-right-radius:0;border-right:0;border-top-right-radius:0}.el-input-group__append{border-left:0}.el-input-group--prepend .el-input__inner,.el-input-group__append{border-bottom-left-radius:0;border-top-left-radius:0}.el-input-group--prepend .el-select .el-input.is-focus .el-input__inner{border-color:transparent}.el-input-group--append .el-input__inner{border-bottom-right-radius:0;border-top-right-radius:0}.el-input-group--append .el-select .el-input.is-focus .el-input__inner{border-color:transparent}.el-input__inner::-ms-clear{display:none;height:0;width:0}.el-transfer{font-size:14px}.el-transfer__buttons{display:inline-block;padding:0 30px;vertical-align:middle}.el-transfer__button{background-color:#1a7efb;border-radius:50%;color:#fff;display:block;font-size:0;margin:0 auto;padding:10px}.el-transfer__button.is-with-texts{border-radius:7px}.el-transfer__button.is-disabled,.el-transfer__button.is-disabled:hover{background-color:#f5f7fa;border:1px solid #dadbdd;color:#afb3ba}.el-transfer__button:first-child{margin-bottom:10px}.el-transfer__button:nth-child(2){margin:0}.el-transfer__button i,.el-transfer__button span{font-size:14px}.el-transfer__button [class*=el-icon-]+span{margin-left:0}.el-transfer-panel{background:#fff;border:1px solid #ebeef5;border-radius:7px;box-sizing:border-box;display:inline-block;max-height:100%;overflow:hidden;position:relative;vertical-align:middle;width:200px}.el-transfer-panel__body{height:246px}.el-transfer-panel__body.is-with-footer{padding-bottom:40px}.el-transfer-panel__list{box-sizing:border-box;height:246px;list-style:none;margin:0;overflow:auto;padding:6px 0}.el-transfer-panel__list.is-filterable{height:194px;padding-top:0}.el-transfer-panel__item{display:block!important;height:30px;line-height:30px;padding-left:15px}.el-transfer-panel__item+.el-transfer-panel__item{margin-left:0}.el-transfer-panel__item.el-checkbox{color:#606266}.el-transfer-panel__item:hover{color:#1a7efb}.el-transfer-panel__item.el-checkbox .el-checkbox__label{box-sizing:border-box;display:block;line-height:30px;overflow:hidden;padding-left:24px;text-overflow:ellipsis;white-space:nowrap;width:100%}.el-transfer-panel__item .el-checkbox__input{position:absolute;top:8px}.el-transfer-panel__filter{box-sizing:border-box;display:block;margin:15px;text-align:center;width:auto}.el-transfer-panel__filter .el-input__inner{border-radius:16px;box-sizing:border-box;display:inline-block;font-size:12px;height:32px;padding-left:30px;padding-right:10px;width:100%}.el-transfer-panel__filter .el-input__icon{margin-left:5px}.el-transfer-panel__filter .el-icon-circle-close{cursor:pointer}.el-transfer-panel .el-transfer-panel__header{background:#f5f7fa;border-bottom:1px solid #ebeef5;box-sizing:border-box;color:#000;height:40px;line-height:40px;margin:0;padding-left:15px}.el-transfer-panel .el-transfer-panel__header .el-checkbox{display:block;line-height:40px}.el-transfer-panel .el-transfer-panel__header .el-checkbox .el-checkbox__label{color:#303133;font-size:16px;font-weight:400}.el-transfer-panel .el-transfer-panel__header .el-checkbox .el-checkbox__label span{color:#909399;font-size:12px;font-weight:400;position:absolute;right:15px}.el-transfer-panel .el-transfer-panel__footer{background:#fff;border-top:1px solid #ebeef5;bottom:0;height:40px;left:0;margin:0;padding:0;position:absolute;width:100%;z-index:1}.el-transfer-panel .el-transfer-panel__footer:after{content:"";display:inline-block;height:100%;vertical-align:middle}.el-transfer-panel .el-transfer-panel__footer .el-checkbox{color:#606266;padding-left:20px}.el-transfer-panel .el-transfer-panel__empty{color:#909399;height:30px;line-height:30px;margin:0;padding:6px 15px 0;text-align:center}.el-transfer-panel .el-checkbox__label{padding-left:8px}.el-transfer-panel .el-checkbox__inner{border-radius:3px;height:14px;width:14px}.el-transfer-panel .el-checkbox__inner:after{height:6px;left:4px;width:3px}.el-container{box-sizing:border-box;display:flex;flex:1;flex-basis:auto;flex-direction:row;min-width:0}.el-container.is-vertical{flex-direction:column}.el-header{padding:0 20px}.el-aside,.el-header{box-sizing:border-box;flex-shrink:0}.el-aside,.el-main{overflow:auto}.el-main{display:block;flex:1;flex-basis:auto;padding:20px}.el-footer,.el-main{box-sizing:border-box}.el-footer{flex-shrink:0;padding:0 20px}.el-timeline{font-size:14px;list-style:none;margin:0}.el-timeline .el-timeline-item:last-child .el-timeline-item__tail{display:none}.el-timeline-item{padding-bottom:20px;position:relative}.el-timeline-item__wrapper{padding-left:28px;position:relative;top:-3px}.el-timeline-item__tail{border-left:2px solid #e4e7ed;height:100%;left:4px;position:absolute}.el-timeline-item__icon{color:#fff;font-size:13px}.el-timeline-item__node{align-items:center;background-color:#e4e7ed;border-radius:50%;display:flex;justify-content:center;position:absolute}.el-timeline-item__node--normal{height:12px;left:-1px;width:12px}.el-timeline-item__node--large{height:14px;left:-2px;width:14px}.el-timeline-item__node--primary{background-color:#1a7efb}.el-timeline-item__node--success{background-color:#00b27f}.el-timeline-item__node--warning{background-color:#fcbe2d}.el-timeline-item__node--danger{background-color:#ff6154}.el-timeline-item__node--info{background-color:#4b4c4d}.el-timeline-item__dot{align-items:center;display:flex;justify-content:center;position:absolute}.el-timeline-item__content{color:#303133}.el-timeline-item__timestamp{color:#909399;font-size:13px;line-height:1}.el-timeline-item__timestamp.is-top{margin-bottom:8px;padding-top:4px}.el-timeline-item__timestamp.is-bottom{margin-top:8px}.el-link{align-items:center;cursor:pointer;display:inline-flex;flex-direction:row;font-size:14px;font-weight:500;justify-content:center;outline:none;padding:0;position:relative;text-decoration:none;vertical-align:middle}.el-link.is-underline:hover:after{border-bottom:1px solid #1a7efb;bottom:0;content:"";height:0;left:0;position:absolute;right:0}.el-link.is-disabled{cursor:not-allowed}.el-link [class*=el-icon-]+span{margin-left:5px}.el-link.el-link--default{color:#606266}.el-link.el-link--default:hover{color:#1a7efb}.el-link.el-link--default:after{border-color:#1a7efb}.el-link.el-link--default.is-disabled{color:#afb3ba}.el-link.el-link--primary{color:#1a7efb}.el-link.el-link--primary:hover{color:#4898fc}.el-link.el-link--primary:after{border-color:#1a7efb}.el-link.el-link--primary.is-disabled{color:#8dbffd}.el-link.el-link--primary.is-underline:hover:after{border-color:#1a7efb}.el-link.el-link--danger{color:#ff6154}.el-link.el-link--danger:hover{color:#ff8176}.el-link.el-link--danger:after{border-color:#ff6154}.el-link.el-link--danger.is-disabled{color:#ffb0aa}.el-link.el-link--danger.is-underline:hover:after{border-color:#ff6154}.el-link.el-link--success{color:#00b27f}.el-link.el-link--success:hover{color:#33c199}.el-link.el-link--success:after{border-color:#00b27f}.el-link.el-link--success.is-disabled{color:#80d9bf}.el-link.el-link--success.is-underline:hover:after{border-color:#00b27f}.el-link.el-link--warning{color:#fcbe2d}.el-link.el-link--warning:hover{color:#fdcb57}.el-link.el-link--warning:after{border-color:#fcbe2d}.el-link.el-link--warning.is-disabled{color:#fedf96}.el-link.el-link--warning.is-underline:hover:after{border-color:#fcbe2d}.el-link.el-link--info{color:#4b4c4d}.el-link.el-link--info:hover{color:#6f7071}.el-link.el-link--info:after{border-color:#4b4c4d}.el-link.el-link--info.is-disabled{color:#a5a6a6}.el-link.el-link--info.is-underline:hover:after{border-color:#4b4c4d}.el-divider{background-color:#dadbdd;position:relative}.el-divider--horizontal{display:block;height:1px;margin:24px 0;width:100%}.el-divider--vertical{display:inline-block;height:1em;margin:0 8px;position:relative;vertical-align:middle;width:1px}.el-divider__text{background-color:#fff;color:#303133;font-size:14px;font-weight:500;padding:0 20px;position:absolute}.el-divider__text.is-left{left:20px;transform:translateY(-50%)}.el-divider__text.is-center{left:50%;transform:translateX(-50%) translateY(-50%)}.el-divider__text.is-right{right:20px;transform:translateY(-50%)}.el-image__error,.el-image__inner,.el-image__placeholder{height:100%;width:100%}.el-image{display:inline-block;overflow:hidden;position:relative}.el-image__inner{vertical-align:top}.el-image__inner--center{display:block;left:50%;position:relative;top:50%;transform:translate(-50%,-50%)}.el-image__error,.el-image__placeholder{background:#f5f7fa}.el-image__error{align-items:center;color:#afb3ba;display:flex;font-size:14px;justify-content:center;vertical-align:middle}.el-image__preview{cursor:pointer}.el-image-viewer__wrapper{bottom:0;left:0;position:fixed;right:0;top:0}.el-image-viewer__btn{align-items:center;border-radius:50%;box-sizing:border-box;cursor:pointer;display:flex;justify-content:center;opacity:.8;position:absolute;-webkit-user-select:none;-moz-user-select:none;user-select:none;z-index:1}.el-image-viewer__close{background-color:#606266;color:#fff;font-size:24px;height:40px;right:40px;top:40px;width:40px}.el-image-viewer__canvas{align-items:center;display:flex;height:100%;justify-content:center;width:100%}.el-image-viewer__actions{background-color:#606266;border-color:#fff;border-radius:22px;bottom:30px;height:44px;left:50%;padding:0 23px;transform:translateX(-50%);width:282px}.el-image-viewer__actions__inner{align-items:center;color:#fff;cursor:default;display:flex;font-size:23px;height:100%;justify-content:space-around;text-align:justify;width:100%}.el-image-viewer__prev{left:40px}.el-image-viewer__next,.el-image-viewer__prev{background-color:#606266;border-color:#fff;color:#fff;font-size:24px;height:44px;top:50%;transform:translateY(-50%);width:44px}.el-image-viewer__next{right:40px;text-indent:2px}.el-image-viewer__mask{background:#000;height:100%;left:0;opacity:.5;position:absolute;top:0;width:100%}.viewer-fade-enter-active{animation:viewer-fade-in .3s}.viewer-fade-leave-active{animation:viewer-fade-out .3s}@keyframes viewer-fade-in{0%{opacity:0;transform:translate3d(0,-20px,0)}to{opacity:1;transform:translateZ(0)}}@keyframes viewer-fade-out{0%{opacity:1;transform:translateZ(0)}to{opacity:0;transform:translate3d(0,-20px,0)}}.el-button{-webkit-appearance:none;background:#fff;border:1px solid #dadbdd;border-radius:7px;box-sizing:border-box;color:#606266;cursor:pointer;display:inline-block;font-size:14px;font-weight:500;line-height:1;margin:0;outline:none;padding:12px 20px;text-align:center;transition:.1s;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;white-space:nowrap}.el-button+.el-button{margin-left:10px}.el-button.is-round{padding:12px 20px}.el-button:focus,.el-button:hover{background-color:#e8f2ff;border-color:#bad8fe;color:#1a7efb}.el-button:active{border-color:#1771e2;color:#1771e2;outline:none}.el-button::-moz-focus-inner{border:0}.el-button [class*=el-icon-]+span{margin-left:5px}.el-button.is-plain:focus,.el-button.is-plain:hover{background:#fff;border-color:#1a7efb;color:#1a7efb}.el-button.is-plain:active{background:#fff;outline:none}.el-button.is-active,.el-button.is-plain:active{border-color:#1771e2;color:#1771e2}.el-button.is-disabled,.el-button.is-disabled:focus,.el-button.is-disabled:hover{background-color:#fff;background-image:none;border-color:#ebeef5;color:#afb3ba;cursor:not-allowed}.el-button.is-disabled.el-button--text{background-color:transparent}.el-button.is-disabled.is-plain,.el-button.is-disabled.is-plain:focus,.el-button.is-disabled.is-plain:hover{background-color:#fff;border-color:#ebeef5;color:#afb3ba}.el-button.is-loading{pointer-events:none;position:relative}.el-button.is-loading:before{background-color:hsla(0,0%,100%,.35);border-radius:inherit;bottom:-1px;content:"";left:-1px;pointer-events:none;position:absolute;right:-1px;top:-1px}.el-button.is-round{border-radius:20px;padding:12px 23px}.el-button.is-circle{border-radius:50%;padding:12px}.el-button--primary{background-color:#1a7efb;border-color:#1a7efb;color:#fff}.el-button--primary:focus,.el-button--primary:hover{background:#4898fc;border-color:#4898fc;color:#fff}.el-button--primary:active{outline:none}.el-button--primary.is-active,.el-button--primary:active{background:#1771e2;border-color:#1771e2;color:#fff}.el-button--primary.is-disabled,.el-button--primary.is-disabled:active,.el-button--primary.is-disabled:focus,.el-button--primary.is-disabled:hover{background-color:#8dbffd;border-color:#8dbffd;color:#fff}.el-button--primary.is-plain{background:#e8f2ff;border-color:#a3cbfd;color:#1a7efb}.el-button--primary.is-plain:focus,.el-button--primary.is-plain:hover{background:#1a7efb;border-color:#1a7efb;color:#fff}.el-button--primary.is-plain:active{background:#1771e2;border-color:#1771e2;color:#fff;outline:none}.el-button--primary.is-plain.is-disabled,.el-button--primary.is-plain.is-disabled:active,.el-button--primary.is-plain.is-disabled:focus,.el-button--primary.is-plain.is-disabled:hover{background-color:#e8f2ff;border-color:#d1e5fe;color:#76b2fd}.el-button--success{background-color:#00b27f;border-color:#00b27f;color:#fff}.el-button--success:focus,.el-button--success:hover{background:#33c199;border-color:#33c199;color:#fff}.el-button--success:active{outline:none}.el-button--success.is-active,.el-button--success:active{background:#00a072;border-color:#00a072;color:#fff}.el-button--success.is-disabled,.el-button--success.is-disabled:active,.el-button--success.is-disabled:focus,.el-button--success.is-disabled:hover{background-color:#80d9bf;border-color:#80d9bf;color:#fff}.el-button--success.is-plain{background:#e6f7f2;border-color:#99e0cc;color:#00b27f}.el-button--success.is-plain:focus,.el-button--success.is-plain:hover{background:#00b27f;border-color:#00b27f;color:#fff}.el-button--success.is-plain:active{background:#00a072;border-color:#00a072;color:#fff;outline:none}.el-button--success.is-plain.is-disabled,.el-button--success.is-plain.is-disabled:active,.el-button--success.is-plain.is-disabled:focus,.el-button--success.is-plain.is-disabled:hover{background-color:#e6f7f2;border-color:#ccf0e5;color:#66d1b2}.el-button--warning{background-color:#fcbe2d;border-color:#fcbe2d;color:#fff}.el-button--warning:focus,.el-button--warning:hover{background:#fdcb57;border-color:#fdcb57;color:#fff}.el-button--warning:active{outline:none}.el-button--warning.is-active,.el-button--warning:active{background:#e3ab29;border-color:#e3ab29;color:#fff}.el-button--warning.is-disabled,.el-button--warning.is-disabled:active,.el-button--warning.is-disabled:focus,.el-button--warning.is-disabled:hover{background-color:#fedf96;border-color:#fedf96;color:#fff}.el-button--warning.is-plain{background:#fff9ea;border-color:#fee5ab;color:#fcbe2d}.el-button--warning.is-plain:focus,.el-button--warning.is-plain:hover{background:#fcbe2d;border-color:#fcbe2d;color:#fff}.el-button--warning.is-plain:active{background:#e3ab29;border-color:#e3ab29;color:#fff;outline:none}.el-button--warning.is-plain.is-disabled,.el-button--warning.is-plain.is-disabled:active,.el-button--warning.is-plain.is-disabled:focus,.el-button--warning.is-plain.is-disabled:hover{background-color:#fff9ea;border-color:#fef2d5;color:#fdd881}.el-button--danger{background-color:#ff6154;border-color:#ff6154;color:#fff}.el-button--danger:focus,.el-button--danger:hover{background:#ff8176;border-color:#ff8176;color:#fff}.el-button--danger:active{outline:none}.el-button--danger.is-active,.el-button--danger:active{background:#e6574c;border-color:#e6574c;color:#fff}.el-button--danger.is-disabled,.el-button--danger.is-disabled:active,.el-button--danger.is-disabled:focus,.el-button--danger.is-disabled:hover{background-color:#ffb0aa;border-color:#ffb0aa;color:#fff}.el-button--danger.is-plain{background:#ffefee;border-color:#ffc0bb;color:#ff6154}.el-button--danger.is-plain:focus,.el-button--danger.is-plain:hover{background:#ff6154;border-color:#ff6154;color:#fff}.el-button--danger.is-plain:active{background:#e6574c;border-color:#e6574c;color:#fff;outline:none}.el-button--danger.is-plain.is-disabled,.el-button--danger.is-plain.is-disabled:active,.el-button--danger.is-plain.is-disabled:focus,.el-button--danger.is-plain.is-disabled:hover{background-color:#ffefee;border-color:#ffdfdd;color:#ffa098}.el-button--info{background-color:#4b4c4d;border-color:#4b4c4d;color:#fff}.el-button--info:focus,.el-button--info:hover{background:#6f7071;border-color:#6f7071;color:#fff}.el-button--info:active{outline:none}.el-button--info.is-active,.el-button--info:active{background:#444445;border-color:#444445;color:#fff}.el-button--info.is-disabled,.el-button--info.is-disabled:active,.el-button--info.is-disabled:focus,.el-button--info.is-disabled:hover{background-color:#a5a6a6;border-color:#a5a6a6;color:#fff}.el-button--info.is-plain{background:#ededed;border-color:#b7b7b8;color:#4b4c4d}.el-button--info.is-plain:focus,.el-button--info.is-plain:hover{background:#4b4c4d;border-color:#4b4c4d;color:#fff}.el-button--info.is-plain:active{background:#444445;border-color:#444445;color:#fff;outline:none}.el-button--info.is-plain.is-disabled,.el-button--info.is-plain.is-disabled:active,.el-button--info.is-plain.is-disabled:focus,.el-button--info.is-plain.is-disabled:hover{background-color:#ededed;border-color:#dbdbdb;color:#939494}.el-button--medium{border-radius:7px;font-size:14px;padding:10px 20px}.el-button--medium.is-round{padding:10px 20px}.el-button--medium.is-circle{padding:10px}.el-button--small{border-radius:6px;font-size:13px;padding:8px 11px}.el-button--small.is-round{padding:8px 11px}.el-button--small.is-circle{padding:8px}.el-button--mini{border-radius:6px;font-size:12px;padding:7px 15px}.el-button--mini.is-round{padding:7px 15px}.el-button--mini.is-circle{padding:7px}.el-button--text{background:transparent;border-color:transparent;color:#1a7efb;padding-left:0;padding-right:0}.el-button--text:focus,.el-button--text:hover{background-color:transparent;border-color:transparent;color:#4898fc}.el-button--text:active{background-color:transparent;color:#1771e2}.el-button--text.is-disabled,.el-button--text.is-disabled:focus,.el-button--text.is-disabled:hover,.el-button--text:active{border-color:transparent}.el-button-group{display:inline-block;vertical-align:middle}.el-button-group:after,.el-button-group:before{content:"";display:table}.el-button-group:after{clear:both}.el-button-group>.el-button{float:left;position:relative}.el-button-group>.el-button+.el-button{margin-left:0}.el-button-group>.el-button.is-disabled{z-index:1}.el-button-group>.el-button:first-child{border-bottom-right-radius:0;border-top-right-radius:0}.el-button-group>.el-button:last-child{border-bottom-left-radius:0;border-top-left-radius:0}.el-button-group>.el-button:first-child:last-child{border-bottom-left-radius:7px;border-bottom-right-radius:7px;border-top-left-radius:7px;border-top-right-radius:7px}.el-button-group>.el-button:first-child:last-child.is-round{border-radius:20px}.el-button-group>.el-button:first-child:last-child.is-circle{border-radius:50%}.el-button-group>.el-button:not(:first-child):not(:last-child){border-radius:0}.el-button-group>.el-button:not(:last-child){margin-right:-1px}.el-button-group>.el-button.is-active,.el-button-group>.el-button:not(.is-disabled):active,.el-button-group>.el-button:not(.is-disabled):focus,.el-button-group>.el-button:not(.is-disabled):hover{z-index:1}.el-button-group>.el-dropdown>.el-button{border-bottom-left-radius:0;border-left-color:hsla(0,0%,100%,.5);border-top-left-radius:0}.el-button-group .el-button--primary:first-child{border-right-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--primary:last-child{border-left-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--primary:not(:first-child):not(:last-child){border-left-color:hsla(0,0%,100%,.5);border-right-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--success:first-child{border-right-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--success:last-child{border-left-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--success:not(:first-child):not(:last-child){border-left-color:hsla(0,0%,100%,.5);border-right-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--warning:first-child{border-right-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--warning:last-child{border-left-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--warning:not(:first-child):not(:last-child){border-left-color:hsla(0,0%,100%,.5);border-right-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--danger:first-child{border-right-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--danger:last-child{border-left-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--danger:not(:first-child):not(:last-child){border-left-color:hsla(0,0%,100%,.5);border-right-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--info:first-child{border-right-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--info:last-child{border-left-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--info:not(:first-child):not(:last-child){border-left-color:hsla(0,0%,100%,.5);border-right-color:hsla(0,0%,100%,.5)}.el-calendar{background-color:#fff}.el-calendar__header{border-bottom:1px solid #ececec;display:flex;justify-content:space-between;padding:12px 20px}.el-calendar__title{align-self:center;color:#000}.el-calendar__body{padding:12px 20px 35px}.el-calendar-table{table-layout:fixed;width:100%}.el-calendar-table thead th{color:#606266;font-weight:400;padding:12px 0}.el-calendar-table:not(.is-range) td.next,.el-calendar-table:not(.is-range) td.prev{color:#afb3ba}.el-calendar-table td{border-bottom:1px solid #ececec;border-right:1px solid #ececec;transition:background-color .2s ease;vertical-align:top}.el-calendar-table td.is-selected{background-color:#f2f8fe}.el-calendar-table td.is-today{color:#1a7efb}.el-calendar-table tr:first-child td{border-top:1px solid #ececec}.el-calendar-table tr td:first-child{border-left:1px solid #ececec}.el-calendar-table tr.el-calendar-table__row--hide-border td{border-top:none}.el-calendar-table .el-calendar-day{box-sizing:border-box;height:85px;padding:8px}.el-calendar-table .el-calendar-day:hover{background-color:#f2f8fe;cursor:pointer}.el-backtop{align-items:center;background-color:#fff;border-radius:50%;box-shadow:0 0 6px rgba(0,0,0,.12);color:#1a7efb;cursor:pointer;display:flex;font-size:20px;height:40px;justify-content:center;position:fixed;width:40px;z-index:5}.el-backtop:hover{background-color:#f2f6fc}.el-page-header{display:flex;line-height:24px}.el-page-header__left{cursor:pointer;display:flex;margin-right:40px;position:relative}.el-page-header__left:after{background-color:#dadbdd;content:"";height:16px;position:absolute;right:-20px;top:50%;transform:translateY(-50%);width:1px}.el-page-header__left .el-icon-back{align-self:center;font-size:18px;margin-right:6px}.el-page-header__title{font-size:14px;font-weight:500}.el-page-header__content{color:#303133;font-size:18px}.el-checkbox{color:#606266;cursor:pointer;display:inline-block;font-size:14px;font-weight:500;margin-right:30px;position:relative;-webkit-user-select:none;-moz-user-select:none;user-select:none;white-space:nowrap}.el-checkbox.is-bordered{border:1px solid #dadbdd;border-radius:7px;box-sizing:border-box;height:40px;line-height:normal;padding:9px 20px 9px 10px}.el-checkbox.is-bordered.is-checked{border-color:#1a7efb}.el-checkbox.is-bordered.is-disabled{border-color:#ebeef5;cursor:not-allowed}.el-checkbox.is-bordered+.el-checkbox.is-bordered{margin-left:10px}.el-checkbox.is-bordered.el-checkbox--medium{border-radius:7px;height:36px;padding:7px 20px 7px 10px}.el-checkbox.is-bordered.el-checkbox--medium .el-checkbox__label{font-size:14px;line-height:17px}.el-checkbox.is-bordered.el-checkbox--medium .el-checkbox__inner{height:14px;width:14px}.el-checkbox.is-bordered.el-checkbox--small{border-radius:6px;height:32px;padding:5px 15px 5px 10px}.el-checkbox.is-bordered.el-checkbox--small .el-checkbox__label{font-size:13px;line-height:15px}.el-checkbox.is-bordered.el-checkbox--small .el-checkbox__inner{height:12px;width:12px}.el-checkbox.is-bordered.el-checkbox--small .el-checkbox__inner:after{height:6px;width:2px}.el-checkbox.is-bordered.el-checkbox--mini{border-radius:6px;height:28px;padding:3px 15px 3px 10px}.el-checkbox.is-bordered.el-checkbox--mini .el-checkbox__label{font-size:12px;line-height:12px}.el-checkbox.is-bordered.el-checkbox--mini .el-checkbox__inner{height:12px;width:12px}.el-checkbox.is-bordered.el-checkbox--mini .el-checkbox__inner:after{height:6px;width:2px}.el-checkbox__input{cursor:pointer;display:inline-block;line-height:1;outline:none;position:relative;vertical-align:middle;white-space:nowrap}.el-checkbox__input.is-disabled .el-checkbox__inner{background-color:#edf2fc;border-color:#dadbdd;cursor:not-allowed}.el-checkbox__input.is-disabled .el-checkbox__inner:after{border-color:#afb3ba;cursor:not-allowed}.el-checkbox__input.is-disabled .el-checkbox__inner+.el-checkbox__label{cursor:not-allowed}.el-checkbox__input.is-disabled.is-checked .el-checkbox__inner{background-color:#f2f6fc;border-color:#dadbdd}.el-checkbox__input.is-disabled.is-checked .el-checkbox__inner:after{border-color:#afb3ba}.el-checkbox__input.is-disabled.is-indeterminate .el-checkbox__inner{background-color:#f2f6fc;border-color:#dadbdd}.el-checkbox__input.is-disabled.is-indeterminate .el-checkbox__inner:before{background-color:#afb3ba;border-color:#afb3ba}.el-checkbox__input.is-disabled+span.el-checkbox__label{color:#afb3ba;cursor:not-allowed}.el-checkbox__input.is-checked .el-checkbox__inner{background-color:#1a7efb;border-color:#1a7efb}.el-checkbox__input.is-checked .el-checkbox__inner:after{transform:rotate(45deg) scaleY(1)}.el-checkbox__input.is-checked+.el-checkbox__label{color:#1a7efb}.el-checkbox__input.is-focus .el-checkbox__inner{border-color:#1a7efb}.el-checkbox__input.is-indeterminate .el-checkbox__inner{background-color:#1a7efb;border-color:#1a7efb}.el-checkbox__input.is-indeterminate .el-checkbox__inner:before{background-color:#fff;content:"";display:block;height:2px;left:0;position:absolute;right:0;top:5px;transform:scale(.5)}.el-checkbox__input.is-indeterminate .el-checkbox__inner:after{display:none}.el-checkbox__inner{background-color:#fff;border:1px solid #868686;border-radius:4px;box-sizing:border-box;display:inline-block;height:14px;position:relative;transition:border-color .25s cubic-bezier(.71,-.46,.29,1.46),background-color .25s cubic-bezier(.71,-.46,.29,1.46);width:14px;z-index:1}.el-checkbox__inner:hover{border-color:#1a7efb}.el-checkbox__inner:after{border:1px solid #fff;border-left:0;border-top:0;box-sizing:content-box;content:"";height:7px;left:4px;position:absolute;top:1px;transform:rotate(45deg) scaleY(0);transform-origin:center;transition:transform .15s ease-in .05s;width:3px}.el-checkbox__original{height:0;margin:0;opacity:0;outline:none;position:absolute;width:0;z-index:-1}.el-checkbox__label{display:inline-block;font-size:14px;line-height:19px;padding-left:10px}.el-checkbox:last-of-type{margin-right:0}.el-checkbox-button,.el-checkbox-button__inner{display:inline-block;position:relative}.el-checkbox-button__inner{-webkit-appearance:none;background:#fff;border:1px solid #dadbdd;border-left:0;border-radius:0;box-sizing:border-box;color:#606266;cursor:pointer;font-size:14px;font-weight:500;line-height:1;margin:0;outline:none;padding:12px 20px;text-align:center;transition:all .3s cubic-bezier(.645,.045,.355,1);-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;vertical-align:middle;white-space:nowrap}.el-checkbox-button__inner.is-round{padding:12px 20px}.el-checkbox-button__inner:hover{color:#1a7efb}.el-checkbox-button__inner [class*=el-icon-]{line-height:.9}.el-checkbox-button__inner [class*=el-icon-]+span{margin-left:5px}.el-checkbox-button__original{margin:0;opacity:0;outline:none;position:absolute;z-index:-1}.el-checkbox-button.is-checked .el-checkbox-button__inner{background-color:#1a7efb;border-color:#1a7efb;box-shadow:-1px 0 0 0 #76b2fd;color:#fff}.el-checkbox-button.is-checked:first-child .el-checkbox-button__inner{border-left-color:#1a7efb}.el-checkbox-button.is-disabled .el-checkbox-button__inner{background-color:#fff;background-image:none;border-color:#ebeef5;box-shadow:none;color:#afb3ba;cursor:not-allowed}.el-checkbox-button.is-disabled:first-child .el-checkbox-button__inner{border-left-color:#ebeef5}.el-checkbox-button:first-child .el-checkbox-button__inner{border-left:1px solid #dadbdd;border-radius:7px 0 0 7px;box-shadow:none!important}.el-checkbox-button.is-focus .el-checkbox-button__inner{border-color:#1a7efb}.el-checkbox-button:last-child .el-checkbox-button__inner{border-radius:0 7px 7px 0}.el-checkbox-button--medium .el-checkbox-button__inner{border-radius:0;font-size:14px;padding:10px 20px}.el-checkbox-button--medium .el-checkbox-button__inner.is-round{padding:10px 20px}.el-checkbox-button--small .el-checkbox-button__inner{border-radius:0;font-size:13px;padding:8px 11px}.el-checkbox-button--small .el-checkbox-button__inner.is-round{padding:8px 11px}.el-checkbox-button--mini .el-checkbox-button__inner{border-radius:0;font-size:12px;padding:7px 15px}.el-checkbox-button--mini .el-checkbox-button__inner.is-round{padding:7px 15px}.el-checkbox-group{font-size:0}.el-radio{color:#606266;cursor:pointer;display:inline-block;font-size:14px;font-weight:500;line-height:1;margin-right:30px;outline:none;position:relative;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;white-space:nowrap}.el-radio.is-bordered{border:1px solid #dadbdd;border-radius:7px;box-sizing:border-box;height:40px;padding:12px 20px 0 10px}.el-radio.is-bordered.is-checked{border-color:#1a7efb}.el-radio.is-bordered.is-disabled{border-color:#ebeef5;cursor:not-allowed}.el-radio.is-bordered+.el-radio.is-bordered{margin-left:10px}.el-radio--medium.is-bordered{border-radius:7px;height:36px;padding:10px 20px 0 10px}.el-radio--medium.is-bordered .el-radio__label{font-size:14px}.el-radio--medium.is-bordered .el-radio__inner{height:14px;width:14px}.el-radio--small.is-bordered{border-radius:6px;height:32px;padding:8px 15px 0 10px}.el-radio--small.is-bordered .el-radio__label{font-size:13px}.el-radio--small.is-bordered .el-radio__inner{height:12px;width:12px}.el-radio--mini.is-bordered{border-radius:6px;height:28px;padding:6px 15px 0 10px}.el-radio--mini.is-bordered .el-radio__label{font-size:12px}.el-radio--mini.is-bordered .el-radio__inner{height:12px;width:12px}.el-radio:last-child{margin-right:0}.el-radio__input{cursor:pointer;display:inline-block;line-height:1;outline:none;position:relative;vertical-align:middle;white-space:nowrap}.el-radio__input.is-disabled .el-radio__inner{background-color:#f5f7fa;border-color:#e4e7ed;cursor:not-allowed}.el-radio__input.is-disabled .el-radio__inner:after{background-color:#f5f7fa;cursor:not-allowed}.el-radio__input.is-disabled .el-radio__inner+.el-radio__label{cursor:not-allowed}.el-radio__input.is-disabled.is-checked .el-radio__inner{background-color:#f5f7fa;border-color:#e4e7ed}.el-radio__input.is-disabled.is-checked .el-radio__inner:after{background-color:#afb3ba}.el-radio__input.is-disabled+span.el-radio__label{color:#afb3ba;cursor:not-allowed}.el-radio__input.is-checked .el-radio__inner{background:#1a7efb;border-color:#1a7efb}.el-radio__input.is-checked .el-radio__inner:after{transform:translate(-50%,-50%) scale(1)}.el-radio__input.is-checked+.el-radio__label{color:#1a7efb}.el-radio__input.is-focus .el-radio__inner{border-color:#1a7efb}.el-radio__inner{background-color:#fff;border:1px solid #dadbdd;border-radius:100%;box-sizing:border-box;cursor:pointer;display:inline-block;height:14px;position:relative;width:14px}.el-radio__inner:hover{border-color:#1a7efb}.el-radio__inner:after{background-color:#fff;border-radius:100%;content:"";height:4px;left:50%;position:absolute;top:50%;transform:translate(-50%,-50%) scale(0);transition:transform .15s ease-in;width:4px}.el-radio__original{bottom:0;left:0;margin:0;opacity:0;outline:none;position:absolute;right:0;top:0;z-index:-1}.el-radio:focus:not(.is-focus):not(:active):not(.is-disabled) .el-radio__inner{box-shadow:0 0 2px 2px #1a7efb}.el-radio__label{font-size:14px;padding-left:10px}.el-scrollbar{overflow:hidden;position:relative}.el-scrollbar:active>.el-scrollbar__bar,.el-scrollbar:focus>.el-scrollbar__bar,.el-scrollbar:hover>.el-scrollbar__bar{opacity:1;transition:opacity .34s ease-out}.el-scrollbar__wrap{height:100%;overflow:scroll}.el-scrollbar__wrap--hidden-default{scrollbar-width:none}.el-scrollbar__wrap--hidden-default::-webkit-scrollbar{height:0;width:0}.el-scrollbar__thumb{background-color:hsla(220,4%,58%,.3);border-radius:inherit;cursor:pointer;display:block;height:0;position:relative;transition:background-color .3s;width:0}.el-scrollbar__thumb:hover{background-color:hsla(220,4%,58%,.5)}.el-scrollbar__bar{border-radius:4px;bottom:2px;opacity:0;position:absolute;right:2px;transition:opacity .12s ease-out;z-index:1}.el-scrollbar__bar.is-vertical{top:2px;width:6px}.el-scrollbar__bar.is-vertical>div{width:100%}.el-scrollbar__bar.is-horizontal{height:6px;left:2px}.el-scrollbar__bar.is-horizontal>div{height:100%}.el-cascader-panel{border-radius:7px;display:flex;font-size:14px}.el-cascader-panel.is-bordered{border:1px solid #e4e7ed;border-radius:7px}.el-cascader-menu{border-right:1px solid #e4e7ed;box-sizing:border-box;color:#606266;min-width:180px}.el-cascader-menu:last-child{border-right:none}.el-cascader-menu:last-child .el-cascader-node{padding-right:20px}.el-cascader-menu__wrap{height:204px}.el-cascader-menu__list{box-sizing:border-box;list-style:none;margin:0;min-height:100%;padding:6px 0;position:relative}.el-cascader-menu__hover-zone{height:100%;left:0;pointer-events:none;position:absolute;top:0;width:100%}.el-cascader-menu__empty-text{color:#afb3ba;left:50%;position:absolute;text-align:center;top:50%;transform:translate(-50%,-50%)}.el-cascader-node{align-items:center;display:flex;height:34px;line-height:34px;outline:none;padding:0 30px 0 20px;position:relative}.el-cascader-node.is-selectable.in-active-path{color:#606266}.el-cascader-node.in-active-path,.el-cascader-node.is-active,.el-cascader-node.is-selectable.in-checked-path{color:#1a7efb;font-weight:700}.el-cascader-node:not(.is-disabled){cursor:pointer}.el-cascader-node:not(.is-disabled):focus,.el-cascader-node:not(.is-disabled):hover{background:#f5f7fa}.el-cascader-node.is-disabled{color:#afb3ba;cursor:not-allowed}.el-cascader-node__prefix{left:10px;position:absolute}.el-cascader-node__postfix{position:absolute;right:10px}.el-cascader-node__label{flex:1;overflow:hidden;padding:0 10px;text-overflow:ellipsis;white-space:nowrap}.el-cascader-node>.el-radio{margin-right:0}.el-cascader-node>.el-radio .el-radio__label{padding-left:0}.el-avatar{background:#c0c4cc;box-sizing:border-box;color:#fff;display:inline-block;font-size:14px;height:40px;line-height:40px;overflow:hidden;text-align:center;width:40px}.el-avatar>img{display:block;height:100%;vertical-align:middle}.el-avatar--circle{border-radius:50%}.el-avatar--square{border-radius:7px}.el-avatar--icon{font-size:18px}.el-avatar--large{height:40px;line-height:40px;width:40px}.el-avatar--medium{height:36px;line-height:36px;width:36px}.el-avatar--small{height:28px;line-height:28px;width:28px}@keyframes el-drawer-fade-in{0%{opacity:0}to{opacity:1}}@keyframes rtl-drawer-in{0%{transform:translate(100%)}to{transform:translate(0)}}@keyframes rtl-drawer-out{0%{transform:translate(0)}to{transform:translate(100%)}}@keyframes ltr-drawer-in{0%{transform:translate(-100%)}to{transform:translate(0)}}@keyframes ltr-drawer-out{0%{transform:translate(0)}to{transform:translate(-100%)}}@keyframes ttb-drawer-in{0%{transform:translateY(-100%)}to{transform:translate(0)}}@keyframes ttb-drawer-out{0%{transform:translate(0)}to{transform:translateY(-100%)}}@keyframes btt-drawer-in{0%{transform:translateY(100%)}to{transform:translate(0)}}@keyframes btt-drawer-out{0%{transform:translate(0)}to{transform:translateY(100%)}}.el-drawer{background-color:#fff;box-shadow:0 8px 10px -5px rgba(0,0,0,.2),0 16px 24px 2px rgba(0,0,0,.14),0 6px 30px 5px rgba(0,0,0,.12);box-sizing:border-box;display:flex;flex-direction:column;outline:0;overflow:hidden;position:absolute}.el-drawer.rtl{animation:rtl-drawer-out .3s}.el-drawer__open .el-drawer.rtl{animation:rtl-drawer-in .3s 1ms}.el-drawer.ltr{animation:ltr-drawer-out .3s}.el-drawer__open .el-drawer.ltr{animation:ltr-drawer-in .3s 1ms}.el-drawer.ttb{animation:ttb-drawer-out .3s}.el-drawer__open .el-drawer.ttb{animation:ttb-drawer-in .3s 1ms}.el-drawer.btt{animation:btt-drawer-out .3s}.el-drawer__open .el-drawer.btt{animation:btt-drawer-in .3s 1ms}.el-drawer__wrapper{bottom:0;left:0;margin:0;overflow:hidden;position:fixed;right:0;top:0}.el-drawer__header{align-items:center;color:#72767b;display:flex;margin-bottom:32px;padding:20px 20px 0}.el-drawer__header>:first-child{flex:1}.el-drawer__title{flex:1;font-size:1rem;line-height:inherit;margin:0}.el-drawer__close-btn{background-color:transparent;border:none;color:inherit;cursor:pointer;font-size:20px}.el-drawer__body{flex:1;overflow:auto}.el-drawer__body>*{box-sizing:border-box}.el-drawer.ltr,.el-drawer.rtl{bottom:0;height:100%;top:0}.el-drawer.btt,.el-drawer.ttb{left:0;right:0;width:100%}.el-drawer.ltr{left:0}.el-drawer.rtl{right:0}.el-drawer.ttb{top:0}.el-drawer.btt{bottom:0}.el-drawer__container{bottom:0;height:100%;left:0;position:relative;right:0;top:0;width:100%}.el-drawer-fade-enter-active{animation:el-drawer-fade-in .3s}.el-drawer-fade-leave-active{animation:el-drawer-fade-in .3s reverse}.el-statistic{font-feature-settings:"tnum";box-sizing:border-box;color:#000;font-variant:tabular-nums;list-style:none;margin:0;padding:0;text-align:center;width:100%}.el-statistic .head{color:#606266;font-size:13px;margin-bottom:4px}.el-statistic .con{align-items:center;color:#303133;display:flex;font-family:Sans-serif;justify-content:center}.el-statistic .con .number{font-size:20px;padding:0 4px}.el-statistic .con span{display:inline-block;line-height:100%;margin:0}.el-popconfirm__main{align-items:center;display:flex}.el-popconfirm__icon{margin-right:5px}.el-popconfirm__action{margin:0;text-align:right}@keyframes el-skeleton-loading{0%{background-position:100% 50%}to{background-position:0 50%}}.el-skeleton{width:100%}.el-skeleton__first-line,.el-skeleton__paragraph{background:#f2f2f2;height:16px;margin-top:16px}.el-skeleton.is-animated .el-skeleton__item{animation:el-skeleton-loading 1.4s ease infinite;background:linear-gradient(90deg,#f2f2f2 25%,#e6e6e6 37%,#f2f2f2 63%);background-size:400% 100%}.el-skeleton__item{background:#f2f2f2;border-radius:7px;display:inline-block;height:16px;width:100%}.el-skeleton__circle{border-radius:50%;height:36px;line-height:36px;width:36px}.el-skeleton__circle--lg{height:40px;line-height:40px;width:40px}.el-skeleton__circle--md{height:28px;line-height:28px;width:28px}.el-skeleton__button{border-radius:4px;height:40px;width:64px}.el-skeleton__p{width:100%}.el-skeleton__p.is-last{width:61%}.el-skeleton__p.is-first{width:33%}.el-skeleton__text{height:13px;width:100%}.el-skeleton__caption{height:12px}.el-skeleton__h1{height:20px}.el-skeleton__h3{height:18px}.el-skeleton__h5{height:16px}.el-skeleton__image{align-items:center;border-radius:0;display:flex;justify-content:center;width:unset}.el-skeleton__image svg{fill:#dcdde0;height:22%;width:22%}.el-empty{align-items:center;box-sizing:border-box;display:flex;flex-direction:column;justify-content:center;padding:40px 0;text-align:center}.el-empty__image{width:160px}.el-empty__image img{height:100%;-o-object-fit:contain;object-fit:contain;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:top;width:100%}.el-empty__image svg{fill:#dcdde0;height:100%;vertical-align:top;width:100%}.el-empty__description{margin-top:20px}.el-empty__description p{color:#909399;font-size:14px;margin:0}.el-empty__bottom{margin-top:20px}.el-descriptions{box-sizing:border-box;color:#303133;font-size:14px}.el-descriptions__header{align-items:center;display:flex;justify-content:space-between;margin-bottom:20px}.el-descriptions__title{font-size:16px;font-weight:700}.el-descriptions__body{background-color:#fff;color:#606266}.el-descriptions__body .el-descriptions__table{border-collapse:collapse;table-layout:fixed;width:100%}.el-descriptions__body .el-descriptions__table .el-descriptions-item__cell{box-sizing:border-box;font-weight:400;line-height:1.5;text-align:left}.el-descriptions__body .el-descriptions__table .el-descriptions-item__cell.is-left{text-align:left}.el-descriptions__body .el-descriptions__table .el-descriptions-item__cell.is-center{text-align:center}.el-descriptions__body .el-descriptions__table .el-descriptions-item__cell.is-right{text-align:right}.el-descriptions .is-bordered{table-layout:auto}.el-descriptions .is-bordered .el-descriptions-item__cell{border:1px solid #ebeef5;padding:12px 10px}.el-descriptions :not(.is-bordered) .el-descriptions-item__cell{padding-bottom:12px}.el-descriptions--medium.is-bordered .el-descriptions-item__cell{padding:10px}.el-descriptions--medium:not(.is-bordered) .el-descriptions-item__cell{padding-bottom:10px}.el-descriptions--small{font-size:12px}.el-descriptions--small.is-bordered .el-descriptions-item__cell{padding:8px 10px}.el-descriptions--small:not(.is-bordered) .el-descriptions-item__cell{padding-bottom:8px}.el-descriptions--mini{font-size:12px}.el-descriptions--mini.is-bordered .el-descriptions-item__cell{padding:6px 10px}.el-descriptions--mini:not(.is-bordered) .el-descriptions-item__cell{padding-bottom:6px}.el-descriptions-item{vertical-align:top}.el-descriptions-item__container{display:flex}.el-descriptions-item__container .el-descriptions-item__content,.el-descriptions-item__container .el-descriptions-item__label{align-items:baseline;display:inline-flex}.el-descriptions-item__container .el-descriptions-item__content{flex:1}.el-descriptions-item__label.has-colon:after{content:":";position:relative;top:-.5px}.el-descriptions-item__label.is-bordered-label{background:#fafafa;color:#909399;font-weight:700}.el-descriptions-item__label:not(.is-bordered-label){margin-right:10px}.el-descriptions-item__content{overflow-wrap:break-word;word-break:break-word}.el-result{align-items:center;box-sizing:border-box;display:flex;flex-direction:column;justify-content:center;padding:40px 30px;text-align:center}.el-result__icon svg{height:64px;width:64px}.el-result__title{margin-top:20px}.el-result__title p{color:#303133;font-size:20px;line-height:1.3;margin:0}.el-result__subtitle{margin-top:10px}.el-result__subtitle p{color:#606266;font-size:14px;line-height:1.3;margin:0}.el-result__extra{margin-top:30px}.el-result .icon-success{fill:#00b27f}.el-result .icon-error{fill:#ff6154}.el-result .icon-info{fill:#4b4c4d}.el-result .icon-warning{fill:#fcbe2d}.el-button--upload{border-style:dashed;justify-content:center;padding:24px;width:100%}.el-button--upload .el-icon{font-size:22px}.ff_file_upload_result{align-items:center;background-color:#fafafa;border:1px solid #f2f2f2;border-radius:8px;display:flex;overflow:hidden;padding:10px;position:relative}.ff_file_upload_result .el-button{position:absolute;right:10px;top:50%;transform:translateY(-50%)}.ff_file_upload_result+.ff_file_upload_result{margin-top:10px}.ff_file_upload_preview{height:44px;width:44px}.ff_file_upload_preview img{border-radius:4px;height:100%;-o-object-fit:cover;object-fit:cover;width:44px}.ff_file_upload_preview+.ff_file_upload_data{margin-left:15px}.ff_file_upload_description{color:#1e1f21;font-size:14px}.ff_file_upload_size{font-size:12px;margin-top:4px}.mt-1{margin-top:4px!important}.mt-2{margin-top:8px!important}.mt-3{margin-top:16px!important}.mt-4{margin-top:24px!important}.mt-5{margin-top:32px!important}.mt-6{margin-top:40px!important}.mb-1{margin-bottom:4px!important}.mb-2{margin-bottom:8px!important}.mb-3{margin-bottom:16px!important}.mb-4{margin-bottom:24px!important}.mb-5{margin-bottom:32px!important}.mb-6{margin-bottom:40px!important}.mr-1{margin-right:4px!important}.mr-2{margin-right:8px!important}.mr-3{margin-right:16px!important}.mr-4{margin-right:24px!important}.mr-5{margin-right:32px!important}.mr-6{margin-right:40px!important}.ml-1{margin-left:4px!important}.ml-2{margin-left:8px!important}.ml-3{margin-left:16px!important}.ml-4{margin-left:24px!important}.ml-5{margin-left:32px!important}.ml-6{margin-left:40px!important}.mt-0{margin-top:0!important}.mb-0{margin-bottom:0!important}.mr-0{margin-right:0!important}.ml-0{margin-left:0!important}.el-tabs--border-card>.el-tabs__content{overflow:inherit;padding:16px 22px}.ff-control-title-breaker{background:rgba(164,175,183,.129);font-weight:700;text-align:center}.ff-control-field{clear:both;display:block;margin-bottom:0;overflow:hidden}.ff-control-field.ff_control_full .ff-control-title{display:block;float:none;margin-bottom:8px;width:100%}.el-collapse{border:none!important}.el-collapse .el-collapse-item__header{background-color:#f2f2f2;border-bottom:0;border-radius:6px;height:auto;line-height:40px;margin-bottom:10px;padding-left:16px}.el-collapse .el-collapse-item__header .el-collapse-item__arrow{margin-right:14px}.el-collapse .el-collapse-item .el-collapse-item__wrap{background:#f6f7fa;border-bottom:0;border-radius:6px;margin-bottom:20px;padding:20px}.el-collapse .el-collapse-item .el-collapse-item__wrap .el-collapse-item__content:last-child{margin-bottom:0;padding-bottom:0}.ff_each_style{padding:0 0 15px;position:relative}.ff_each_style:last-child{padding-bottom:0!important}.ff_each_style .ff-control-title{float:left;font-size:14px;font-weight:500;width:50%}.ff_each_style .ff-control-title-auto{width:auto}.ff_each_style .ff-control-input-wrapper{float:right;text-align:right;width:50%}.ff_each_style .ff-control-input-wrapper.ff_input_wrapper_full{float:none;text-align:left;width:100%}.ff_each_style .ff-control-input-wrapper-auto{width:auto}.ff_each_style .ff-control-dimensions{margin:0;overflow:hidden;padding:0}.ff_each_style .ff-control-dimensions li{float:left;list-style:none;margin:0;padding:0;width:20%}.ff_each_style .ff-control-dimensions li:first-child input{border-left:1px solid #d5dadf;border-radius:3px 0 0 3px}.ff_each_style .ff-control-dimensions li input{border-color:#d5dadf;border-radius:0;display:block;height:27px;padding:4px 0;text-align:center;width:100%}.ff_each_style .ff-control-dimensions li input:focus{border-color:#a4afb7;margin-left:0;outline:0;width:100%}.ff_each_style .ff-control-dimensions li label{color:#989898;display:block;font-size:9px;padding-top:0;text-align:center;text-transform:uppercase}.ff_each_style .ff-control-dimensions li .ff_item_linkable{border:1px solid #d5dadf;border-bottom-right-radius:3px;border-top-right-radius:3px;display:inline-block;font-size:10px;height:27px;padding:0 16px;vertical-align:top}.ff_each_style .ff-control-dimensions li .ff_item_linkable.ff_item_linked{background-color:#606266;border-color:#606266;color:#fff}.ff_each_style .ff-control-dimensions li .ff_item_linkable span{font-size:17px;margin-top:4px}.ff_each_style .ff-linked{cursor:pointer}.ff_each_style .ff_section_title{font-size:18px;font-weight:500;margin-bottom:10px;margin-top:10px}.ff_each_style .ff-control-background .ff-control-input-wrapper .el-switch{height:26px}.ff_each_style .ff-control-background .ff-control-input-wrapper .el-switch__label{height:15px}.ff_each_style .ff-control-background-head{display:list-item;margin-bottom:10px;overflow:hidden}.ff_each_style .ff-control-background-body{background-color:#f2f2f2;border:1px solid #ececec;clear:both;padding:6px}.ff_each_style .ff-control-background-body .ff-control-field{margin-top:10px}.ff_type_settings{width:100%}.ff_type_settings .ff-type-control{display:block;margin-bottom:10px;overflow:hidden}.ff_type_settings .ff-type-control .ff-control-title,.ff_type_settings .ff-type-control .ff-type-value{color:#808184;display:inline-block;font-size:12px}.ff_type_settings .ff-type-control .ff-type-value{float:right;width:110px}.ff_type_settings .ff-type-control.ff-type-full{width:100%}.ff_type_settings .ff-type-control.ff-type-full .ff-type-value{float:none;width:100%}.ff-type-control-slider .ff-control-input-wrapper{width:110px}.ff-type-control-slider .el-input--mini .el-input__inner{height:22px;padding:2px 8px}.ff-type-control-slider .el-input__suffix{right:0;top:4px}.ff-type-control-slider .ff-type-slider{clear:both}.ff-type-control-slider .ff-type-slider .el-slider__input{width:110px}.ff-type-control-slider .ff-type-slider .el-input-number__decrease,.ff-type-control-slider .ff-type-slider .el-input-number__increase{align-items:center;display:flex;height:20px;justify-content:center}.ff-type-control-slider .ff-type-slider .ff-type-custom{margin-top:7px}.ff-type-control-slider .ff-type-slider .el-slider__runway.show-input{margin-left:8px;margin-right:127px}input.ff_mini_input{padding:5px;width:100px}input.ff_mini_input:focus{outline:none}#ff_preview_header,.el-popover,.el-popper,.styler_wrapper{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif!important;font-size:15px}#ff_preview_header button,#ff_preview_header input,#ff_preview_header optgroup,#ff_preview_header select,#ff_preview_header textarea,.el-popover button,.el-popover input,.el-popover optgroup,.el-popover select,.el-popover textarea,.el-popper button,.el-popper input,.el-popper optgroup,.el-popper select,.el-popper textarea,.styler_wrapper button,.styler_wrapper input,.styler_wrapper optgroup,.styler_wrapper select,.styler_wrapper textarea{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif!important;font-size:12px}#ff_preview_header input[type=color],#ff_preview_header input[type=date],#ff_preview_header input[type=datetime-local],#ff_preview_header input[type=datetime],#ff_preview_header input[type=email],#ff_preview_header input[type=month],#ff_preview_header input[type=number],#ff_preview_header input[type=password],#ff_preview_header input[type=range],#ff_preview_header input[type=search],#ff_preview_header input[type=tel],#ff_preview_header input[type=text],#ff_preview_header input[type=time],#ff_preview_header input[type=url],#ff_preview_header input[type=week],#ff_preview_header textarea,.el-popover input[type=color],.el-popover input[type=date],.el-popover input[type=datetime-local],.el-popover input[type=datetime],.el-popover input[type=email],.el-popover input[type=month],.el-popover input[type=number],.el-popover input[type=password],.el-popover input[type=range],.el-popover input[type=search],.el-popover input[type=tel],.el-popover input[type=text],.el-popover input[type=time],.el-popover input[type=url],.el-popover input[type=week],.el-popover textarea,.el-popper input[type=color],.el-popper input[type=date],.el-popper input[type=datetime-local],.el-popper input[type=datetime],.el-popper input[type=email],.el-popper input[type=month],.el-popper input[type=number],.el-popper input[type=password],.el-popper input[type=range],.el-popper input[type=search],.el-popper input[type=tel],.el-popper input[type=text],.el-popper input[type=time],.el-popper input[type=url],.el-popper input[type=week],.el-popper textarea,.styler_wrapper input[type=color],.styler_wrapper input[type=date],.styler_wrapper input[type=datetime-local],.styler_wrapper input[type=datetime],.styler_wrapper input[type=email],.styler_wrapper input[type=month],.styler_wrapper input[type=number],.styler_wrapper input[type=password],.styler_wrapper input[type=range],.styler_wrapper input[type=search],.styler_wrapper input[type=tel],.styler_wrapper input[type=text],.styler_wrapper input[type=time],.styler_wrapper input[type=url],.styler_wrapper input[type=week],.styler_wrapper textarea{background-color:#fff;background-image:none;border:1px solid #dcdfe6;border-radius:4px;line-height:1;margin-bottom:0;padding:3px 15px}.ff_form_style_selector{align-items:center;display:flex;flex-direction:column}.ff_form_style_selector_head{align-items:center;display:flex;justify-content:space-between;margin-bottom:14px;width:100%}.ff_form_style_selector_head .el-button+.el-button{margin-left:2px}.ff_form_style_selector_footer{margin-top:10px;width:100%}.ff_form_style_selector label{margin-bottom:10px}.ff_form_style_selector .el-select,.ff_form_style_selector label{width:100%}.ff_form_style_selector+.el-collapse{margin-top:15px}.ff_form_style_selector .overline-title-sep{margin-bottom:14px;margin-top:8px}.styler_wrapper{position:relative}.styler_wrapper .ffs_save_settings{position:absolute;right:22px;top:8px;z-index:999}.styler_wrapper .ff_each_style{padding:0 0 15px;position:relative}.styler_wrapper .el-tabs--border-card{background:transparent;border:0;box-shadow:none}.styler_wrapper .el-tabs--border-card>.el-tabs__header{background-color:transparent;padding-left:22px;padding-right:22px}.styler_wrapper .el-tabs--border-card>.el-tabs__header .el-tabs__item{background-color:transparent;border-left:0;border-right:0;color:#1e1f21;height:auto;line-height:1;margin-right:30px;margin-top:0;padding-bottom:14px;padding-left:0!important;padding-right:0!important;padding-top:14px;position:relative}.styler_wrapper .el-tabs--border-card>.el-tabs__header .el-tabs__item:after{background-color:#1a7efb;bottom:-1px;content:"";height:2px;left:0;position:absolute;transition:.3s;width:0}.styler_wrapper .el-tabs--border-card>.el-tabs__header .el-tabs__item:first-child{margin-left:0}.styler_wrapper .el-tabs--border-card>.el-tabs__header .el-tabs__item:last-child{margin-right:0}.styler_wrapper .el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active,.styler_wrapper .el-tabs--border-card>.el-tabs__header .el-tabs__item:hover{color:#1a7efb}.styler_wrapper .el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active:after{width:100%}.styler_wrapper .el-tabs--border-card .el-tabs__nav-wrap{margin-bottom:0}.styler_wrapper .el-tabs--border-card h4{font-size:18px;text-transform:capitalize}.styler_wrapper .el-tabs--border-card hr{background-color:#d5dadf;border:none;height:1px;margin-bottom:16px;margin-top:16px}.el-popover.el-popper{padding:12px}.el-popper .el-tabs__item,.styler_wrapper .el-tabs__item{padding:0 20px}.el-popper .el-select-dropdown__item,.styler_wrapper .el-select-dropdown__item{font-size:14px;padding:0 20px}.el-popper .el-button,.styler_wrapper .el-button{display:inline-block;padding:12px 20px}.el-popper .el-button--small,.el-popper .el-button--small.is-round,.styler_wrapper .el-button--small,.styler_wrapper .el-button--small.is-round{padding:9px 15px}.el-popper .el-button--mini,.el-popper .el-button--mini.is-round,.styler_wrapper .el-button--mini,.styler_wrapper .el-button--mini.is-round{padding:7px 15px}.el-popper .el-button--mini,.el-popper .el-button--small,.styler_wrapper .el-button--mini,.styler_wrapper .el-button--small{border-radius:5px;font-size:12px}.el-popper .el-collapse-item__content,.styler_wrapper .el-collapse-item__content{padding-bottom:25px}.el-popper .el-button--icon.el-button--mini,.styler_wrapper .el-button--icon.el-button--mini{padding:7px}div#ff_preview_header>label{display:inline-block!important}.el-button--mini .dashicons{font-size:12px;height:12px;width:12px}button.ff_align_active{background-color:#8bc34a!important;color:#fff}button.ff_align_active:focus{color:#fff;outline:none}.file-input{background:#fff;border:1px solid #ececec;border-radius:4px;color:#606266;padding:5px!important;width:100%}.file-input::file-selector-button{background:#f2f2f2;border:none;border-radius:5px;color:#606266;cursor:pointer;margin-right:6px;padding:6px 16px;transition:background .2s ease-in-out}.file-input::file-selector-button:hover{background:#ced0d4}.overline-title-sep{color:#606266;display:inline-block;font-size:14px;font-weight:700;padding-left:10px;padding-right:12px;position:relative;text-transform:uppercase;width:auto!important}.overline-title-sep:after,.overline-title-sep:before{background:#ced0d4;content:"";height:1px;opacity:.4;position:absolute;top:50%;transform:translateY(-50%);width:134px}.overline-title-sep:before{right:100%}.overline-title-sep:after{left:100%}.ff_form_style_import{align-items:center;display:flex;margin-top:12px}.ff_form_style_import .file-input{margin-right:10px;min-width:204px} PK! ::public/css/payment_skin.cssnu[.ffp_table{border:1px solid #cbcbcb;border-collapse:collapse;empty-cells:show;font-size:14px;width:100%}.ffp_table td,.ffp_table th{border-bottom-width:0;border-left:1px solid #cbcbcb;border-right-width:0;border-top-width:0;font-size:inherit;margin:0;overflow:visible;padding:.5em 1em}.ffp_table td:first-child,.ffp_table th:first-child{border-left-width:0}.ffp_table thead{background-color:#e3e8ee;color:#000;text-align:left;vertical-align:bottom}.ffp_table td{background-color:transparent}.ffp_table tfoot{border-top:1px solid #cbcbcb}.ffp_table tfoot .item_right{text-align:right}table.input_items_table{border-collapse:collapse;margin-bottom:0}table.input_items_table tr td,table.input_items_table tr th{border:1px solid #cbcbcb;text-align:left;width:auto;word-break:normal}table.input_items_table tr th{min-width:20%}ul.ff_sub_items{list-style:disc;margin-bottom:0;margin-left:0;padding-left:25px}.ff_sub_smart_ui .ff-el-form-check-label .ff_plan_title{display:block;font-size:120%;margin-bottom:5px}.ff_sub_smart_ui .ff_sub_desc .ff_summary_container{display:block!important} PK! [;O22public/css/form_landing.cssnu[.ff_landing_page_body{height:100vh}@media (max-width:1023px){.ff_landing_page_body{overflow:auto}}.ff_landing_page_body .ff_landing_wrapper{align-content:center;align-items:center;display:flex;overflow:hidden}.ff_landing_page_body .ff_landing_wrapper.ff_landing_design_modern .ff_landing_form{background-color:#fff;border-radius:8.5px;box-shadow:0 30px 40px 0 rgba(0,0,0,.25),inset 0 4px 0 0 #a1c5e5;color:#444}.ff_landing_page_body .ff_landing_wrapper .ff_landing_form_wrapper{margin:0 auto;max-width:740px;padding:0 40px}@media (max-width:1023px){.ff_landing_page_body .ff_landing_wrapper .ff_landing_form_wrapper{padding:0;width:100%}}.ff_landing_page_body .ff_landing_wrapper .ff_landing_form{box-sizing:border-box;padding:30px 40px;width:100%!important}.ff_landing_page_body .ff_landing_wrapper .ff_landing_form .ff_landing_header{border-bottom:1px solid #e6e6e6;margin-bottom:25px;padding-bottom:24px}.ff_landing_page_body .ff_landing_wrapper .ff_landing_form .ff_landing_header .ff_landing-custom-logo{margin-bottom:29px;margin-top:12px}.ff_landing_page_body .ff_landing_wrapper .ff_landing_form .ff_landing_header .ff_landing-custom-logo img{display:block;margin:0 auto;max-height:225px;max-width:100%}.ff_landing_page_body .ff_landing_wrapper .ff_landing_form .ff_landing_header h1{color:#444;font-size:30px;margin:0 0 9px}.ff_landing_page_body .ff_landing_wrapper .ff_landing_form .ff_landing_header .ff_landing_desc{color:#444;font-size:16px;font-weight:300}.ff_landing_page_body .ff_landing_wrapper.ff_landing_layout_default .ff_landing_form_wrapper{padding:0;width:100%}.ff_landing_page_body .ff_landing_wrapper:not(.ff_landing_layout_default) .ff_landing_form_wrapper{padding:0 40px;width:50%}@media (max-width:1023px){.ff_landing_page_body .ff_landing_wrapper:not(.ff_landing_layout_default) .ff_landing_form_wrapper{margin:0 auto;padding:0 0 40px;width:90%}}.ff_landing_page_body .ff_landing_media_holder{-webkit-touch-callout:none;text-align:center;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:50%}.ff_landing_page_body .ff_landing_media_holder .fc_image_holder{display:block;overflow:hidden}.ff_landing_page_body .ff_landing_media_holder .fc_image_holder img{display:inline-block}@media (max-width:1023px){.ff_landing_page_body .ff_landing_media_holder{margin-bottom:50px;width:100%}}.ff_landing_page_body .ff_landing_layout_media_left{flex-direction:row-reverse}.ff_landing_page_body .ff_landing_layout_media_left .ff_landing_form_wrapper{margin-left:auto;margin-right:0}@media (max-width:1023px){.ff_landing_page_body .ff_landing_layout_media_left .ff_landing_form_wrapper{margin-left:0;padding:0}.ff_landing_page_body .ff_landing_layout_media_left .ff_landing_media_holder{margin-top:50px}}.ff_landing_page_body .ff_landing_layout_media_left .ff_landing_media_holder img{max-height:75vh;max-width:720px;width:auto}@media (max-width:1023px){.ff_landing_page_body .ff_landing_layout_media_left .ff_landing_media_holder img{-o-object-fit:cover;object-fit:cover;width:100%}}.ff_landing_page_body .ff_landing_layout_media_left_full{flex-direction:row-reverse}.ff_landing_page_body .ff_landing_layout_media_right .ff_landing_form_wrapper{margin:0}@media (max-width:1023px){.ff_landing_page_body .ff_landing_layout_media_right .ff_landing_media_holder{margin-top:50px}}.ff_landing_page_body .ff_landing_layout_media_right .ff_landing_media_holder img{max-height:75vh;max-width:720px;width:auto}@media (max-width:1023px){.ff_landing_page_body .ff_landing_layout_media_right .ff_landing_media_holder img{-o-object-fit:cover;object-fit:cover;width:100%}}.ff_landing_page_body .ff_landing_layout_media_left_full .ff_landing_media_holder img,.ff_landing_page_body .ff_landing_layout_media_right_full .ff_landing_media_holder img{display:block;height:100vh;margin:0 auto;max-height:100vh;-o-object-fit:cover;object-fit:cover;-o-object-position:50% 50%;object-position:50% 50%;width:100%}.ff_landing_page_body .ff_landing_layout_media_left_full,.ff_landing_page_body .ff_landing_layout_media_right,.ff_landing_page_body .ff_landing_layout_media_right_full{height:auto}.ff_landing_page_body .ff_landing_layout_media_left_full .ff_landing_form,.ff_landing_page_body .ff_landing_layout_media_right .ff_landing_form,.ff_landing_page_body .ff_landing_layout_media_right_full .ff_landing_form{height:auto;justify-content:center;margin:unset;max-height:calc(100vh - 100px);overflow:auto}@media (max-width:1023px){.ff_landing_page_body .ff_landing_layout_media_left_full .ff_landing_form,.ff_landing_page_body .ff_landing_layout_media_right .ff_landing_form,.ff_landing_page_body .ff_landing_layout_media_right_full .ff_landing_form{height:auto}}@media (max-width:600px){.ff_landing_page_body .ff_landing_layout_media_left_full .ff_landing_form,.ff_landing_page_body .ff_landing_layout_media_right .ff_landing_form,.ff_landing_page_body .ff_landing_layout_media_right_full .ff_landing_form{max-height:inherit}}@media (max-width:1023px){.ff_landing_page_body .ff_landing_layout_media_left_full .ff_landing_media_holder,.ff_landing_page_body .ff_landing_layout_media_right .ff_landing_media_holder,.ff_landing_page_body .ff_landing_layout_media_right_full .ff_landing_media_holder{position:relative}.ff_landing_page_body .ff_landing_layout_media_left_full .ff_landing_media_holder img,.ff_landing_page_body .ff_landing_layout_media_right .ff_landing_media_holder img,.ff_landing_page_body .ff_landing_layout_media_right_full .ff_landing_media_holder img{height:46vh}}.ff_landing_page_body .ff_landing_layout_default{padding:80px 20px 100px}.ff_landing_page_body .ff_landing_layout_default .ff_landing_form{width:100%}.ff_landing_page_body .ff_landing_layout_double_optin_confirm{padding-bottom:100px;padding-top:80px}.ff_landing_page_body .ff_landing_layout_double_optin_confirm .ff_landing_form_wrapper{background-color:#fff;border-radius:8.5px;box-shadow:0 30px 40px 0 rgba(0,0,0,.25),inset 0 4px 0 0 #a1c5e5;box-sizing:border-box;margin:0 auto;max-width:740px}.ff_landing_page_body .ff_landing_layout_double_optin_confirm .ff_landing_form_wrapper .ff_landing_body{padding:30px 40px}.ff_landing_page_body .ff_landing_layout_media_left_full .ff_landing_media_holder{left:0}.ff_landing_page_body .ff_landing_layout_media_right_full .ff_landing_media_holder{right:0}.ff_landing_page_body .ff_landing_layout_media_left,.ff_landing_page_body .ff_landing_layout_media_right{height:100%}.ff_landing_page_body .ff_landing_layout_media_left .ff_landing_form,.ff_landing_page_body .ff_landing_layout_media_right .ff_landing_form{height:auto;max-height:calc(100vh - 100px)}@media (max-width:1023px){.ff_landing_page_body .ff_landing_layout_media_left .ff_landing_form,.ff_landing_page_body .ff_landing_layout_media_right .ff_landing_form{max-height:inherit}.ff_landing_page_body .ff_landing_layout_media_left,.ff_landing_page_body .ff_landing_layout_media_right{align-items:flex-start;flex-direction:column-reverse;height:auto;padding:0}.ff_landing_page_body .ff_landing_layout_media_left .fc_image_holder,.ff_landing_page_body .ff_landing_layout_media_right .fc_image_holder{padding:0 40px;position:relative;text-align:center}}.ff_landing_page_body .ff_landing_layout_media_left_full,.ff_landing_page_body .ff_landing_layout_media_right_full{height:100%;padding:0}@media (max-width:1023px){.ff_landing_page_body .ff_landing_layout_media_left_full,.ff_landing_page_body .ff_landing_layout_media_right_full{align-items:center;flex-direction:column-reverse;height:auto}}.ff_landing_page_body .ff_landing_layout_media_left_full .ff_landing_form_wrapper,.ff_landing_page_body .ff_landing_layout_media_right_full .ff_landing_form_wrapper{margin:0}.landing-page-settings-iframe.ff_landing_page_body{overflow:auto}@media (max-width:1023px){.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_left{align-items:center;flex-direction:row-reverse;height:100%}.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_left .ff_landing_form{height:auto;max-height:calc(100vh - 100px)}.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_left .fc_image_holder{display:block;overflow:hidden}.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_left .fc_image_holder img{display:inline-block;height:auto;max-height:75vh;max-width:100%;width:auto}.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_left .ff_landing_media_holder{margin-bottom:0}}@media (max-width:600px){.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_left{align-items:center;flex-direction:column-reverse;height:auto;padding:0}.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_left .ff_landing_form{max-height:inherit}.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_left .fc_image_holder{padding:0 40px;position:relative;text-align:center}.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_left .fc_image_holder img{max-height:35vh}.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_left .ff_landing_media_holder{margin-bottom:30px}}@media (max-width:1023px){.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_right{align-items:center;flex-direction:row;height:100%}.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_right .ff_landing_form{height:auto;max-height:calc(100vh - 100px)}.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_right .fc_image_holder{display:block;overflow:hidden}.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_right .fc_image_holder img{display:inline-block;height:auto;max-height:75vh;max-width:100%;width:auto}.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_right .ff_landing_media_holder{margin-bottom:0}}@media (max-width:600px){.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_right{align-items:center;flex-direction:column-reverse;height:auto;padding:0}.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_right .ff_landing_form{max-height:inherit}.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_right .fc_image_holder{padding:0 40px;position:relative;text-align:center}.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_right .fc_image_holder img{max-height:35vh}.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_right .ff_landing_media_holder{margin-bottom:30px}}@media (max-width:1023px){.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_right_full{align-items:center;flex-direction:row;height:100%;padding:0}.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_right_full .ff_landing_media_holder{margin-bottom:0}.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_right_full .ff_landing_media_holder img{height:100vh;max-height:100vh;width:100%}}@media (max-width:600px){.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_right_full{align-items:center;flex-direction:column-reverse;height:100%;height:auto;padding:0}.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_right_full .ff_landing_media_holder{margin-bottom:30px}.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_right_full .ff_landing_media_holder img{height:35vh;max-height:35vh;width:100%}}@media (max-width:1023px){.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_left_full{align-items:center;flex-direction:row-reverse;height:100%;padding:0}.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_left_full .ff_landing_media_holder{margin-bottom:0}.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_left_full .ff_landing_media_holder img{height:100vh;max-height:100vh;width:100%}}@media (max-width:600px){.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_left_full{align-items:center;flex-direction:column-reverse;height:100%;height:auto;padding:0}.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_left_full .ff_landing_media_holder{margin-bottom:30px}.landing-page-settings-iframe.ff_landing_page_body .ff_landing_layout_media_left_full .ff_landing_media_holder img{height:35vh;max-height:35vh;width:100%}}.landing-page-settings-iframe.ff_landing_page_body .ff_landing_wrapper:not(.ff_landing_layout_default) .ff_landing_form_wrapper{padding:0 40px;width:50%}@media (max-width:600px){.landing-page-settings-iframe.ff_landing_page_body .ff_landing_wrapper:not(.ff_landing_layout_default) .ff_landing_form_wrapper{margin:0 auto;padding:0 0 40px;width:90%}}.landing-page-settings-iframe.ff_landing_page_body .ff_landing_media_holder{width:50%}@media (max-width:600px){.landing-page-settings-iframe.ff_landing_page_body .ff_landing_media_holder{margin-bottom:30px;width:100%}} PK!%e(n(nApublic/fonts/vendor/element-ui/lib/theme-chalk/element-icons.woffnu[wOFFn( ڔGSUB3BOS/2<DV=IcmapT*8 ҩglyfY+Bheadbp/6"hheab$hmtxbddlocab44}`maxpe  1namee,JaÌpostfx sxc`d``bca`tq a``a cNfz"P ʱi f#Oxc`da`tB3f0b```b`ef \S-x~C sCP$W Nxu]R`ˠ vw3(%H#vw9& &֋u]wP%zޢG}x-xEzy5?ĤKcyV>;f쑽O.%V>g@ 1;Ŋ!;e왽o.>/}NlBOgGaV~5]WN^cm}'uG}61MhJ3ӂb Zӆ=kk+zlFlYw6e39؂lVl6lvlN.K7{{^A!aQ1KC_xNDq's rsgrgsrsrs rsWrWs rs7r7s rswrwsry@1!#>>3> n/oNXOg~W~w`URSjڥN[:ƥIiZEiYZ5JҦ-S/5kT?oSLO1ЪAV%E *Ab $Eb$ObU#M,1ʪWM11DcM61M;1M@L21ٔ SBSMYAL3tS~3LIB4e 1˔.lSsLC5e1ϔB|S LD,4eȔVbSnKL F0/)LL|lJgSN̔'09d'Ҕė'2>oL]@|kj;S?KMMA,3u=L=B,75 -O!V LKд ȍLشMLldӊ 75 r3Ӳ 6imL´@-BniZ%V}BnmZ*6BnkZ/vCnoZ4mChZ9NClZ>. D0!iL mJ䮦DfO%EaT䞦uEeYަEc^侦FgceF`h䁦FdmGbr䡦UGfwᦥGa|䑦GeځѦEHcچ䱦H1Ei9Ǚ6$yiM'v%yiaL[<ɴ:ɓM<ŴDSM<ʹNM;<ôX3Mە<˴bɳM{<ǴlsM<ϴvM M[ȴɋMĴKM̴M;´+MۚʴɫM{ƴkMδMM[ɴɛMŴ[MʹM;ô;M۟twe@kLyn 0]䃦[|tU ӥA>j9L!0]$dmB>iRȧL 9tM7 9t͐Mw 9tOnr!r"Gn"r:"G$rb"kաo VΟhIVƪ*'[:Z:[:gZ:Rul+UϱRu\+UϳRu|+J TJKax `[Օ0}Wk-[bIv+eIvω:!C$@Bh%Jô`H˰B,[(˴R:Pv:_i;tX$'}ng zDB/ lo2u7`4I&zfOh{r]H?'4X^utu퇚;ח|tc̞ l>h5ۏ[Y,19HY}}[?/i>ټQ , 35AIVa;5 ,( uBd3D,5\^Zsh"H5Hr A|Plv;"D ٕY"g ɶǂnrd۳q|_q|ͭ.&.4 R mv`2$5P1$?@jm"4=AnUηg,ʹFۼC -6P趏"d p^V貑qKq'll6p'? #JF|ɰ{<1'Z8;i@CCM3|{ft?ٶgc_nu:ەq-z Ą0Sea{^4@$D &M<\aơYlAl HɬnF6W4Ҷ ]6FW3^/zp䓿s LD! Ce3B"tY) >{u;dX]'X}ơ>"f P'_:_:oL`.(,-MfUMD<*N.랐>ҥ5,@Х~]^[,fMZ #X(oito9Ioއ`շRO^͟%j&N եuiI 9af\a x>@4^90j9~服ߋw \ d. _**Nݛۮcl]p^ao+-ͣyv}{o\~ l[-_߬qhdAh4̧y2a·R ;(H(nJ̥ 49(\)DL"F$pInvGw8CI]ɡo3cG6cM%f́>gh4mQclv}yv.Gl40W!E䋑5V?t#mg.G*s.͸uΣ#@Wsnsr&EHH'6.3N>iYaq,(! e"QD F2j b>_"L̠?Jlm2 Ww7ZH?־:ɴI&xz'j$ 츆}]xG;[8;$O:5 Q5hj kLksn5 j!Wh2}-޲DJV0NK&#}P1ָ|$1(QAǩq~'ɲ u~B!?~Wպc BTu/=ݻ ,:Eidvco0J߹ݷ9ݫ‰s64\g} Ťt}zGKnuevYRuӇ6Q.Ahj'pաb4D*_.QȬs2еEh4Z@:YTF)aVWػq.|KX'(]TzׄdꮕDnx0 \+C {K!>aNdstT$A[!6 J%+AAKiTJL>)zd)C4Ey&!W:@rba ΉL<Y )BA,8@5Dh1rQ_1H mcy_6gF#f`/4ލ ^zBNfLAnq@J9Nd#@@|4hcE(2ܐs;ogO|6{yh!$V& IC4 :/,G Eqºur#z"5GIȸoYGZLo:Pm6Ӿnj+t`q5%Jv8h}B r}i]<2CC ;@ f0%x#2e@@,8`JFMݳ˖,_>*}4k ;V[,ŧd~k,}UQ p]Z~:B-Mwaݖ-u?Fr~}n\R&qc z~p[)iFckpH sY}lej$=C Ab&X1K$?xR)ޣ Dclfkн[zY~MFwil7Wt:!os!/z걃 ghL&vfmX4ݐ8'V6{4ߥݍcF!<- \':.. ԃIqE=BGETL≡$8/ߕJsLK%m"n!}i|}KQQW/ _892s]×kf{-ݿ Vr??Z`d3U(ϵU-iGχ;(i_"߶||Esݴ([nrɟgV]@Y'$a`Eir%qAt O9hD"4l0(  0p{Ζ]Gbʇ?e[>\>pȏ7l2E}iי4Z1< {ˎ/Xf+EΊ=k-ouq/-F4";lnidJ3v7-OLByY?!jf}#F|p Q R榨n=xt.AQKeryF[k&-zE.$ɞ%yoHd25+N3K0󈡱C)dFSEooI˙?|U6GQ'uNH-j(0#0]Hxw&WuGJt?>vY7;\O?L\±t?&`kk0>$߁r*/$PpH<ʰmnC_eV 0`ظ掯m; 0{ =$0dVZ1ڪs*\ RǐFp`&k޻ +]'!|JGl]2_s,wv={)+Gݗ\gE;@\CӪF..m}k KrGa26^;g \T\(vQwj3\E]9dP |Y*hEtYYv>(  yt(v#{:}7{MGmx~+Ϣ^ؘ8H&`za []o6^ohMLy!Bx mSܛ5Ž򍮡!e,2F x6.@v ^Q \XuN=ָ"45ZӢk;ʊ>\-h6}:H]韬zӗM~tbա[: A0&dVTE#Q*L)񑟷֘t/g?ҋi7Lam_`d']%a0&@=Fh/F^{!f{@`*텇?p_h~ o(IP9?`i43Cfa̜y4u.fL5yRS)(^':1ȕir(p.2Zچ -n{ѓMQKa亪˵@R^57 @_ |;kI(:G` {炅AI5׍zztA=FGf3xA< xIfO(oeihĸn=:(D`{&9$U>`BѠRJ(JpV4?`BKy TЋk%<ᘗ^_} gyT1}pMgdK:HX]=Rq^1ߓ/>s/1o߾:|b̔Y+0U$UKֺvS丗=B鑽cˢ}U_}BTe易;@_Zcɘcro΃tk7fx=}$oGD!s{opxh?uoಥA"Y/,¡\ZLuyT$J:}[,#dـ_nZ+|Wq`,LU{*vx7EC73j'_+Ni^vni0hE"ƔM,@KqE<|1^p"Y#&H\ANEZBD PfA9j]dhDVhie08ȐC hi2! ph(6So G d$3A-}Tq0rsKD!Gh!4_Y'N q$\@AsnGG蟙^@GGD̀!dlf'f[7&,?jrSHz40ߎ0@yfƕ0p RHr2t;\47LdLVr- oBeE9(݂Ym7Pr]J{Y>sʱlDZB ڡdhbE4}MC@p&T= uWڛƢJSh.r2#X%3 " p MM'K@Q+' ŋ̌]1\gjUFߢJX~;u:R4i*;vZ/پAy *ޝ`Jb)-Gz2 IWB4eZD~_5#!Eq4PQ_T~.i:PwsEPLc3]a7> @_s@_$d:$U% @qtY 7o !y@|!nnrAhUol DcaM޺5k+tۛ׃K&9y2gR7xAU#g\qkBau>,#0b:QL:wSLFq] fdm.0L 9/G**"]y|.yV73fPb0Vge&0UTW)6<4bwf(d `;Z?I'HA9s"^30Oh,Ab 3N @:KQ!qNV]# OxG_U~b!=FE(1y!ꡪ'yC+H9B/E:q˪ڵͳ|ҹfccƄ c˶C|^(=`rx"GYR o?ymI{d{X,'8cqnApw +>ơ7ۂK|uR9 s'/O TcHќ :ܿ_W\Ӈ_Kw'zugm3#K_ޭ3MR|xy۱gu?!\~W|᳈#; 2Pnxߵ-X7v4v9oi|S7?Lnص--:%Wl#wݱ^,9{/jW[ 4di Q-:K`;Ԣ$3Hs Y2 Ev^iN.:``6:&k6^LţG0;fM=b:k(iv_:x N[#K[ӰB~i~|M ۄk{*@#SSa gMT]pL׹T]d&vW-hfXV)siG ]*N)s#}N&zA2(S@:7Fă$1QE8m+H7m_cXY!LLƳ[yͪUkoeK,*40>G ,VFtH\zͺ.f<\L;yÔ tsvD #Y¦*\bTo#0)b3w6YڇWuYrYw{׎=֬)|%hNu сCmF9[)/Yrɗa޵~rMDs16`BǑZe3 rJ#;IEl_Gɚ& cݦc>3xfl7d-Jܶ%1l߱`N ,$-uu'h3lOM 3qy}eK~j :L0ƥ lEQ+IwwFrJbgw}sI lJ*"+Q["ŭ:VQ  俐:wcOMIdu}$n#v71U*ӹ8P~Ի3 '#>3it[YnDx䦓BQ m )yx&˃Ū/ ŢRlGmZuXzQ.\1k޽Q=Ir(k8\3< oҏkG{!Sv2HzjֽR*jxXqV!?m@c3ځB~wZή4)K dUK,Q Y E *8)uڣgĆJQYIi!άVIYpYҸh9W@r&'eח ϋX=BP0WX^{d(FĒD]^,xb(#jVK6_q }3b={O=%m[R l;֣=g[[f-fh+0@xٚ"(ojF zO&JU soM9"rKIvx(Ol~H&8_7KH[(*=~ '\$YTߢz̖r^SWTRU9  Ԃ {s-\gT,6z6N dl(\y>yjvt&O9@N 8_ծqSX 2jEϹE3?85vO+kkZ/*Yvh@N'[Otӓ"ٹv-zKMlu ;-Cî22T[*jc|[k#&GM6 Ѹ£.mGm;^Tt{9VRz>YqJpE+/@ TY{RGS'ZHV E e^֗N}A0%PU3k&ho\gzo"rpř84.\=l7@2&Qi U)"QFst[g=K6Y"K3CvKsqȘ֬@%^|Z"_{%\(5sLtFj}b-Jn(t#5ai)YbDa.B$M&_ꋄ{,?^uaѐ2#K4ݼ'ҜKLQa,7hJtY^n_o9ꎅxօb^NJf=jQ{U53M*3!C^/[\ vsL'/Kf:GI=5Gqk&knɲNN<,+` ӆԆ: K,2Ub=d׬$zPDqٚ-4 ]&logu{T3# y>ӚȨUkbzbm!DNC&)#Z BFy'Ų9Q+LG\ևS&ߒԹ A"EA8czD ?%a,@^pE"M/pMdMl\w%BAeFW, m*.Zkf>0M7<_>qCҠ# /Z؂EMcg5E42^p1O !s!(nѡ2hg>0Yyʇ^> wّ}K@F.](>sӚ!DX]l:;Ug]1&?AnjbYۼo oxp߂F|RFr}w$s]=tt ;;SʏN~(rye~j\8d󳄵@os `I]i x!"a/h*|f&B".!bx/U&:Dkzwp`59uοuv4,|coeoW}h֍o4F_K!]elIQco.:4Kj]8]Ӈo#wu,N 7jNt.IFbbio5Gۢ{[lfxBtFoyD#Nqbu:g>H&w<^;a!t|=o^4# 6WXҜOó悁a5\\0v EnH~OǜCs,Mx9sq?AL. (j8UN(T(ˏ0j{8%(r Q:Y'k'tIDp63ƫ4=[-s+ʡtb;W^yw\y;g뮯/elңp Z>FVgٯ&|lOjkp!|QRŸY~*DxJPĝTqܹe+--;Y엚-IKW}8%<,胃ԖDeʙD|\>&gDi[gc4~5<ùLMY;_Iun]ˢ10\Բf@Ԫbj}Ujh}:5@ 2XѸZTp񃛦9T5.wk:LZh-eoh"p&(i*j>ZNW3vo%kb8%ɬ$6`oj(xjz(rOLkE= {egk&AɖM`3”>UNAH/$/khC )P,"B-P.H  Z;r%_\f8q)v?0A ySz1O|c"e[۳6~u`3-$IΈݩwt٣\lvSZgΒ#pCBUء}1F—(l”p*3|_,Ā V3vz:h,m>N8sRH]Er׉ajCRq,] zd\ʪluc 4<唕&vv;K#2!)=v^TNRj 5ޯPҕ J1|7I!fl KWm8/ Y~c4G=N$l AIPVhwutvߥ_g NpO|dN+)>2bN0]m[[朁ϮwǧwDdJ1ۛ erk)dBe}GWYY+xʬ)p,bQXP%hadU rithӇq˂qG5$%m!?~.|riOQ&*[=Umeru(nYcE+8\/(uZϑ#Gio=R_ | .2`L> *P洽M6Vx=e^eg֢A^A;:˃XEgt]ځL`?ɯ\Xŷ{m5ڦ߾o)[W6֦{λ^^o[3)AR.fQ [OoLej)ߨОP𓤎K\S>:Jlp/LpvD2}3̎B*`j+)mMNbBpŏdq|'?Cs0t;7.7C^ޜnS!05POss/@ ?m=P >i_?pO00 bIDy@pEC1Rj8TMW=9!EYh[t>?wP\st5EN~Ld1WO$ }T-:ǖ G+DZʓNٹaoCjl>ǿ ~?믱_ݎSp=nj/hJ*םщ)2BB$`sav*d! p)"\@{X8ˏwDT ާThj%_ntA'|oISfGl7ڻY -qT~^;F0~md5 Z#[URjm{s:oAۚS_V_j>ղ"W.jdg9sd67yP%GhUZ_ pd&&I|Pn3\q(w9K/hYA6oA/awh?9cv WF,vT/If>OrOo T(A6`xd"9e?he$тR(7.X@c7J&=l5ZhQ srL$\xHp`+VKOк\ok&ݨֿ_02gA)'u7IxA"5Lw/pP`5J?]fEtCy Oձ1Ůp<Md꫏Ehǒ&x͑ͳDq5$T]G\v.76w:4}f7:?2:DlF6x%iY.?&IzUoЮ"pwa GToa(cʑt6犸"d ؐ(z予CY%fq.`傘z~ v}hpv3u W6y韶s4^FCI) úyy7#D9 KT\rRa#j!'ԛTj%h& s#ZClkB0 @f+Rk(ǦiTc0(Dywn vf';QiL&#tpw͋j4QL)rl8|3A==Wڈ_7Ta)=O|Y 4M!h{p픋u"A!<-Er=@]yPϟ!2A#@`ްCƕ5ݏW%Q}P&j<1 CL%)55sd =U*6ʠxr ;WI2Ϗ%y Bt}+:|LyC +W@(*mt 4ƶ^M[cָ|Ճ#m*(CŅEG!;@"vVa{p 4(7a`oIu;FZ(mL: FRZ^K*r_ڨT.hG4~))pwUf&$-v?k0*,h^jYQZ"s&Ă`tZJ4F ͮir-MiצMsLfMXh::#P5B>|D9!LZ۱mb4"Y ]3OOq`FdiEf?' ɻN&>OMoX&\R(4((Sz#Y?0Jf tƐyM:)e*Ř(8z"^\ P hQ;2j /Ry\^R٪?]4Ū`Tl+ebϡ0j%~(x`34o0$154pBi9R;⎍$GQч \ (#(&1hE2q8_ EUXy!E 'Y2.IᶣVR p( [ʷ9}JX:EfGSM-+KV(=X%aKERP&t]V\O s^A{EcM9>NyV, X]Rb$ԋ&\Յ'kxҘCOxs<)Y;J{SVئ-kczi( p] knGBA$-g焀#L5$6ƔUڑ@:K`P<G OI կb'Ώ dGN xB~,7Ĩ&2?D#h_!BfmrXAFM*>za {*-+(%Ŕ$Qİ۷Vy)y/= .qꒄQ@7Cag} V,%r,TkVąq؎)LI66nT5az1%hPA-S` Q@ðcfI;҄bE|^L9nq,f* Aޅ)—(ld?P*bTZEsJEPq,RZvO`97!ĘLV@?[-P|VcDHr)"}t'_?'`HY-(=w3iQwd6@⊹bSQKWdB]"8PH) }gՐ8SuMgmdO w>Nz$I5(V/h`0Ih[F%hVeSn M{t?H8r墌htS*7_.qoD$+Ӣ-/]QzA70^fUU#:3=ER,(閿/]wI벭Ycsy uB+[ĈbhH$ÓDjEwOQ<.|T>,JwwDޞSfu tDK>j41d$;\rD魁P34ݽb҃;6-V1μq0 4{ީ_r`~睆-XLtb <JO&Ic%pIGS6h俊3lEd NfCC8Y5N}q$tpYنTŸO̩o4|qk¯™I%1XU1|ld[<0 Y-6yfnQ,Q"pk_4W/ ~]9Z90 PRXU6V1wJRׅ{1I:!bx4MB~H1bw?o>.8p"SETD)6$*7ю1!)‚ n=3">)yl*)r_S|d=75%KG&w@F2Tϒ77Iu[dISٟGbEfy0̴(rpN~s#@p _mbS9M \'AZ+sbɘ1U[`[a$0JE/~]c@ 6JsǫVh0z,MY cuBP^!J#0vHG$z!~\oGBO=kN6;_x75qp?~eĭ_ 텮ܛ+T#|Elc,d.,OH$Usdks0-j0O4}"I\zC2x@uްȽP`D|Ld_sik[HT"Yz0CitVh.]WnX==؜X_^?`NK~V*W- _k .(ӣ=" @]\,uBoCd6?%@4 /?/0"&P"w5AYeL=1%dk8C9^;Đ^ gwo̅*a'8Y ̢tj)*aU+5ZQ/L $YL&K]s;%;k/w"1Ci~O"^ZR?ΛxrʴElWSq8%  N<7(d)UiBXmq  9}ǦCN}ey 3L|#8Qe[70 Cق1&?~%H . %$E" .x.`ڕ|'I(A"3yllO/MbPnߡODvM[4Ff_ZQrwJxm{R~]u[ aFG|Y}}d6H# ~q[{DUl{}*7%B39D JW"F=` ̣¼5`7/e cWV#e ?9ʗŢE%w|8ys A䢡zB[w>0l2\!J pm|P t2 &BI҃2M帪=ƐB.hFa84(qlqLk%(UM$}Vz̉R^[%SBU ,}x/Ȉ~\N{+~P՘n UX$㔸p6sJfqO!/} 6n!Z-1wCjlCX熱Tx,A}>hY>rtr)[|*o'=(0NS&W7̎HDx2d̅<) #3 =O5=_]Vh3.6HjǍxG{jh6a]ktMY->W o!\9O ltj߫/NQ/($->" H{ɧҝ)i{KӣOv,ҡѠPv5nR3z7}j0 zl #j(3Z+4+BE] .6>eB_O_Ryj8< C_"&=ٕ^u`Z$o=fR-2F1S.ހAcJ3@Y5$*1c(J.RPX 66+ 7Ο)C?#\7 #sxKЇ5yúH|N/~)xiM4lc6j%=GYg͋YZ\uΐ5ε[SB .ԵROP<*3ݽLtM&zf[D%X޾fN?L7l'SG""M񡏕X^~  Qh/:`ju 񶱳'Հ򷢳TH$$LJUU@q'2\Fkb3cF1 x-P|nn?trENa{UKyI4WBUN۸IF99ZOTl&q>lk/ҵ, 5ë;8kWa%k7/ ] g_@bbfQ*?; Z+$wJ %B`c@'/{_n?e)h;δ#-H% WٝN]tBY>+ X=L3Ş1I DDI1|8S?N_]Gwfno/w{'9\.5I/O7ZZKir}C_V/•X(}P(h%(J4"iIňXmݻ!ݙٿ3}G|;s$f!15*K0~'ռAzs\g QZ"xvYwZ aQ&8MVc]^m'TV{/׷sh&B::r'%Ud 3iJ :;:?~7)G|v<-2/ ËIvs=67}c5_1=k~ؑ%_W{\_R%(_MyAjjiF rZiq7c9F#qF9},֋. :tZÚ)7 ̈gS#7pZvV:k֑ޖAwցR1/@Q{e[-پ98!8N+EF#؎c^o/>9w!UkEhͣKKkټ$t6o~?mB3<RHFi=g#>Ǐ+̮M{tϓ^ƕM~`k' &" /#[*Jl|fYH ^5+ ƻ1o"N%|q`G _j/HA }]>wZSC@*ogkߏ=LYpPʿ]/Ga= tukiZ-/в趠GK/~m qW{NIZ Y'Z N5>C--0{=_m&D􉋔^٠dB={?E70ʟd_WYJG3.y1d?-cXkcb7UT&5dtt+ىaE8 6,5 Yzܻkвw^0^SM¬ f0 }d=;8ML~Ϗ4!E!uTU^\#N1~0~͸Γ_mZ7sfA(GRi>S+ȼE% r,@\U>c29:l=փ ;xsS;53Zә黼XFDxR39_elߓFѱο<:Fl$.=g'>ĔBf<uƳ.HcxW8TF9e&̐ ( 0ZS(``DLxOqiJ: J.L3R(n H8*!vL!a7ksG ]caNJݧ+cOS"+F$uLr뒹;d=KhIYgv1\K#Q^(cDbcswD e~^䉋U6u&'0"߉xc`d``L6_Y@mL $ 6} Jxc`d``n@0JG!xca```ţxba;en.FnZh<,lh 4 B  v @  ZP dX V2Fd6ZB2bHxd^L\lP Z !!h!" "##r#$$$%&&&&'^''(d())\))*.**+V+,N,~,-*--.P../$/00t01$12L223d34H45556P6778,8z89699::z:;;,;x;<<<<=@=r=>>n>?6??@8@j@AA>A~ABBBCLCCD^DDE2EEF&F`FGG0GXGHHXHHIIZIIIJ:JlJJK K:KL:LHLVLdLrLLM"MMNNTNhNNO2OvOOPNPzPQQ6QvQQQRRBRRRSS0SZSSST Tx];N@)JHAreD)Spuz)%p :~;53;3 vb]f'n{/F#'a p>^=\UA~n߅[6n%ܡ-#=nF1nf9n[V5nv=;N3n`#L!qwPDGa``s'{>/x !x(x$G1x, x"')x*x&g9x.x!^%x)^x%^W5x-^ x#ބ7-x+ކx'ޅw=x/އ >#(>$>O3,> "/+*&o;.!~')~%~_7-~#?/+'?F 608H4ݠA `' SSӂ7kLʷxsaZ* YzP+ˬʌղ6i)Yf,q\BJj"Z0.ḐBEwάХ(TM4E_IޙQ!lޒs;qKw*ֈn{yƛTs{I.F0ݱI}5shEdb*=^\f= EJվЃfLLRl/n9+: ,%OG̈0sSV.m̄'ScΨW\ -oJQٞPj`ҹ>j(%&eT$Wu"Rs*A_T[Zdʡ垫uMpDU0cK;wm+gbvH'˙)ưSf3w'~!W+Zz=^ԟ{]{2*OWLU lMdM9Ǣd#42TuX T֑ %#N=hI#lȕ\^t(d9Rg$5aejLU];\IvDvof͎9wYOLf*ں1+XYdžO*gCUArM`#fّr/q@]hܧZr l_4Tr"CRZE.JvA,#`Hө+TrG CdiJ"sBIG1ӄP$H) KClsEQ%`q V3nJSqdq YQ1ͧq{oL9[d.MHQdN#*AVԇUf9^`:~Z:N\5[c$n.,ЊktYp"B5^)CHCovZOnKa(_4-#;<'Ŷ*$[yuOo&넲dY`,t/CF]n*cMXWAr5aLC]2PAh!i *]vMz&+F m9`EtSUGU+!BsWkU*Eϟ>t](uËZKv4Т$#jMkYgD⩦ޥ8)r2+y꣹;{iCPK!W&Em@public/fonts/vendor/element-ui/lib/theme-chalk/element-icons.ttfnu[ 0GSUB8BOS/2=I|Vcmap8 ҩ8*glyf+Bhead"6hhea$hmtxddloca}`d4maxp1 nameÌ$aposts͈ \i?-_< 罆罆  ,DFLTliga2PfEd@\,, "  +AEa"-DGc""*DR 24h0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ ` a b c defghijklmnopqrst u""v##w$$x%%y&&z''{((|))}**~++--..//00112233445566778899::;;<<==>>??@@AADDEEGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXXYYZZ[[\\]]^^__``aaccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~     n.FnZh<,lh 4 B  v @  ZP dX V2Fd6ZB2bHxd^L\lP Z !!h!" "##r#$$$%&&&&'^''(d())\))*.**+V+,N,~,-*--.P../$/00t01$12L223d34H45556P6778,8z89699::z:;;,;x;<<<<=@=r=>>n>?6??@8@j@AA>A~ABBBCLCCD^DDE2EEF&F`FGG0GXGHHXHHIIZIIIJ:JlJJK K:KL:LHLVLdLrLLM"MMNNTNhNNO2OvOOPNPzPQQ6QvQQQRRBRRRSS0SZSSST T7!+2656R6@)66)@)66)@@@)66)6))66)@)6H+>F&>>53./676&'&>#.'&.?&676'&'75* ;?'@ZDDZ~^^OUW73#5>65>6+"&'#5&/#"!76&+'4&";'54&"3#23!26?`e@p% <4$`$4< %.I: !".I: /(4v4K  K@%c  @ d  '"++"D' %5 &$ %%5 &$ */ / p f  f#.:@5>732+"!!.'.>7!7.7>?%!264&#!"6)@'6/&($x$(&/6'4(P\mR@7G< )6 2N9!!E9N2GSSr A@5 OpX =A37!#33.3732+!.'#"&46;>75>732+"!!@Da@tG@9#p#9@G_6)0 VhaDr8_')6#'7;?CG>7!.'.'5467!.'!!!26=4&#!"3#;+3#3#vv &&!1#r#1!&&bYY0@@@@@@@@@@|ss 2!@!3 u 3!@!2 Vhh@@@@@@|@#',032+#!"&'#"&?>;'463!27!!'!!7 1' < '1  ;G 7b K%%   " ^^@@@@@ @ ")07CL%>7'>7!%.'.'67%!677&'&'.'>7>4&" 74&/.'67676.'>?>#1A,.||., F[ #,   AX 6=Ɩ=6 u}  F1g T.]].T g3HM3(aBN(m@zz@m(NPhC6\63#&/."&'&7>766767>.?.#>7>76'.&X $97HX5"'#6P.J&9#tE/   H  15Z4/9@)%6--5'(3$P 77M: B^x(  @Gn k>G (=  9w  80fS)A61n H>@4@L6767#"&463!2+&'&67&'&'#.'&6>7.'%>7.'*$Mu9$6XzgWWLR"(;SEYg Z[yntDZZDDZZDZZDDZZiI=S;S39sXY ZTV!#:TAWxWZYqwZZZDDZZDDZ>ZDDZZDDZ'7''7''7'73'.'&67,=57.8a jo"w[U||K`(7.86>,woj a`K||U@3<ENW`i>".7.7.>>75#"&46;2+>4&">4&">4&">4&"7>4&"7>4&" 1"gg5L8&?'XlX'?&8L5gg"1@@ )66R66)66R66)66R66)66R66)66R66)66R66,*]nK#LC)4hEEh4)CL#Kn]*,C6R66R66R66R66R66R66R66R66R66R66R66R6@@ #'+!4&#!"3!265!!.'>3#3#@ )66)@)66I@@@@ `6)@)66))6``D@'E7671>25!>7&'.#&#'"&.75463!232#!"&46; 5>'':$)E }{v| 1(%9#)G{@{``q g|r_ccD@&32#!"&46;.75463!2>'5! ``{@{7}}cc,rrA@ &!4'!!>32#!"&46;.'47!%N)YY``}@@@vJ`Vhh~`~A@$32#!"&46;.'47!>74'! ``}@@cmm%N)~`~/mmvJ`I)9D'32#!"&46;5&=4673'&>!>3>.&/# ;^.Ro7`` HB `Rb1 P1T &\[ J00@>moUޫ S  {:E l .`X),?  k)32'#.'463!2>7.!2#!"&463>75Y47[5Ym6II*.lRRl4]f[0Vim``I66IRllR@ #-%!!>3#!.'463!232675.#$$A@(77(@I6@6I@  `$$;6))66II6x^#0=JV!5!;2>=%!#".=462"&=46"&'5>%"&'5>!2#!"&46"5D&f&D5"mf4]H'{ 1VD3&D66D&3m&I]44DffffB #.>7>3"'3!.'!.' %>.kOXXw7D " AP88PXO98Od: XvU (@OjVksX^;8GG88GGxs139GJ: /@'/7>J=4>>76#5.%3&67."6."!36.">7!!2#!"&461= uLLu =1ę@ UrU M%,%%,%~  9*IXXI*9 0aaֹ'F7CC7F'((((}}G1:BHNT"&/&/.>?'.467>27>!767!2?'&"76&?"&&.4."# m.4.#"  n=UZ3iv3vۏ  #'f(m #".4.m  "#=ZGvv a L$,0%>7!.'463!2!.'#76#%6!5@MBM@[dd[$$Z $    @-NN-?;ll;A$$ $ ќ@@>-4?"!26=4!./.=4675>7.'!3!26?  #5 00 5#ۣ=@)  )@ @; 1@. !! .@1 ڞk k@@'-9462>=462"&5.'5462%3&'&"&53#F99F#M@@; 1:V = V:1vZR`@':F462>=462"&5.'5462.'>7"&5>7.'#F99F#FYlRRlYF 3KK33KK: 1:V = V:1ammajTTjjTTjD%0;F%7.'./.>7&676/676.6.?>.^ B &GS; )7 &KOPFR OFO6,V9aw;QD%'"8 %'"9 #PK& 7)  :SG& NGN REQQ#CQ6!.'5&&673>73.'3."36.#"6!3!265%!>7!_@2iY' ",6))6, [@ZDDZ@__~6R6E $5 $anL``YD!> Ac6,E+)66)+E+DZZD__)66)90 &O `zz !)5>7!&!2#!"&467!.'5."H66H~@.٣$6$m36IH724響 $$  ,5#"&463!2+!&>!.'!2#!"&46``^v1 1v٣$@AAV]]VH )32#.=462>.'3>7.'&!]Vkj{٣@n]^W 2M%-0t٣e&#+ )5462#.46;.>73.'>76 ]NcbVp@٣zjk2 R#46nl٣t/.%@  -.'>>7.'7"&4622"&546٣((/@٣٣٬( @LXd3#'''7.'#367'76'&'#37?7'76?35#'./7.'>>7.q+$ VV.++FF++# VV.++FFC -::-"n!&DC !n"-::-"n!&DC !____DZZDDZZ@K>!C6KK KK=!C6KK ' ;@;"-8++0";@; ;@;".7++3";M____>ZDDZZDDZ@!)1?>/.76&/&?75#.'5#.O   F# !lDQi.Q[hnm@lR@l! #F   h[.iQ4@mRl@  )5>>7."&46%.'>264&%.'>264&0??00??0(d0??00??0(<0??00??0(?00??00??((A?00??00??((A?00??00??(('3%6/.>%"&46;2#"&463!2#"&463!2# % R  @@K!  #/&'6>7..'>>7.  ))⪪))____DZZDDZZ44* FF FF5____>ZDDZZDDZ@ &3@MZg2"&=462"&=46%+"&46;2+"&46;262"/&462"/&4"&4?62"&4?62}       E  @/  E     2   ;%'.'367#"&4673"&532#.'5>2>#.'&Wjj{@m^^E] ] Wkjz@m^^eN$-0te%$,J % 2N$-0te%$,3G/&4?6!.?62/!'&462"&4?!76"/&462* # ` ` # *#) % `  `  *#)  ` `  )* # `  `  )`)# `  ` #)&* $ ` `  ))  `  `  )) # ` `  *&@)462&'&471624>1"/"&5   )    )     :`` #,7!>75%!.'!.'>7!'"&462$$@$@$ )66))66)((`$$`@ $$6))66))6(G8?F#"&46;>7#"&546;2.'6;2+.67>7%.'>`23 G7\``>b rr  Cd#19Ɩ6II6I66IdsWZmE:@ppMu"ǼI66I6II@+4J32#'#"&=!"&=#!!"&7>;5>75.''"&=.?62 @ff3Y9 lRRl@I66III#  #` à````@@ VrrV;NN;JJ # # @+4J32#'#"&=!"&=#!!"&7>;5>75.'6"/&>5462 @ff3Y9 lRRl@I66I$  #I` à````@@ VrrV;NN;$ $ # JA#'4A#"&463!5463!2!2+#!"&55#!!"&54623"&5462@@@```@@@@@ !264&#!"` 462!2#!"&5!"&463``` %'& 6." $   #  7'&"?264/76.  #  $  $  $ D#62"&47 &4'62"&47 &4  K  8  K  8    @@     @@ D!62 "'&4762 "'&47  8  K  8   U  U U   264' 64&"a K  8    @@ t4 &"2764&"@ U  U+8  K  2764'&"U 8  K   U  Ut2 27 27564'&"  @@  (   P   e A+46;2+32+&'&6>7.' h }fhiRllRRllh gh sffdlRRllRRl@ 3>7.'.'>75.'!"&=>7!"&RllRRllRmmm6)@)6ZDDZlRRllRRlBmmmm`)66)``DZZD`L,?"3!2654&#%!!.'>2"&=46.!!5>76@@)66))66IvEEV``q]\%@6))66))6'A@ gG@&^VW@,5>"3!2654&#%!!.'>2"&=4675.'!5>@@)66))66IlRRlm@6))66))6@RllR@@mmL!"&5"&4762"'<     Y    A!"&463!2"&562"&47b   @   !!264&#!"265&"264'@    @   a!"3!2764'&"S           !2#!"&46"'&4762          @%4&"'&"2764&"       Z~  2  A%"3!2654&"264'&"`   `7    !%!2#!"&5462"&4762@    )    L #/?>7&3&&76$%3!21#!"514!2#!"&46321+.5146qfbv ?9oq!e`2  @ w>P]?gdMjX@  4 67.77'.'&7J3;Gtߩ> p&w+ d M͍/@O>tl d ⨨+w@!2)&'&67>%!676&'&.>.Vj j>~knkgi3#O`ok8=~#aw]++jjva(-ڄAll$!Oa sOPdK9TUJ7>Bpo)!%!&'&67>%!676&'&Vj j>~knkgi3#O`o@jjva(-ڄAll$!Oa sOPd*/.!2>5.'!.'&67>76! h_ 'IQ jKp*K; W8]qtd maVW =DQ?' tKJ^ ;K*InQ`s~cdTk[ @ $1=JWdq~%>7.'.'>72"&=462"&=4662/&462"/&4%46;2+"&%46;2+"&&4?62"&4?62"RllRRllRmmmm  . #- (  -  . g@@@@ -  .  .  - lRRllRRlBmmmm@@@@} -# .  .  -   .  - (  -  . @ !-&76 #6&'&"3!21#!"5143!21#!"514S([vxxv[(C)HghigH)  @   @  VTTVzNLLNz@ @ &3?K7!2#!"&463!21#!"514'>7#.'2"&=46.?6262/&4 @  @ `Ɩ@zz  D # D   D # D  Ɩzz@``  D # D D # D  &2>7!2#!"&467>7#.'2"&=46.?6262/&4 @ÌAqq D # D   D # D `pp ``  D # D D # D D*7DQ^/.!>76&!".5>7>762"&=4632"&=4632"&=4632"&=46# g_ )APcKLj Vlp1WD$nX}VU \s"]";CO?( _BKc`LLsm$DX0ZRjYOb````````D(=%.'>7>765>7./..?623.? a}nX}VU _s{`FXVF# g_ )APZ $ ee@aZRjYOa`A gGHh";CO?( _BGaH    D*.26:>/.!>76&!".5>7>763#73#3#73#73## g_ )APcKLj Vlp1WD$nX}VU \sb@@@@`@@@@`@@]";CO?( _BKc`LLsm$DX0ZRjYOb@@@ @@@@@ ",312#1"5475''#53%7>=4&/ @@i&00&@c  c@ @ `86&&68 )   @@ $%19A%>7.'.'>72"&=46;21+"5145##5!353!5mmmm @@@mmmmC  @@ '09BKT]fo%>7.'.'>75##5!353!5"&462"&462'"&462"&462%.762.76''&4>7'&>2mmmm(@@@@#  $  $  # mmmmC=L $  # $# # @ $%.>!>7.'.'>72"&'746#264&"#5#"&463!2#٣٣@$6$$6$_@`C٣٣|$$6$$E %6CO%>7.'.'>7%"&7%26'32+"&=462%&>&!6.6٣80 $80 $Z Sn1/;+ .C Ro1/;, @C٣٣C SS S1nS / ,;/1nS / ,;@ *26.'>5>7%>4&".'>7!5!!)! zzƖ$$6$$6II66II$ffoLzzY勋9@Ɩ$6$$6$AI66II66I@@a@ "#/!3!21#!"514.'>5>73!21#!"514  @  zzƖ  zzY勋9@Ɩ a@ ">!3!21#!"514.'>5>732+"&=#"&46;5462  @  zzƖ```` zzY勋9@Ɩ```a@ "+7!3!21#!"514.'>5>7%>4&".'>7  @  zzƖ)66R66)DZZDDZZ zzY勋9@Ɩ6R66R6AZDDZZDDZa@ *.'>5>7%>4&".'>7 zzƖ)66R66)DZZDDZZzzY勋9@Ɩ6R66R6AZDDZZDDZ@ $>>7.'.'>7'2"&546>7.'5.'>RllRRllRmmmmrWhhWr٣lRRllRRlBmmmm=A1??1AQ5DZZD5Q@ #!>7.'.'>7&7>76٣٣J J ٣٣DJ K @;?O!>7.'%!!.'>32+"&=#"&46;5462!5%!2#!"&=46$$$$6II66II````@$@$$$@I6@6II66I``` @@@ @&,59EQ>7%!2.'4637#27674&#'3"'&'&63#!2#!"&467!2#!"&46@lRRl`mm] "_A:s^ !`@:m@@RllR@mm r! @: @r! @: @3<FP!5.'#"&/&>;5463!232+32#!"&463!>7326?6&+5#"3Ot! 2 - YY . 2 !tO`lRRlB .YY. fM%#``#&Mf @RllR   @@ #(4!>7.'.'>7#63277!#67!2&"&6mmmmH #@%)'u')%6::mmmmC=  ``{@@ ").3?!>7.'.'>733#535#5#63277!#67!2&"&6mmmm@@@@ #@%)'u')%6::mmmmC@@@`  ``{@ !>7.'.'>7&76٣٣;@8z(@٣٣DnNFXn@@`%3>75#"&46;5#"&46;5#"&46;5.'!32+32+32+32#!"&46;5#.'>7!$``````$$``````$@`6II66II6$ `` $$ `` $@I66II6@6IA '77&76  ' 76'& 7&'.6&'6&'.&Ãf]w2wppwwpq#+>@N_LI ^IG#)" (<=MCfppw2wppw8N@>+#- IL)#GI^M=<(!@#Y%7>7%6.&76$762///.?'&>7'&>7'&462 Eu?r_E@s_E DtH8V0h^V2f  - # .-- $ --- # - $ - # .-- $ ---   GvDE_r??F^q>rGuD 0]e4V^2H  - # --- $ --. # - $ - # --- $ --.  @ %+17>EKQW.'>7'>7.'67&%'6777'&'7'6767&%&'7%6&''6&'7٣٢(!/m"2!* ## .m,' !"', !"2!)y)!2.. ##J ! 'Y ! ,@;٣٣p.#9':7*8%1?? 8  ? \7*8%/0%8*?2? 88 ? A&.;G%>7..'>&67&''67.'76&'%>. '&76  3;8;X?-K20\-0UHf8]uU?)[&W;~8;@DC##Bu]8Mf0;%6/76&/&"7.?'.>?>2/+rr,'!& c "(" c &!'Ɣx%%8 %ݜ''  ''% i@'7%!.'>7!>7!>7.'%!!.'>I6@6II6$$$$$$$@6II6@6II@6II66I@$@$$$@$$$@I6@6II66I .=3+"&51#4623213"&=#"&467#.46;5462@@@ @@&>76&'5.'&6%312#1"54`nc}}cn!ߘ  F;yyyy;F= @ @ $1>K!>7.'.'>72"&=462"&=46%46;2+"&%46;2+"&٣٣n@٣٣D[@!%!2#!"&5462"&5!"&463!2@@`@@ -<E!>7.'.'>7>7"&5.'"&.>?>>.٣٣mmz!@D$ 3$=#   ٣٣DmmfC?9G-  @ $%1!>7.'.'>72"&5463!21#!"514٣٣  ٣٣D @ (!>7.'.'>762"/&462٣٣+    ٣٣DR   @ #!2#!"&46>7.'.'>7`@٣٣`٣٣D@ #/!2#!"&46462"&>7.'.'>7`@ ٣٣@٣٣D@ #/49>C!>7.'.'>7'>7.'.'>77&'6'7/7٣٣RllRRllRmmm----٣٣DlRRllRRlBmmmm----@'-#5>!.'!>3!21#!"5143"&$$mm @ $6$@$@@$A@mm@ $$@-3??!&'732#!#"&46;>75>2.3"&%".762@.`7`r$6$2W#.6X$6$    @@@@6/%S-@u$$ 1%.<$:Q$$@    @@ E>7.'.'>5.'54623>7546232+"&4636II66II6RllRRll2z_@_z@I66II66IAlRRllRRl@z  __  z@`@$GUa.5>75.'>=7"'7;>7546232+"&46;5"&'.=462".762-lRRl@I66IO?5@3Ze.e.7@@_z@@.TS%&    0.@#RllR,@l6II6.I $8 9@y4X4e."_  z@@C)c6  +K    (.676.'?(,   1+O7  ()56B"3!2654&#%!!.'>"&463!21#!"5143!21#!"514@)66)@)66I$$6$$[   @6))66))6$6$$6$  !)!>7%!!.'>"&'326?$$$I66I$#KTKU282$$@$6II6$?"" +,8?!>7.'!&'>7!3!21#!"51453!21#!"514r$$$#I6@6II6 @ @ E[$$$v }6II6`6I  '09%!>7.'!7&'>7!"&4623"&462!"&462$$$#I6@6II6,,j,$$$v }6II6`6I-,,,,,, $0<H?3>7.'&?.5>7"'".4>323".4>32!".4>32R`٣$#\:(,mbj(- *ːː4f-5y@0=  ,  ,  , %!>7.'!7&'>7!$$$#I6@6II6$$$v }6II6`6I $%12>?3>7.'&?.5>7"'3!21#!"51473!21#!"514R`٣$#\:(,mb @  (- *ːː4f-5y@00  $?3>7.'&?.5>7&'RfѬ$!Z8(*x\(, (ȔǕ8h,5|B.  (45AJVWc!>7.'%!!.'>>4&".'>773!21#!"514>4&".'>7%3!21#!"514$$@$$@6II66II$$6$$6II66II  $$6$$6II66IIJ  $$$@$@I66II6@6I$6$$6$AI66II66I `$6$$6$AI66II66I  (4!>7.'%!!.'>2>4.#.'>7Jllllll11.>>.MggMMggllllIO3:3>..>JgMMggMMg (4!>7.'%!!.'>2>4.#.'>7Jllllll22.>>.MggMMggllllIO3:3>..>JgMMggMMg!C#!>754&'5!.'5>753>75.'!.'5>7!6II6@6I"9FlRRllR@6II66I":ElR@RllR@I66II6#:F`@RllRRl@I66II6#:Fb>RllRRl#''7>'&'7>'&6?6?'.[8 .2;[-ZOEA KZOEA KZ.[8 .2;[----[;2. 8[.ZK AEOZK AEOZ-[;2. 8[<--@(1:CLU^gpy!>7.'%!!.'>72#54632#546!2#546"&=33"&=3!"&=346;#"&546;#"&46;#"&%+5325+532+532@$$$$6II66II@@@@@@$$$$@I66II66I@@@@@@C>'.3!4&/.=.4>2!"&/.>76$= %$!=E=! )1$5 ,e)$ $ A"> 1!$T#<$$<# > B+$+-%  @@ $%1>7.'.'>7'312#1"543!21#!"514mmmm @ mmmmC=   %&26%>7.'.'>7;21+"514;12#1"=4'__`_xwxj(%(/`__`9wxwx(%(@#(:?Q#53+"&=335'53#5##546;2!5%!2#!"/&4?6!5!7!"3!2?64/&@@@@@@]GG#R cc G#Q dd  `PP@ p  p P@ p  p @ &3LX%'"&'3267>54&'.#">2%7.46767>54&'.#"26.'>7["PVP"[4EG~`,/0+[.4EG~3["PXO!>,/0+[F #!@"+L#!?H?c[[[,/0X4EG~3[!OZO!,/0+[.4EG~3["PXO! ?$+L#!?$+L@'3!!>73!.'>7>7.'.'>7$$$@I66II66II66II6RllRRll@$$$6II66II66II66IAlRRllRRl/ %/!2!.'&63!>77'!!7!>?LdBBdLV摑N C,^,C =?KK? J~ '#BO@@c*22*c$07;DM7#"&5463!232+".7#".7>2367!!3'#7'#>4&">4&"!@ 6\#GRG##GRG#>J>-M 6B"--D--"--D--` *I--I**I--Ij""'h`A ``-D--D--D--D-  $0<M]a%>7.'.'>7'3!21#!"514>7.'.'>7"&46;2&'"&46;2&/'6II66II6RllRRllR @ 6II66II6RllRRll `Z @%9*@*@I66II66IAlRRllRRl I66II66IAlRRllRRl  h 0 0`[".!'&"7#!"&547%62>4&".'>7@,z  %X,$$6$$6II66IIBB2 q e$6$$6$AI66II66I`[ &27!'&"!5#!"&547%62>4&".'>7@,@  %X,$$6$$6II66II> q e$6$$6$AI66II66I@)2#5!!3!"&5463!2!%!2#!"&546.462@@@@n$$6$$`@ @@$6$$6$ /;G>7&'7.'467>7&'7.'46.'>7'>7.'ŗ"쯯#ŗ"쯯#}쯯쯗ŗ;;"@^^@";>#c{{c#>;"@^^@";>#c{{c#>{cc{{cc{>^@@^^@@^!%IU^!#532#!"&'&'.=!!#!"&'&'.546767>3!2.'>7'>4&"  R @@ R   DZZDDZZD)66R66@   @    _ZDDZZDDZ>6R66R6#GKOS4&'&'.#!"3!26767>5#!"&'&'.546767>3!2!!!!!!   8 @ **** **8**  <    x**  **x** *&@@@@@#/!'%!2#!"&54?6!!%3'#'3+"&5=l  22@(@ T @88@` @&/;DP!!5!!)!!!!#!"&53!21#!"514!>4&".'>77>4&".'>7 `  `@@ @ `$$6$$6II66II$$6$$6II66II@@@` $6$$6$AI66II66I?$6$$6$AI66II66I@%!%!2#!"&5465.'#5>7`@I66I@lRRl@@@6II6RllR@(/3+5!#"&=#!%>732#!"&546;!.'!! lRRl@I66I@``@@RllR6II @@)-.462.462"&46;2!2#!"&'!!(,(\ "_` @ {R (((( @  f$-!2#!!2#!#"&46!.462.462`7p ````(,(@ @@@ ((((@)-06.462.462"&46;2!2#!"&'!!%'762!(,(\ "_` @ {Ro\\+<8 (((( @  f@nn@#!5%!2#!"&=463#3#'3#3#`@@@@@@@@@@@@@@@ "&*.#3#"&=463!35732#!735''3#'3#3#8@PxHh..@@@@@@@@@xH.."7!62#!"&54`  ` @ % {@  !-1!3!21#!"514 !%!2#!"&7>312#1"=4#3#@ @ c`cM qPqr @@ @@   @$-159!%!2#!"&546!!3#!5.'7!5>'3#3#3#@r@I66IRlln@@@`@6II6lRRl` ``` @#'+/?!%!2#!"&546!!!!!!%3#3#!!3'!2#!"&546`@n@@@@@@@@@@@@@ "+!!467#!>73>7.'.462SRl-__mA]]AA]$$6$$lR Dthzzm}aa}}6R66R6@$%12>##!%!2#!"&546;21+"514;21+"514;21+"514`@``@. @@ @$%12>?K!%!2#!"&5463#;21+"514;21+"514;21+"514;21+"514`@@@ @@@ @!%!2#!"&5467!!7!!@N@`@@@@@(-87!!7!2#!>!5%!!.'>75%!/&'$@`@ I&P$0??``@#ll#`$`:6I!(`@$?00?aMM@ VV +!!7!!3!53!#!5#!!#!"&5476 @`\R  @@@Xg  4!%!2#!"&5463121#1"514'>67/& @@@@2O}  2O| @@@@@@' e (d @ $8>7.'.'>3121#1"514'7>6?/&٣٣@@@@.D  *A  ٣٣D@@@@ .b0b@ +/?!5.'!3!!3>7#!!.'>7!5%!!.'5>$$$@@@$6II66II$$$$@$$$$@I6@6II66IA@@@$@$$@$@ #'7!5.'!!>7!!.'>7!5%!!.'5>$$$$@6II66II$$$$@$$$$@I6@6II66IA@@@$@$$@$ 7!%!2#!"&54653!33#3#3##!#5#535#535#5 @@@@@@`@@@`@@@"3462#!"&5463!2#!!76. &?6762@@`5D $  iLME # qOi L@@762%!2/&"&'46B@#  #E@  !.;H%#'##7#"&5#"&463!2+#!!2"&=4672"&=4672"&=46oJooJo@@   @@@@@f >73'.'>!.'56! ՙ@)_bC!3# rr+||+t@@!65555&#77#&Y@@ 3#3#53!5377''7@@@@Z----Y-=---@`@@@@-----=---@ !-3#!.'!7!!5>>7.'.'>7@@$$?6II6RllRRllRmmm@$$eI6@@6IlRRllRRlBmmmm@@#GHTh";26767>54&'&'.#'32+"&'&'.546767>312#1"=47"&=4&+"&46;22  2222  22>@/ /@>>@/ /@h @``)6 2222  2222 @ /@>>@/ /@>>@/ `@6)!0%#"&5#"&463!2++#'##!!%"&4?76'g@@oJooJH  }m %    ^#b .;!3!53>74767!733##!"&=#.'3!&767#7!$$=n% FI66I}}  `'$$G9QOFF@`@@6II6ED.)980@'3?5.'62.'>7.'54>2."267%2675."٣D<"I66II66I"7!..'@$6$@I66I:А$$6IIv4!*6B&'&6767&>>'.7>'>&'&>.kJ==c189p!["o981c=>Z >;;k#4  4#k;;> Z>V)  8V*4.BJ.5*KA%!7'#!"&5463!2%3#@``@Ȱ@0(@@+4!>7.'%!!.'>!2#!"&46.462$$$$6II66II$$6$$$$$$@I66II66I$6$$6$+5#.'#3#>75#5!.'!>@lRRl@٣I66I@RllR@@@٣6II/%32#!"&46;5!.'>7!!>7.' @6II66II6$$$$I66II66I@$$$$D*%"/$'&76$>7.'!2#!"&46}  }wrw|D{WƖ}  }m{D|wrwƖƖ|D:%"/$'&76$>7.'546232+"&=#"&463}  }wrw|D{WƖv```}  }m{D|wrwƖƖ|````D%"/$'&76$>7.'}  }wrw|D{WƖƑ}  }m{D|wrwƖƖ@!-9!!'!#37>3!232#!"&546>7.'.'>7 . 1 .DZZDDZZD___@@]]ZDDZZDDZB____@!-!!!5!#!"&5#"&5463!2#32+"&46@ @ @@@  7!2#!"&46#' @@-==.@B>-=- 7!2#!"&46%7 73@.-@@-=-E,62"'&472764'&"7.67Z<;88OOKK.h88<;=%%(f' $ &-23$ 88<;KKOO.i;<88=(f'&& $ &- $41@+/CGKO%#"&'&'.546767>;5!32+!!5!34.#!"!5!3#73#   EE   @@ v @@@@@ \     @E  @@@@"!!!'!#!"&546533##5#5@ @N@@@@@@@"!!!'!#!"&546!!3#!!@ @@@@@@@@'!!!!#!"&5467'7&`@L.-@@@@--@&*.!%!2#!"&546%+53!#5463!2!!!!@n`@@@@@@@@@@@@`@@@"'!!!!#!"&546'77''&`@C[.Z[-ZZ-[Z.@@@@Z.[[.Z[-ZZ-@'!!!!#!"&546!!&`@@@@@@@@!%!2#!"&546!!3#!!`@@@@@@@!!'%!!2#!"&5467'7f --@ --#!!'%!!2#!"&546'77''f [.ZZ.[[.ZZ.@@Z.[[.ZZ.[[.!!'%!!2#!"&546!!f @@`@#!!'%!!2#!"&546533##5#5f @@@`@@ $!!5!'#7>3!"&5463!!232n`|2: N9 `p@@ `@ !!'%!!2#!"&546f @U 7'77' 1!5!!f9h1Gpp@.^pbpgN@@@%1'&46276/"&47>7.'.'>7[  ZZ# [[ #ZZ  ٣٣Z  [[ #ZZ# [[  ٣٣D@7CO[gs!#"&=!"&=#!!546232#!"&546;546232+"&4632+"&46732+"&4632+"&46732+"&4632+"&46 @@@@@@@@@@@@   @   `@@ !@@ @@@  >.7%.>%&>&[X!"S`7JO3&JM.&ZY5M^#i(.W],L2i"%.'>%.'>0??00??0??00??0??00???00??00??00??00??00??00??>/.76&/&l   A ! l! A  #/<E7'#!"&5463!2!5>7.72>5."4>2.7264&"ZDDZZDDZ>-2.6R6"7&>23#I66IF:p $ r:@6II6@!v  u!  !! @ &2!>7.'#'.#!"2>4.#.'>7$$$$t. .551AA1mmm$$$$]]M7<7A11Ammmm@ .'>'&"276.c    +@c   + @ &.'>'&"2?>/764&"h  hh  hh* hh  @{h  hh  hh *hh  ` &>7>7.'>4&".'>7p;KTŗTK;p$$6$$WttWWtt VAUZ[UAV$6%%6$sWWttWWs)3"&5463!2#%'&"!&"2>5."`@E    -2.6R6@E " %,,)66@ '.'>#";26=3264&+54&"  @k  @ 4.'>264&"46''&76&'7>>""3""%5 X#S5 W#2D@44 =  (9, =  '8@ .'>3!264&#!""t@E @ !.'>"2676&>4&""",@&&,,@ *.'>>4&"3>76&'&>,B` A??t AAI' 6@E,, !RAAl/:)"7.'!"&=>7!#____`ZDDZ@___A`DZZD`  #!!3#!5!53!5!3###53#5@@@@@@3!>735.>25!p6II63&'bb'&I66I&tyHHyt6@@ !3!3!3 @@ !!!!!!@I"53!54&'.7>76>75C=#ODhO~EgXu@@@ P2A&%B?ch$fqey@~ !>7.'>7uuvXXvvXXvo*؍*XvvXXvv@)3#'''7&'#5367'767.'>>mm>77VV77>mm>77VV7slRRllRRl@UU@_`__`_@UU@_`__`RllRRll`  3!3!'5!@x.=-? @.=-`` 3!!#.4673!0??0  d?00? ((!.462.462.46237!000`000000w@!!#3 ``` 3!7''."26$00((Gf*f*u(  !!35#35#%#>7#.'@@@@@@@lRRl@I66I @RllR6II#.'55>7!3.'>7 U=ӝ=U U=ӝ=U =U ݝ U==U ݝ U="%3!53!7"&'"&'"&'"&'47!@@6R66R66R66R6=@ )66))66))66))66) @%"&'5#.'!%!`6R6`6II6)66)I66I 73!#3#@```` %!5>7.'5!35!!5#356II6@@6II6@@@I66II66I` 7''773!3!%5!----- @ ----( @@`` !!!@% @@BM@@a/o/%>2!!"&'!5>23#"&'!5>2!!"&'#5 1>1 E 1>1  1>1 1>1 ; 1>1 ; 1>1 ##@##@ ##@##@ ##@##@ !!!!!!@ࠀ %533!5'!@@@@@@`  3!3!!5!!5!5!@`@@` @@@`` 5!3!5!!!5!@@@@ *.'>>7.'?'7.54>٣s  @٣٣F2 L @ $%1.'>>7.'312#1"54;12#1"54٣# @٣٣   @!55>732#!"&7>;!5.'#!#"&=!"&5@lRRl 99 I66I@f33f`VrrV @ ;NN;V```%53'3#5.'>7>7' fw\XX\wf f^ WjjW ^f@'&>54&"@ # )  : $  265264'.     )'4AN[2#!"&5463%!3!2>54."2654&!"2654&26=4&"26=4&-"##"Z,"",Z,"",    "##"=",,"",,"  -   - <        }-=6&/&6?>'&'.76$'&6&/&67,&[ EK^-<@a*  [T? $.T>* 7 0Aa]-<  T>&#1GA#0=5463!2!2#!"&463!35#"&5!#%2654&"32654&"`@```@`@@@<L!!.'>767>/.&'&6767%6'5'&$?>/.0??0`0??t7IPw  %U85'RB= 4 PU>( @?0`0??00?Oxs7J  4'RU:)1 % r7(> +#* 1< +C n *       V &] Created by iconfont elementRegularelementelementVersion 1.0elementGenerated by svg2ttf from Fontello project.http://fontello.com Created by iconfont elementRegularelementelementVersion 1.0elementGenerated by svg2ttf from Fontello project.http://fontello.com       !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~     ice-cream-roundice-cream-squarelollipop potato-stripsmilk-tea ice-drinkice-teacoffeeorangepearapplecherry watermelongrape refrigeratorgoblet-square-full goblet-square goblet-fullgoblet cold-drink coffee-cup water-cup hot-water ice-creamdessertsugar tablewareburger knife-fork fork-spoonchickenfooddish-1dish refresh-left refresh-rightwarning-outlinesetting phone-outline more-outlinefinishedviewloadingrefreshranksort mobile-phoneservicesellsold-outdeleteminuspluscheckclose d-arrow-right d-arrow-left arrow-left arrow-down arrow-rightarrow-upkeyuserunlocklocktop top-righttop-leftrightbackbottom bottom-right bottom-left moon-nightmooncloudy-and-sunny partly-cloudycloudysunnysunset sunrise-1sunrise heavy-rain lightning light-rain wind-powerwatchwatch-1timer alarm-clock map-locationdelete-location add-locationlocation-informationlocation-outlineplacediscover first-aid-kittrophy-1trophymedalmedal-1 stopwatchmicbaseballsoccerfootball basketballstar-off copy-document full-screen switch-buttonaimcropodometertime circle-checkremove-outlinecircle-plus-outlinebangzhubellclose-notification microphoneturn-off-microphonepositionpostcardmessagechat-line-squarechat-dot-squarechat-dot-round chat-squarechat-line-round chat-roundset-upturn-offopen connectionlinkcputhumbfemalemaleguidehelpnewsshiptruckbicycle price-tagdiscountwalletcoinmoney bank-cardboxpresentshopping-bag-2shopping-bag-1shopping-cart-2shopping-cart-1shopping-cart-fullsmoking no-smokinghouse table-lampschooloffice-building toilet-paper notebook-2 notebook-1files collection receivingpicture-outlinepicture-outline-round suitcase-1suitcasefilm edit-outlinecollection-tag data-analysis pie-chart data-boardreading magic-stick coordinatemouse data-linebrushheadsetumbrellascissors video-cameramobileattractmonitorzoom-outzoom-insearchcamera takeaway-boxupload2download paperclipprinter document-adddocumentdocument-checked document-copydocument-deletedocument-removeticketsfolder-checked folder-delete folder-remove folder-add folder-openedfolderedit circle-closedate caret-top caret-bottom caret-right caret-leftsharemorephonevideo-camera-solidstar-onmenu message-solidd-caret camera-solidsuccesserrorlocationpicture circle-plusinforemovewarningquestion user-solids-grids-checks-datas-fold s-opportunitys-customs-toolss-claim s-finance s-comments-flag s-marketings-goodss-helps-shops-open s-managements-ticket s-releases-home s-promotion s-operations-unfold s-platforms-order s-cooperation video-play video-pausegoodsupload sort-downsort-upc-scale-to-originaleleme delete-solidplatform-elemePK!%e(n(nJpublic/fonts/vendor/element-ui/packages/theme-chalk/src/element-icons.woffnu[wOFFn( ڔGSUB3BOS/2<DV=IcmapT*8 ҩglyfY+Bheadbp/6"hheab$hmtxbddlocab44}`maxpe  1namee,JaÌpostfx sxc`d``bca`tq a``a cNfz"P ʱi f#Oxc`da`tB3f0b```b`ef \S-x~C sCP$W Nxu]R`ˠ vw3(%H#vw9& &֋u]wP%zޢG}x-xEzy5?ĤKcyV>;f쑽O.%V>g@ 1;Ŋ!;e왽o.>/}NlBOgGaV~5]WN^cm}'uG}61MhJ3ӂb Zӆ=kk+zlFlYw6e39؂lVl6lvlN.K7{{^A!aQ1KC_xNDq's rsgrgsrsrs rsWrWs rs7r7s rswrwsry@1!#>>3> n/oNXOg~W~w`URSjڥN[:ƥIiZEiYZ5JҦ-S/5kT?oSLO1ЪAV%E *Ab $Eb$ObU#M,1ʪWM11DcM61M;1M@L21ٔ SBSMYAL3tS~3LIB4e 1˔.lSsLC5e1ϔB|S LD,4eȔVbSnKL F0/)LL|lJgSN̔'09d'Ҕė'2>oL]@|kj;S?KMMA,3u=L=B,75 -O!V LKд ȍLشMLldӊ 75 r3Ӳ 6imL´@-BniZ%V}BnmZ*6BnkZ/vCnoZ4mChZ9NClZ>. D0!iL mJ䮦DfO%EaT䞦uEeYަEc^侦FgceF`h䁦FdmGbr䡦UGfwᦥGa|䑦GeځѦEHcچ䱦H1Ei9Ǚ6$yiM'v%yiaL[<ɴ:ɓM<ŴDSM<ʹNM;<ôX3Mە<˴bɳM{<ǴlsM<ϴvM M[ȴɋMĴKM̴M;´+MۚʴɫM{ƴkMδMM[ɴɛMŴ[MʹM;ô;M۟twe@kLyn 0]䃦[|tU ӥA>j9L!0]$dmB>iRȧL 9tM7 9t͐Mw 9tOnr!r"Gn"r:"G$rb"kաo VΟhIVƪ*'[:Z:[:gZ:Rul+UϱRu\+UϳRu|+J TJKax `[Օ0}Wk-[bIv+eIvω:!C$@Bh%Jô`H˰B,[(˴R:Pv:_i;tX$'}ng zDB/ lo2u7`4I&zfOh{r]H?'4X^utu퇚;ח|tc̞ l>h5ۏ[Y,19HY}}[?/i>ټQ , 35AIVa;5 ,( uBd3D,5\^Zsh"H5Hr A|Plv;"D ٕY"g ɶǂnrd۳q|_q|ͭ.&.4 R mv`2$5P1$?@jm"4=AnUηg,ʹFۼC -6P趏"d p^V貑qKq'll6p'? #JF|ɰ{<1'Z8;i@CCM3|{ft?ٶgc_nu:ەq-z Ą0Sea{^4@$D &M<\aơYlAl HɬnF6W4Ҷ ]6FW3^/zp䓿s LD! Ce3B"tY) >{u;dX]'X}ơ>"f P'_:_:oL`.(,-MfUMD<*N.랐>ҥ5,@Х~]^[,fMZ #X(oito9Ioއ`շRO^͟%j&N եuiI 9af\a x>@4^90j9~服ߋw \ d. _**Nݛۮcl]p^ao+-ͣyv}{o\~ l[-_߬qhdAh4̧y2a·R ;(H(nJ̥ 49(\)DL"F$pInvGw8CI]ɡo3cG6cM%f́>gh4mQclv}yv.Gl40W!E䋑5V?t#mg.G*s.͸uΣ#@Wsnsr&EHH'6.3N>iYaq,(! e"QD F2j b>_"L̠?Jlm2 Ww7ZH?־:ɴI&xz'j$ 츆}]xG;[8;$O:5 Q5hj kLksn5 j!Wh2}-޲DJV0NK&#}P1ָ|$1(QAǩq~'ɲ u~B!?~Wպc BTu/=ݻ ,:Eidvco0J߹ݷ9ݫ‰s64\g} Ťt}zGKnuevYRuӇ6Q.Ahj'pաb4D*_.QȬs2еEh4Z@:YTF)aVWػq.|KX'(]TzׄdꮕDnx0 \+C {K!>aNdstT$A[!6 J%+AAKiTJL>)zd)C4Ey&!W:@rba ΉL<Y )BA,8@5Dh1rQ_1H mcy_6gF#f`/4ލ ^zBNfLAnq@J9Nd#@@|4hcE(2ܐs;ogO|6{yh!$V& IC4 :/,G Eqºur#z"5GIȸoYGZLo:Pm6Ӿnj+t`q5%Jv8h}B r}i]<2CC ;@ f0%x#2e@@,8`JFMݳ˖,_>*}4k ;V[,ŧd~k,}UQ p]Z~:B-Mwaݖ-u?Fr~}n\R&qc z~p[)iFckpH sY}lej$=C Ab&X1K$?xR)ޣ Dclfkн[zY~MFwil7Wt:!os!/z걃 ghL&vfmX4ݐ8'V6{4ߥݍcF!<- \':.. ԃIqE=BGETL≡$8/ߕJsLK%m"n!}i|}KQQW/ _892s]×kf{-ݿ Vr??Z`d3U(ϵU-iGχ;(i_"߶||Esݴ([nrɟgV]@Y'$a`Eir%qAt O9hD"4l0(  0p{Ζ]Gbʇ?e[>\>pȏ7l2E}iי4Z1< {ˎ/Xf+EΊ=k-ouq/-F4";lnidJ3v7-OLByY?!jf}#F|p Q R榨n=xt.AQKeryF[k&-zE.$ɞ%yoHd25+N3K0󈡱C)dFSEooI˙?|U6GQ'uNH-j(0#0]Hxw&WuGJt?>vY7;\O?L\±t?&`kk0>$߁r*/$PpH<ʰmnC_eV 0`ظ掯m; 0{ =$0dVZ1ڪs*\ RǐFp`&k޻ +]'!|JGl]2_s,wv={)+Gݗ\gE;@\CӪF..m}k KrGa26^;g \T\(vQwj3\E]9dP |Y*hEtYYv>(  yt(v#{:}7{MGmx~+Ϣ^ؘ8H&`za []o6^ohMLy!Bx mSܛ5Ž򍮡!e,2F x6.@v ^Q \XuN=ָ"45ZӢk;ʊ>\-h6}:H]韬zӗM~tbա[: A0&dVTE#Q*L)񑟷֘t/g?ҋi7Lam_`d']%a0&@=Fh/F^{!f{@`*텇?p_h~ o(IP9?`i43Cfa̜y4u.fL5yRS)(^':1ȕir(p.2Zچ -n{ѓMQKa亪˵@R^57 @_ |;kI(:G` {炅AI5׍zztA=FGf3xA< xIfO(oeihĸn=:(D`{&9$U>`BѠRJ(JpV4?`BKy TЋk%<ᘗ^_} gyT1}pMgdK:HX]=Rq^1ߓ/>s/1o߾:|b̔Y+0U$UKֺvS丗=B鑽cˢ}U_}BTe易;@_Zcɘcro΃tk7fx=}$oGD!s{opxh?uoಥA"Y/,¡\ZLuyT$J:}[,#dـ_nZ+|Wq`,LU{*vx7EC73j'_+Ni^vni0hE"ƔM,@KqE<|1^p"Y#&H\ANEZBD PfA9j]dhDVhie08ȐC hi2! ph(6So G d$3A-}Tq0rsKD!Gh!4_Y'N q$\@AsnGG蟙^@GGD̀!dlf'f[7&,?jrSHz40ߎ0@yfƕ0p RHr2t;\47LdLVr- oBeE9(݂Ym7Pr]J{Y>sʱlDZB ڡdhbE4}MC@p&T= uWڛƢJSh.r2#X%3 " p MM'K@Q+' ŋ̌]1\gjUFߢJX~;u:R4i*;vZ/پAy *ޝ`Jb)-Gz2 IWB4eZD~_5#!Eq4PQ_T~.i:PwsEPLc3]a7> @_s@_$d:$U% @qtY 7o !y@|!nnrAhUol DcaM޺5k+tۛ׃K&9y2gR7xAU#g\qkBau>,#0b:QL:wSLFq] fdm.0L 9/G**"]y|.yV73fPb0Vge&0UTW)6<4bwf(d `;Z?I'HA9s"^30Oh,Ab 3N @:KQ!qNV]# OxG_U~b!=FE(1y!ꡪ'yC+H9B/E:q˪ڵͳ|ҹfccƄ c˶C|^(=`rx"GYR o?ymI{d{X,'8cqnApw +>ơ7ۂK|uR9 s'/O TcHќ :ܿ_W\Ӈ_Kw'zugm3#K_ޭ3MR|xy۱gu?!\~W|᳈#; 2Pnxߵ-X7v4v9oi|S7?Lnص--:%Wl#wݱ^,9{/jW[ 4di Q-:K`;Ԣ$3Hs Y2 Ev^iN.:``6:&k6^LţG0;fM=b:k(iv_:x N[#K[ӰB~i~|M ۄk{*@#SSa gMT]pL׹T]d&vW-hfXV)siG ]*N)s#}N&zA2(S@:7Fă$1QE8m+H7m_cXY!LLƳ[yͪUkoeK,*40>G ,VFtH\zͺ.f<\L;yÔ tsvD #Y¦*\bTo#0)b3w6YڇWuYrYw{׎=֬)|%hNu сCmF9[)/Yrɗa޵~rMDs16`BǑZe3 rJ#;IEl_Gɚ& cݦc>3xfl7d-Jܶ%1l߱`N ,$-uu'h3lOM 3qy}eK~j :L0ƥ lEQ+IwwFrJbgw}sI lJ*"+Q["ŭ:VQ  俐:wcOMIdu}$n#v71U*ӹ8P~Ի3 '#>3it[YnDx䦓BQ m )yx&˃Ū/ ŢRlGmZuXzQ.\1k޽Q=Ir(k8\3< oҏkG{!Sv2HzjֽR*jxXqV!?m@c3ځB~wZή4)K dUK,Q Y E *8)uڣgĆJQYIi!άVIYpYҸh9W@r&'eח ϋX=BP0WX^{d(FĒD]^,xb(#jVK6_q }3b={O=%m[R l;֣=g[[f-fh+0@xٚ"(ojF zO&JU soM9"rKIvx(Ol~H&8_7KH[(*=~ '\$YTߢz̖r^SWTRU9  Ԃ {s-\gT,6z6N dl(\y>yjvt&O9@N 8_ծqSX 2jEϹE3?85vO+kkZ/*Yvh@N'[Otӓ"ٹv-zKMlu ;-Cî22T[*jc|[k#&GM6 Ѹ£.mGm;^Tt{9VRz>YqJpE+/@ TY{RGS'ZHV E e^֗N}A0%PU3k&ho\gzo"rpř84.\=l7@2&Qi U)"QFst[g=K6Y"K3CvKsqȘ֬@%^|Z"_{%\(5sLtFj}b-Jn(t#5ai)YbDa.B$M&_ꋄ{,?^uaѐ2#K4ݼ'ҜKLQa,7hJtY^n_o9ꎅxօb^NJf=jQ{U53M*3!C^/[\ vsL'/Kf:GI=5Gqk&knɲNN<,+` ӆԆ: K,2Ub=d׬$zPDqٚ-4 ]&logu{T3# y>ӚȨUkbzbm!DNC&)#Z BFy'Ų9Q+LG\ևS&ߒԹ A"EA8czD ?%a,@^pE"M/pMdMl\w%BAeFW, m*.Zkf>0M7<_>qCҠ# /Z؂EMcg5E42^p1O !s!(nѡ2hg>0Yyʇ^> wّ}K@F.](>sӚ!DX]l:;Ug]1&?AnjbYۼo oxp߂F|RFr}w$s]=tt ;;SʏN~(rye~j\8d󳄵@os `I]i x!"a/h*|f&B".!bx/U&:Dkzwp`59uοuv4,|coeoW}h֍o4F_K!]elIQco.:4Kj]8]Ӈo#wu,N 7jNt.IFbbio5Gۢ{[lfxBtFoyD#Nqbu:g>H&w<^;a!t|=o^4# 6WXҜOó悁a5\\0v EnH~OǜCs,Mx9sq?AL. (j8UN(T(ˏ0j{8%(r Q:Y'k'tIDp63ƫ4=[-s+ʡtb;W^yw\y;g뮯/elңp Z>FVgٯ&|lOjkp!|QRŸY~*DxJPĝTqܹe+--;Y엚-IKW}8%<,胃ԖDeʙD|\>&gDi[gc4~5<ùLMY;_Iun]ˢ10\Բf@Ԫbj}Ujh}:5@ 2XѸZTp񃛦9T5.wk:LZh-eoh"p&(i*j>ZNW3vo%kb8%ɬ$6`oj(xjz(rOLkE= {egk&AɖM`3”>UNAH/$/khC )P,"B-P.H  Z;r%_\f8q)v?0A ySz1O|c"e[۳6~u`3-$IΈݩwt٣\lvSZgΒ#pCBUء}1F—(l”p*3|_,Ā V3vz:h,m>N8sRH]Er׉ajCRq,] zd\ʪluc 4<唕&vv;K#2!)=v^TNRj 5ޯPҕ J1|7I!fl KWm8/ Y~c4G=N$l AIPVhwutvߥ_g NpO|dN+)>2bN0]m[[朁ϮwǧwDdJ1ۛ erk)dBe}GWYY+xʬ)p,bQXP%hadU rithӇq˂qG5$%m!?~.|riOQ&*[=Umeru(nYcE+8\/(uZϑ#Gio=R_ | .2`L> *P洽M6Vx=e^eg֢A^A;:˃XEgt]ځL`?ɯ\Xŷ{m5ڦ߾o)[W6֦{λ^^o[3)AR.fQ [OoLej)ߨОP𓤎K\S>:Jlp/LpvD2}3̎B*`j+)mMNbBpŏdq|'?Cs0t;7.7C^ޜnS!05POss/@ ?m=P >i_?pO00 bIDy@pEC1Rj8TMW=9!EYh[t>?wP\st5EN~Ld1WO$ }T-:ǖ G+DZʓNٹaoCjl>ǿ ~?믱_ݎSp=nj/hJ*םщ)2BB$`sav*d! p)"\@{X8ˏwDT ާThj%_ntA'|oISfGl7ڻY -qT~^;F0~md5 Z#[URjm{s:oAۚS_V_j>ղ"W.jdg9sd67yP%GhUZ_ pd&&I|Pn3\q(w9K/hYA6oA/awh?9cv WF,vT/If>OrOo T(A6`xd"9e?he$тR(7.X@c7J&=l5ZhQ srL$\xHp`+VKOк\ok&ݨֿ_02gA)'u7IxA"5Lw/pP`5J?]fEtCy Oձ1Ůp<Md꫏Ehǒ&x͑ͳDq5$T]G\v.76w:4}f7:?2:DlF6x%iY.?&IzUoЮ"pwa GToa(cʑt6犸"d ؐ(z予CY%fq.`傘z~ v}hpv3u W6y韶s4^FCI) úyy7#D9 KT\rRa#j!'ԛTj%h& s#ZClkB0 @f+Rk(ǦiTc0(Dywn vf';QiL&#tpw͋j4QL)rl8|3A==Wڈ_7Ta)=O|Y 4M!h{p픋u"A!<-Er=@]yPϟ!2A#@`ްCƕ5ݏW%Q}P&j<1 CL%)55sd =U*6ʠxr ;WI2Ϗ%y Bt}+:|LyC +W@(*mt 4ƶ^M[cָ|Ճ#m*(CŅEG!;@"vVa{p 4(7a`oIu;FZ(mL: FRZ^K*r_ڨT.hG4~))pwUf&$-v?k0*,h^jYQZ"s&Ă`tZJ4F ͮir-MiצMsLfMXh::#P5B>|D9!LZ۱mb4"Y ]3OOq`FdiEf?' ɻN&>OMoX&\R(4((Sz#Y?0Jf tƐyM:)e*Ř(8z"^\ P hQ;2j /Ry\^R٪?]4Ū`Tl+ebϡ0j%~(x`34o0$154pBi9R;⎍$GQч \ (#(&1hE2q8_ EUXy!E 'Y2.IᶣVR p( [ʷ9}JX:EfGSM-+KV(=X%aKERP&t]V\O s^A{EcM9>NyV, X]Rb$ԋ&\Յ'kxҘCOxs<)Y;J{SVئ-kczi( p] knGBA$-g焀#L5$6ƔUڑ@:K`P<G OI կb'Ώ dGN xB~,7Ĩ&2?D#h_!BfmrXAFM*>za {*-+(%Ŕ$Qİ۷Vy)y/= .qꒄQ@7Cag} V,%r,TkVąq؎)LI66nT5az1%hPA-S` Q@ðcfI;҄bE|^L9nq,f* Aޅ)—(ld?P*bTZEsJEPq,RZvO`97!ĘLV@?[-P|VcDHr)"}t'_?'`HY-(=w3iQwd6@⊹bSQKWdB]"8PH) }gՐ8SuMgmdO w>Nz$I5(V/h`0Ih[F%hVeSn M{t?H8r墌htS*7_.qoD$+Ӣ-/]QzA70^fUU#:3=ER,(閿/]wI벭Ycsy uB+[ĈbhH$ÓDjEwOQ<.|T>,JwwDޞSfu tDK>j41d$;\rD魁P34ݽb҃;6-V1μq0 4{ީ_r`~睆-XLtb <JO&Ic%pIGS6h俊3lEd NfCC8Y5N}q$tpYنTŸO̩o4|qk¯™I%1XU1|ld[<0 Y-6yfnQ,Q"pk_4W/ ~]9Z90 PRXU6V1wJRׅ{1I:!bx4MB~H1bw?o>.8p"SETD)6$*7ю1!)‚ n=3">)yl*)r_S|d=75%KG&w@F2Tϒ77Iu[dISٟGbEfy0̴(rpN~s#@p _mbS9M \'AZ+sbɘ1U[`[a$0JE/~]c@ 6JsǫVh0z,MY cuBP^!J#0vHG$z!~\oGBO=kN6;_x75qp?~eĭ_ 텮ܛ+T#|Elc,d.,OH$Usdks0-j0O4}"I\zC2x@uްȽP`D|Ld_sik[HT"Yz0CitVh.]WnX==؜X_^?`NK~V*W- _k .(ӣ=" @]\,uBoCd6?%@4 /?/0"&P"w5AYeL=1%dk8C9^;Đ^ gwo̅*a'8Y ̢tj)*aU+5ZQ/L $YL&K]s;%;k/w"1Ci~O"^ZR?ΛxrʴElWSq8%  N<7(d)UiBXmq  9}ǦCN}ey 3L|#8Qe[70 Cق1&?~%H . %$E" .x.`ڕ|'I(A"3yllO/MbPnߡODvM[4Ff_ZQrwJxm{R~]u[ aFG|Y}}d6H# ~q[{DUl{}*7%B39D JW"F=` ̣¼5`7/e cWV#e ?9ʗŢE%w|8ys A䢡zB[w>0l2\!J pm|P t2 &BI҃2M帪=ƐB.hFa84(qlqLk%(UM$}Vz̉R^[%SBU ,}x/Ȉ~\N{+~P՘n UX$㔸p6sJfqO!/} 6n!Z-1wCjlCX熱Tx,A}>hY>rtr)[|*o'=(0NS&W7̎HDx2d̅<) #3 =O5=_]Vh3.6HjǍxG{jh6a]ktMY->W o!\9O ltj߫/NQ/($->" H{ɧҝ)i{KӣOv,ҡѠPv5nR3z7}j0 zl #j(3Z+4+BE] .6>eB_O_Ryj8< C_"&=ٕ^u`Z$o=fR-2F1S.ހAcJ3@Y5$*1c(J.RPX 66+ 7Ο)C?#\7 #sxKЇ5yúH|N/~)xiM4lc6j%=GYg͋YZ\uΐ5ε[SB .ԵROP<*3ݽLtM&zf[D%X޾fN?L7l'SG""M񡏕X^~  Qh/:`ju 񶱳'Հ򷢳TH$$LJUU@q'2\Fkb3cF1 x-P|nn?trENa{UKyI4WBUN۸IF99ZOTl&q>lk/ҵ, 5ë;8kWa%k7/ ] g_@bbfQ*?; Z+$wJ %B`c@'/{_n?e)h;δ#-H% WٝN]tBY>+ X=L3Ş1I DDI1|8S?N_]Gwfno/w{'9\.5I/O7ZZKir}C_V/•X(}P(h%(J4"iIňXmݻ!ݙٿ3}G|;s$f!15*K0~'ռAzs\g QZ"xvYwZ aQ&8MVc]^m'TV{/׷sh&B::r'%Ud 3iJ :;:?~7)G|v<-2/ ËIvs=67}c5_1=k~ؑ%_W{\_R%(_MyAjjiF rZiq7c9F#qF9},֋. :tZÚ)7 ̈gS#7pZvV:k֑ޖAwցR1/@Q{e[-پ98!8N+EF#؎c^o/>9w!UkEhͣKKkټ$t6o~?mB3<RHFi=g#>Ǐ+̮M{tϓ^ƕM~`k' &" /#[*Jl|fYH ^5+ ƻ1o"N%|q`G _j/HA }]>wZSC@*ogkߏ=LYpPʿ]/Ga= tukiZ-/в趠GK/~m qW{NIZ Y'Z N5>C--0{=_m&D􉋔^٠dB={?E70ʟd_WYJG3.y1d?-cXkcb7UT&5dtt+ىaE8 6,5 Yzܻkвw^0^SM¬ f0 }d=;8ML~Ϗ4!E!uTU^\#N1~0~͸Γ_mZ7sfA(GRi>S+ȼE% r,@\U>c29:l=փ ;xsS;53Zә黼XFDxR39_elߓFѱο<:Fl$.=g'>ĔBf<uƳ.HcxW8TF9e&̐ ( 0ZS(``DLxOqiJ: J.L3R(n H8*!vL!a7ksG ]caNJݧ+cOS"+F$uLr뒹;d=KhIYgv1\K#Q^(cDbcswD e~^䉋U6u&'0"߉xc`d``L6_Y@mL $ 6} Jxc`d``n@0JG!xca```ţxba;en.FnZh<,lh 4 B  v @  ZP dX V2Fd6ZB2bHxd^L\lP Z !!h!" "##r#$$$%&&&&'^''(d())\))*.**+V+,N,~,-*--.P../$/00t01$12L223d34H45556P6778,8z89699::z:;;,;x;<<<<=@=r=>>n>?6??@8@j@AA>A~ABBBCLCCD^DDE2EEF&F`FGG0GXGHHXHHIIZIIIJ:JlJJK K:KL:LHLVLdLrLLM"MMNNTNhNNO2OvOOPNPzPQQ6QvQQQRRBRRRSS0SZSSST Tx];N@)JHAreD)Spuz)%p :~;53;3 vb]f'n{/F#'a p>^=\UA~n߅[6n%ܡ-#=nF1nf9n[V5nv=;N3n`#L!qwPDGa``s'{>/x !x(x$G1x, x"')x*x&g9x.x!^%x)^x%^W5x-^ x#ބ7-x+ކx'ޅw=x/އ >#(>$>O3,> "/+*&o;.!~')~%~_7-~#?/+'?F 608H4ݠA `' SSӂ7kLʷxsaZ* YzP+ˬʌղ6i)Yf,q\BJj"Z0.ḐBEwάХ(TM4E_IޙQ!lޒs;qKw*ֈn{yƛTs{I.F0ݱI}5shEdb*=^\f= EJվЃfLLRl/n9+: ,%OG̈0sSV.m̄'ScΨW\ -oJQٞPj`ҹ>j(%&eT$Wu"Rs*A_T[Zdʡ垫uMpDU0cK;wm+gbvH'˙)ưSf3w'~!W+Zz=^ԟ{]{2*OWLU lMdM9Ǣd#42TuX T֑ %#N=hI#lȕ\^t(d9Rg$5aejLU];\IvDvof͎9wYOLf*ں1+XYdžO*gCUArM`#fّr/q@]hܧZr l_4Tr"CRZE.JvA,#`Hө+TrG CdiJ"sBIG1ӄP$H) KClsEQ%`q V3nJSqdq YQ1ͧq{oL9[d.MHQdN#*AVԇUf9^`:~Z:N\5[c$n.,ЊktYp"B5^)CHCovZOnKa(_4-#;<'Ŷ*$[yuOo&넲dY`,t/CF]n*cMXWAr5aLC]2PAh!i *]vMz&+F m9`EtSUGU+!BsWkU*Eϟ>t](uËZKv4Т$#jMkYgD⩦ޥ8)r2+y꣹;{iCPK!W&EmIpublic/fonts/vendor/element-ui/packages/theme-chalk/src/element-icons.ttfnu[ 0GSUB8BOS/2=I|Vcmap8 ҩ8*glyf+Bhead"6hhea$hmtxddloca}`d4maxp1 nameÌ$aposts͈ \i?-_< 罆罆  ,DFLTliga2PfEd@\,, "  +AEa"-DGc""*DR 24h0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ ` a b c defghijklmnopqrst u""v##w$$x%%y&&z''{((|))}**~++--..//00112233445566778899::;;<<==>>??@@AADDEEGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXXYYZZ[[\\]]^^__``aaccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~     n.FnZh<,lh 4 B  v @  ZP dX V2Fd6ZB2bHxd^L\lP Z !!h!" "##r#$$$%&&&&'^''(d())\))*.**+V+,N,~,-*--.P../$/00t01$12L223d34H45556P6778,8z89699::z:;;,;x;<<<<=@=r=>>n>?6??@8@j@AA>A~ABBBCLCCD^DDE2EEF&F`FGG0GXGHHXHHIIZIIIJ:JlJJK K:KL:LHLVLdLrLLM"MMNNTNhNNO2OvOOPNPzPQQ6QvQQQRRBRRRSS0SZSSST T7!+2656R6@)66)@)66)@@@)66)6))66)@)6H+>F&>>53./676&'&>#.'&.?&676'&'75* ;?'@ZDDZ~^^OUW73#5>65>6+"&'#5&/#"!76&+'4&";'54&"3#23!26?`e@p% <4$`$4< %.I: !".I: /(4v4K  K@%c  @ d  '"++"D' %5 &$ %%5 &$ */ / p f  f#.:@5>732+"!!.'.>7!7.7>?%!264&#!"6)@'6/&($x$(&/6'4(P\mR@7G< )6 2N9!!E9N2GSSr A@5 OpX =A37!#33.3732+!.'#"&46;>75>732+"!!@Da@tG@9#p#9@G_6)0 VhaDr8_')6#'7;?CG>7!.'.'5467!.'!!!26=4&#!"3#;+3#3#vv &&!1#r#1!&&bYY0@@@@@@@@@@|ss 2!@!3 u 3!@!2 Vhh@@@@@@|@#',032+#!"&'#"&?>;'463!27!!'!!7 1' < '1  ;G 7b K%%   " ^^@@@@@ @ ")07CL%>7'>7!%.'.'67%!677&'&'.'>7>4&" 74&/.'67676.'>?>#1A,.||., F[ #,   AX 6=Ɩ=6 u}  F1g T.]].T g3HM3(aBN(m@zz@m(NPhC6\63#&/."&'&7>766767>.?.#>7>76'.&X $97HX5"'#6P.J&9#tE/   H  15Z4/9@)%6--5'(3$P 77M: B^x(  @Gn k>G (=  9w  80fS)A61n H>@4@L6767#"&463!2+&'&67&'&'#.'&6>7.'%>7.'*$Mu9$6XzgWWLR"(;SEYg Z[yntDZZDDZZDZZDDZZiI=S;S39sXY ZTV!#:TAWxWZYqwZZZDDZZDDZ>ZDDZZDDZ'7''7''7'73'.'&67,=57.8a jo"w[U||K`(7.86>,woj a`K||U@3<ENW`i>".7.7.>>75#"&46;2+>4&">4&">4&">4&"7>4&"7>4&" 1"gg5L8&?'XlX'?&8L5gg"1@@ )66R66)66R66)66R66)66R66)66R66)66R66,*]nK#LC)4hEEh4)CL#Kn]*,C6R66R66R66R66R66R66R66R66R66R66R66R6@@ #'+!4&#!"3!265!!.'>3#3#@ )66)@)66I@@@@ `6)@)66))6``D@'E7671>25!>7&'.#&#'"&.75463!232#!"&46; 5>'':$)E }{v| 1(%9#)G{@{``q g|r_ccD@&32#!"&46;.75463!2>'5! ``{@{7}}cc,rrA@ &!4'!!>32#!"&46;.'47!%N)YY``}@@@vJ`Vhh~`~A@$32#!"&46;.'47!>74'! ``}@@cmm%N)~`~/mmvJ`I)9D'32#!"&46;5&=4673'&>!>3>.&/# ;^.Ro7`` HB `Rb1 P1T &\[ J00@>moUޫ S  {:E l .`X),?  k)32'#.'463!2>7.!2#!"&463>75Y47[5Ym6II*.lRRl4]f[0Vim``I66IRllR@ #-%!!>3#!.'463!232675.#$$A@(77(@I6@6I@  `$$;6))66II6x^#0=JV!5!;2>=%!#".=462"&=46"&'5>%"&'5>!2#!"&46"5D&f&D5"mf4]H'{ 1VD3&D66D&3m&I]44DffffB #.>7>3"'3!.'!.' %>.kOXXw7D " AP88PXO98Od: XvU (@OjVksX^;8GG88GGxs139GJ: /@'/7>J=4>>76#5.%3&67."6."!36.">7!!2#!"&461= uLLu =1ę@ UrU M%,%%,%~  9*IXXI*9 0aaֹ'F7CC7F'((((}}G1:BHNT"&/&/.>?'.467>27>!767!2?'&"76&?"&&.4."# m.4.#"  n=UZ3iv3vۏ  #'f(m #".4.m  "#=ZGvv a L$,0%>7!.'463!2!.'#76#%6!5@MBM@[dd[$$Z $    @-NN-?;ll;A$$ $ ќ@@>-4?"!26=4!./.=4675>7.'!3!26?  #5 00 5#ۣ=@)  )@ @; 1@. !! .@1 ڞk k@@'-9462>=462"&5.'5462%3&'&"&53#F99F#M@@; 1:V = V:1vZR`@':F462>=462"&5.'5462.'>7"&5>7.'#F99F#FYlRRlYF 3KK33KK: 1:V = V:1ammajTTjjTTjD%0;F%7.'./.>7&676/676.6.?>.^ B &GS; )7 &KOPFR OFO6,V9aw;QD%'"8 %'"9 #PK& 7)  :SG& NGN REQQ#CQ6!.'5&&673>73.'3."36.#"6!3!265%!>7!_@2iY' ",6))6, [@ZDDZ@__~6R6E $5 $anL``YD!> Ac6,E+)66)+E+DZZD__)66)90 &O `zz !)5>7!&!2#!"&467!.'5."H66H~@.٣$6$m36IH724響 $$  ,5#"&463!2+!&>!.'!2#!"&46``^v1 1v٣$@AAV]]VH )32#.=462>.'3>7.'&!]Vkj{٣@n]^W 2M%-0t٣e&#+ )5462#.46;.>73.'>76 ]NcbVp@٣zjk2 R#46nl٣t/.%@  -.'>>7.'7"&4622"&546٣((/@٣٣٬( @LXd3#'''7.'#367'76'&'#37?7'76?35#'./7.'>>7.q+$ VV.++FF++# VV.++FFC -::-"n!&DC !n"-::-"n!&DC !____DZZDDZZ@K>!C6KK KK=!C6KK ' ;@;"-8++0";@; ;@;".7++3";M____>ZDDZZDDZ@!)1?>/.76&/&?75#.'5#.O   F# !lDQi.Q[hnm@lR@l! #F   h[.iQ4@mRl@  )5>>7."&46%.'>264&%.'>264&0??00??0(d0??00??0(<0??00??0(?00??00??((A?00??00??((A?00??00??(('3%6/.>%"&46;2#"&463!2#"&463!2# % R  @@K!  #/&'6>7..'>>7.  ))⪪))____DZZDDZZ44* FF FF5____>ZDDZZDDZ@ &3@MZg2"&=462"&=46%+"&46;2+"&46;262"/&462"/&4"&4?62"&4?62}       E  @/  E     2   ;%'.'367#"&4673"&532#.'5>2>#.'&Wjj{@m^^E] ] Wkjz@m^^eN$-0te%$,J % 2N$-0te%$,3G/&4?6!.?62/!'&462"&4?!76"/&462* # ` ` # *#) % `  `  *#)  ` `  )* # `  `  )`)# `  ` #)&* $ ` `  ))  `  `  )) # ` `  *&@)462&'&471624>1"/"&5   )    )     :`` #,7!>75%!.'!.'>7!'"&462$$@$@$ )66))66)((`$$`@ $$6))66))6(G8?F#"&46;>7#"&546;2.'6;2+.67>7%.'>`23 G7\``>b rr  Cd#19Ɩ6II6I66IdsWZmE:@ppMu"ǼI66I6II@+4J32#'#"&=!"&=#!!"&7>;5>75.''"&=.?62 @ff3Y9 lRRl@I66III#  #` à````@@ VrrV;NN;JJ # # @+4J32#'#"&=!"&=#!!"&7>;5>75.'6"/&>5462 @ff3Y9 lRRl@I66I$  #I` à````@@ VrrV;NN;$ $ # JA#'4A#"&463!5463!2!2+#!"&55#!!"&54623"&5462@@@```@@@@@ !264&#!"` 462!2#!"&5!"&463``` %'& 6." $   #  7'&"?264/76.  #  $  $  $ D#62"&47 &4'62"&47 &4  K  8  K  8    @@     @@ D!62 "'&4762 "'&47  8  K  8   U  U U   264' 64&"a K  8    @@ t4 &"2764&"@ U  U+8  K  2764'&"U 8  K   U  Ut2 27 27564'&"  @@  (   P   e A+46;2+32+&'&6>7.' h }fhiRllRRllh gh sffdlRRllRRl@ 3>7.'.'>75.'!"&=>7!"&RllRRllRmmm6)@)6ZDDZlRRllRRlBmmmm`)66)``DZZD`L,?"3!2654&#%!!.'>2"&=46.!!5>76@@)66))66IvEEV``q]\%@6))66))6'A@ gG@&^VW@,5>"3!2654&#%!!.'>2"&=4675.'!5>@@)66))66IlRRlm@6))66))6@RllR@@mmL!"&5"&4762"'<     Y    A!"&463!2"&562"&47b   @   !!264&#!"265&"264'@    @   a!"3!2764'&"S           !2#!"&46"'&4762          @%4&"'&"2764&"       Z~  2  A%"3!2654&"264'&"`   `7    !%!2#!"&5462"&4762@    )    L #/?>7&3&&76$%3!21#!"514!2#!"&46321+.5146qfbv ?9oq!e`2  @ w>P]?gdMjX@  4 67.77'.'&7J3;Gtߩ> p&w+ d M͍/@O>tl d ⨨+w@!2)&'&67>%!676&'&.>.Vj j>~knkgi3#O`ok8=~#aw]++jjva(-ڄAll$!Oa sOPdK9TUJ7>Bpo)!%!&'&67>%!676&'&Vj j>~knkgi3#O`o@jjva(-ڄAll$!Oa sOPd*/.!2>5.'!.'&67>76! h_ 'IQ jKp*K; W8]qtd maVW =DQ?' tKJ^ ;K*InQ`s~cdTk[ @ $1=JWdq~%>7.'.'>72"&=462"&=4662/&462"/&4%46;2+"&%46;2+"&&4?62"&4?62"RllRRllRmmmm  . #- (  -  . g@@@@ -  .  .  - lRRllRRlBmmmm@@@@} -# .  .  -   .  - (  -  . @ !-&76 #6&'&"3!21#!"5143!21#!"514S([vxxv[(C)HghigH)  @   @  VTTVzNLLNz@ @ &3?K7!2#!"&463!21#!"514'>7#.'2"&=46.?6262/&4 @  @ `Ɩ@zz  D # D   D # D  Ɩzz@``  D # D D # D  &2>7!2#!"&467>7#.'2"&=46.?6262/&4 @ÌAqq D # D   D # D `pp ``  D # D D # D D*7DQ^/.!>76&!".5>7>762"&=4632"&=4632"&=4632"&=46# g_ )APcKLj Vlp1WD$nX}VU \s"]";CO?( _BKc`LLsm$DX0ZRjYOb````````D(=%.'>7>765>7./..?623.? a}nX}VU _s{`FXVF# g_ )APZ $ ee@aZRjYOa`A gGHh";CO?( _BGaH    D*.26:>/.!>76&!".5>7>763#73#3#73#73## g_ )APcKLj Vlp1WD$nX}VU \sb@@@@`@@@@`@@]";CO?( _BKc`LLsm$DX0ZRjYOb@@@ @@@@@ ",312#1"5475''#53%7>=4&/ @@i&00&@c  c@ @ `86&&68 )   @@ $%19A%>7.'.'>72"&=46;21+"5145##5!353!5mmmm @@@mmmmC  @@ '09BKT]fo%>7.'.'>75##5!353!5"&462"&462'"&462"&462%.762.76''&4>7'&>2mmmm(@@@@#  $  $  # mmmmC=L $  # $# # @ $%.>!>7.'.'>72"&'746#264&"#5#"&463!2#٣٣@$6$$6$_@`C٣٣|$$6$$E %6CO%>7.'.'>7%"&7%26'32+"&=462%&>&!6.6٣80 $80 $Z Sn1/;+ .C Ro1/;, @C٣٣C SS S1nS / ,;/1nS / ,;@ *26.'>5>7%>4&".'>7!5!!)! zzƖ$$6$$6II66II$ffoLzzY勋9@Ɩ$6$$6$AI66II66I@@a@ "#/!3!21#!"514.'>5>73!21#!"514  @  zzƖ  zzY勋9@Ɩ a@ ">!3!21#!"514.'>5>732+"&=#"&46;5462  @  zzƖ```` zzY勋9@Ɩ```a@ "+7!3!21#!"514.'>5>7%>4&".'>7  @  zzƖ)66R66)DZZDDZZ zzY勋9@Ɩ6R66R6AZDDZZDDZa@ *.'>5>7%>4&".'>7 zzƖ)66R66)DZZDDZZzzY勋9@Ɩ6R66R6AZDDZZDDZ@ $>>7.'.'>7'2"&546>7.'5.'>RllRRllRmmmmrWhhWr٣lRRllRRlBmmmm=A1??1AQ5DZZD5Q@ #!>7.'.'>7&7>76٣٣J J ٣٣DJ K @;?O!>7.'%!!.'>32+"&=#"&46;5462!5%!2#!"&=46$$$$6II66II````@$@$$$@I6@6II66I``` @@@ @&,59EQ>7%!2.'4637#27674&#'3"'&'&63#!2#!"&467!2#!"&46@lRRl`mm] "_A:s^ !`@:m@@RllR@mm r! @: @r! @: @3<FP!5.'#"&/&>;5463!232+32#!"&463!>7326?6&+5#"3Ot! 2 - YY . 2 !tO`lRRlB .YY. fM%#``#&Mf @RllR   @@ #(4!>7.'.'>7#63277!#67!2&"&6mmmmH #@%)'u')%6::mmmmC=  ``{@@ ").3?!>7.'.'>733#535#5#63277!#67!2&"&6mmmm@@@@ #@%)'u')%6::mmmmC@@@`  ``{@ !>7.'.'>7&76٣٣;@8z(@٣٣DnNFXn@@`%3>75#"&46;5#"&46;5#"&46;5.'!32+32+32+32#!"&46;5#.'>7!$``````$$``````$@`6II66II6$ `` $$ `` $@I66II6@6IA '77&76  ' 76'& 7&'.6&'6&'.&Ãf]w2wppwwpq#+>@N_LI ^IG#)" (<=MCfppw2wppw8N@>+#- IL)#GI^M=<(!@#Y%7>7%6.&76$762///.?'&>7'&>7'&462 Eu?r_E@s_E DtH8V0h^V2f  - # .-- $ --- # - $ - # .-- $ ---   GvDE_r??F^q>rGuD 0]e4V^2H  - # --- $ --. # - $ - # --- $ --.  @ %+17>EKQW.'>7'>7.'67&%'6777'&'7'6767&%&'7%6&''6&'7٣٢(!/m"2!* ## .m,' !"', !"2!)y)!2.. ##J ! 'Y ! ,@;٣٣p.#9':7*8%1?? 8  ? \7*8%/0%8*?2? 88 ? A&.;G%>7..'>&67&''67.'76&'%>. '&76  3;8;X?-K20\-0UHf8]uU?)[&W;~8;@DC##Bu]8Mf0;%6/76&/&"7.?'.>?>2/+rr,'!& c "(" c &!'Ɣx%%8 %ݜ''  ''% i@'7%!.'>7!>7!>7.'%!!.'>I6@6II6$$$$$$$@6II6@6II@6II66I@$@$$$@$$$@I6@6II66I .=3+"&51#4623213"&=#"&467#.46;5462@@@ @@&>76&'5.'&6%312#1"54`nc}}cn!ߘ  F;yyyy;F= @ @ $1>K!>7.'.'>72"&=462"&=46%46;2+"&%46;2+"&٣٣n@٣٣D[@!%!2#!"&5462"&5!"&463!2@@`@@ -<E!>7.'.'>7>7"&5.'"&.>?>>.٣٣mmz!@D$ 3$=#   ٣٣DmmfC?9G-  @ $%1!>7.'.'>72"&5463!21#!"514٣٣  ٣٣D @ (!>7.'.'>762"/&462٣٣+    ٣٣DR   @ #!2#!"&46>7.'.'>7`@٣٣`٣٣D@ #/!2#!"&46462"&>7.'.'>7`@ ٣٣@٣٣D@ #/49>C!>7.'.'>7'>7.'.'>77&'6'7/7٣٣RllRRllRmmm----٣٣DlRRllRRlBmmmm----@'-#5>!.'!>3!21#!"5143"&$$mm @ $6$@$@@$A@mm@ $$@-3??!&'732#!#"&46;>75>2.3"&%".762@.`7`r$6$2W#.6X$6$    @@@@6/%S-@u$$ 1%.<$:Q$$@    @@ E>7.'.'>5.'54623>7546232+"&4636II66II6RllRRll2z_@_z@I66II66IAlRRllRRl@z  __  z@`@$GUa.5>75.'>=7"'7;>7546232+"&46;5"&'.=462".762-lRRl@I66IO?5@3Ze.e.7@@_z@@.TS%&    0.@#RllR,@l6II6.I $8 9@y4X4e."_  z@@C)c6  +K    (.676.'?(,   1+O7  ()56B"3!2654&#%!!.'>"&463!21#!"5143!21#!"514@)66)@)66I$$6$$[   @6))66))6$6$$6$  !)!>7%!!.'>"&'326?$$$I66I$#KTKU282$$@$6II6$?"" +,8?!>7.'!&'>7!3!21#!"51453!21#!"514r$$$#I6@6II6 @ @ E[$$$v }6II6`6I  '09%!>7.'!7&'>7!"&4623"&462!"&462$$$#I6@6II6,,j,$$$v }6II6`6I-,,,,,, $0<H?3>7.'&?.5>7"'".4>323".4>32!".4>32R`٣$#\:(,mbj(- *ːː4f-5y@0=  ,  ,  , %!>7.'!7&'>7!$$$#I6@6II6$$$v }6II6`6I $%12>?3>7.'&?.5>7"'3!21#!"51473!21#!"514R`٣$#\:(,mb @  (- *ːː4f-5y@00  $?3>7.'&?.5>7&'RfѬ$!Z8(*x\(, (ȔǕ8h,5|B.  (45AJVWc!>7.'%!!.'>>4&".'>773!21#!"514>4&".'>7%3!21#!"514$$@$$@6II66II$$6$$6II66II  $$6$$6II66IIJ  $$$@$@I66II6@6I$6$$6$AI66II66I `$6$$6$AI66II66I  (4!>7.'%!!.'>2>4.#.'>7Jllllll11.>>.MggMMggllllIO3:3>..>JgMMggMMg (4!>7.'%!!.'>2>4.#.'>7Jllllll22.>>.MggMMggllllIO3:3>..>JgMMggMMg!C#!>754&'5!.'5>753>75.'!.'5>7!6II6@6I"9FlRRllR@6II66I":ElR@RllR@I66II6#:F`@RllRRl@I66II6#:Fb>RllRRl#''7>'&'7>'&6?6?'.[8 .2;[-ZOEA KZOEA KZ.[8 .2;[----[;2. 8[.ZK AEOZK AEOZ-[;2. 8[<--@(1:CLU^gpy!>7.'%!!.'>72#54632#546!2#546"&=33"&=3!"&=346;#"&546;#"&46;#"&%+5325+532+532@$$$$6II66II@@@@@@$$$$@I66II66I@@@@@@C>'.3!4&/.=.4>2!"&/.>76$= %$!=E=! )1$5 ,e)$ $ A"> 1!$T#<$$<# > B+$+-%  @@ $%1>7.'.'>7'312#1"543!21#!"514mmmm @ mmmmC=   %&26%>7.'.'>7;21+"514;12#1"=4'__`_xwxj(%(/`__`9wxwx(%(@#(:?Q#53+"&=335'53#5##546;2!5%!2#!"/&4?6!5!7!"3!2?64/&@@@@@@]GG#R cc G#Q dd  `PP@ p  p P@ p  p @ &3LX%'"&'3267>54&'.#">2%7.46767>54&'.#"26.'>7["PVP"[4EG~`,/0+[.4EG~3["PXO!>,/0+[F #!@"+L#!?H?c[[[,/0X4EG~3[!OZO!,/0+[.4EG~3["PXO! ?$+L#!?$+L@'3!!>73!.'>7>7.'.'>7$$$@I66II66II66II6RllRRll@$$$6II66II66II66IAlRRllRRl/ %/!2!.'&63!>77'!!7!>?LdBBdLV摑N C,^,C =?KK? J~ '#BO@@c*22*c$07;DM7#"&5463!232+".7#".7>2367!!3'#7'#>4&">4&"!@ 6\#GRG##GRG#>J>-M 6B"--D--"--D--` *I--I**I--Ij""'h`A ``-D--D--D--D-  $0<M]a%>7.'.'>7'3!21#!"514>7.'.'>7"&46;2&'"&46;2&/'6II66II6RllRRllR @ 6II66II6RllRRll `Z @%9*@*@I66II66IAlRRllRRl I66II66IAlRRllRRl  h 0 0`[".!'&"7#!"&547%62>4&".'>7@,z  %X,$$6$$6II66IIBB2 q e$6$$6$AI66II66I`[ &27!'&"!5#!"&547%62>4&".'>7@,@  %X,$$6$$6II66II> q e$6$$6$AI66II66I@)2#5!!3!"&5463!2!%!2#!"&546.462@@@@n$$6$$`@ @@$6$$6$ /;G>7&'7.'467>7&'7.'46.'>7'>7.'ŗ"쯯#ŗ"쯯#}쯯쯗ŗ;;"@^^@";>#c{{c#>;"@^^@";>#c{{c#>{cc{{cc{>^@@^^@@^!%IU^!#532#!"&'&'.=!!#!"&'&'.546767>3!2.'>7'>4&"  R @@ R   DZZDDZZD)66R66@   @    _ZDDZZDDZ>6R66R6#GKOS4&'&'.#!"3!26767>5#!"&'&'.546767>3!2!!!!!!   8 @ **** **8**  <    x**  **x** *&@@@@@#/!'%!2#!"&54?6!!%3'#'3+"&5=l  22@(@ T @88@` @&/;DP!!5!!)!!!!#!"&53!21#!"514!>4&".'>77>4&".'>7 `  `@@ @ `$$6$$6II66II$$6$$6II66II@@@` $6$$6$AI66II66I?$6$$6$AI66II66I@%!%!2#!"&5465.'#5>7`@I66I@lRRl@@@6II6RllR@(/3+5!#"&=#!%>732#!"&546;!.'!! lRRl@I66I@``@@RllR6II @@)-.462.462"&46;2!2#!"&'!!(,(\ "_` @ {R (((( @  f$-!2#!!2#!#"&46!.462.462`7p ````(,(@ @@@ ((((@)-06.462.462"&46;2!2#!"&'!!%'762!(,(\ "_` @ {Ro\\+<8 (((( @  f@nn@#!5%!2#!"&=463#3#'3#3#`@@@@@@@@@@@@@@@ "&*.#3#"&=463!35732#!735''3#'3#3#8@PxHh..@@@@@@@@@xH.."7!62#!"&54`  ` @ % {@  !-1!3!21#!"514 !%!2#!"&7>312#1"=4#3#@ @ c`cM qPqr @@ @@   @$-159!%!2#!"&546!!3#!5.'7!5>'3#3#3#@r@I66IRlln@@@`@6II6lRRl` ``` @#'+/?!%!2#!"&546!!!!!!%3#3#!!3'!2#!"&546`@n@@@@@@@@@@@@@ "+!!467#!>73>7.'.462SRl-__mA]]AA]$$6$$lR Dthzzm}aa}}6R66R6@$%12>##!%!2#!"&546;21+"514;21+"514;21+"514`@``@. @@ @$%12>?K!%!2#!"&5463#;21+"514;21+"514;21+"514;21+"514`@@@ @@@ @!%!2#!"&5467!!7!!@N@`@@@@@(-87!!7!2#!>!5%!!.'>75%!/&'$@`@ I&P$0??``@#ll#`$`:6I!(`@$?00?aMM@ VV +!!7!!3!53!#!5#!!#!"&5476 @`\R  @@@Xg  4!%!2#!"&5463121#1"514'>67/& @@@@2O}  2O| @@@@@@' e (d @ $8>7.'.'>3121#1"514'7>6?/&٣٣@@@@.D  *A  ٣٣D@@@@ .b0b@ +/?!5.'!3!!3>7#!!.'>7!5%!!.'5>$$$@@@$6II66II$$$$@$$$$@I6@6II66IA@@@$@$$@$@ #'7!5.'!!>7!!.'>7!5%!!.'5>$$$$@6II66II$$$$@$$$$@I6@6II66IA@@@$@$$@$ 7!%!2#!"&54653!33#3#3##!#5#535#535#5 @@@@@@`@@@`@@@"3462#!"&5463!2#!!76. &?6762@@`5D $  iLME # qOi L@@762%!2/&"&'46B@#  #E@  !.;H%#'##7#"&5#"&463!2+#!!2"&=4672"&=4672"&=46oJooJo@@   @@@@@f >73'.'>!.'56! ՙ@)_bC!3# rr+||+t@@!65555&#77#&Y@@ 3#3#53!5377''7@@@@Z----Y-=---@`@@@@-----=---@ !-3#!.'!7!!5>>7.'.'>7@@$$?6II6RllRRllRmmm@$$eI6@@6IlRRllRRlBmmmm@@#GHTh";26767>54&'&'.#'32+"&'&'.546767>312#1"=47"&=4&+"&46;22  2222  22>@/ /@>>@/ /@h @``)6 2222  2222 @ /@>>@/ /@>>@/ `@6)!0%#"&5#"&463!2++#'##!!%"&4?76'g@@oJooJH  }m %    ^#b .;!3!53>74767!733##!"&=#.'3!&767#7!$$=n% FI66I}}  `'$$G9QOFF@`@@6II6ED.)980@'3?5.'62.'>7.'54>2."267%2675."٣D<"I66II66I"7!..'@$6$@I66I:А$$6IIv4!*6B&'&6767&>>'.7>'>&'&>.kJ==c189p!["o981c=>Z >;;k#4  4#k;;> Z>V)  8V*4.BJ.5*KA%!7'#!"&5463!2%3#@``@Ȱ@0(@@+4!>7.'%!!.'>!2#!"&46.462$$$$6II66II$$6$$$$$$@I66II66I$6$$6$+5#.'#3#>75#5!.'!>@lRRl@٣I66I@RllR@@@٣6II/%32#!"&46;5!.'>7!!>7.' @6II66II6$$$$I66II66I@$$$$D*%"/$'&76$>7.'!2#!"&46}  }wrw|D{WƖ}  }m{D|wrwƖƖ|D:%"/$'&76$>7.'546232+"&=#"&463}  }wrw|D{WƖv```}  }m{D|wrwƖƖ|````D%"/$'&76$>7.'}  }wrw|D{WƖƑ}  }m{D|wrwƖƖ@!-9!!'!#37>3!232#!"&546>7.'.'>7 . 1 .DZZDDZZD___@@]]ZDDZZDDZB____@!-!!!5!#!"&5#"&5463!2#32+"&46@ @ @@@  7!2#!"&46#' @@-==.@B>-=- 7!2#!"&46%7 73@.-@@-=-E,62"'&472764'&"7.67Z<;88OOKK.h88<;=%%(f' $ &-23$ 88<;KKOO.i;<88=(f'&& $ &- $41@+/CGKO%#"&'&'.546767>;5!32+!!5!34.#!"!5!3#73#   EE   @@ v @@@@@ \     @E  @@@@"!!!'!#!"&546533##5#5@ @N@@@@@@@"!!!'!#!"&546!!3#!!@ @@@@@@@@'!!!!#!"&5467'7&`@L.-@@@@--@&*.!%!2#!"&546%+53!#5463!2!!!!@n`@@@@@@@@@@@@`@@@"'!!!!#!"&546'77''&`@C[.Z[-ZZ-[Z.@@@@Z.[[.Z[-ZZ-@'!!!!#!"&546!!&`@@@@@@@@!%!2#!"&546!!3#!!`@@@@@@@!!'%!!2#!"&5467'7f --@ --#!!'%!!2#!"&546'77''f [.ZZ.[[.ZZ.@@Z.[[.ZZ.[[.!!'%!!2#!"&546!!f @@`@#!!'%!!2#!"&546533##5#5f @@@`@@ $!!5!'#7>3!"&5463!!232n`|2: N9 `p@@ `@ !!'%!!2#!"&546f @U 7'77' 1!5!!f9h1Gpp@.^pbpgN@@@%1'&46276/"&47>7.'.'>7[  ZZ# [[ #ZZ  ٣٣Z  [[ #ZZ# [[  ٣٣D@7CO[gs!#"&=!"&=#!!546232#!"&546;546232+"&4632+"&46732+"&4632+"&46732+"&4632+"&46 @@@@@@@@@@@@   @   `@@ !@@ @@@  >.7%.>%&>&[X!"S`7JO3&JM.&ZY5M^#i(.W],L2i"%.'>%.'>0??00??0??00??0??00???00??00??00??00??00??00??>/.76&/&l   A ! l! A  #/<E7'#!"&5463!2!5>7.72>5."4>2.7264&"ZDDZZDDZ>-2.6R6"7&>23#I66IF:p $ r:@6II6@!v  u!  !! @ &2!>7.'#'.#!"2>4.#.'>7$$$$t. .551AA1mmm$$$$]]M7<7A11Ammmm@ .'>'&"276.c    +@c   + @ &.'>'&"2?>/764&"h  hh  hh* hh  @{h  hh  hh *hh  ` &>7>7.'>4&".'>7p;KTŗTK;p$$6$$WttWWtt VAUZ[UAV$6%%6$sWWttWWs)3"&5463!2#%'&"!&"2>5."`@E    -2.6R6@E " %,,)66@ '.'>#";26=3264&+54&"  @k  @ 4.'>264&"46''&76&'7>>""3""%5 X#S5 W#2D@44 =  (9, =  '8@ .'>3!264&#!""t@E @ !.'>"2676&>4&""",@&&,,@ *.'>>4&"3>76&'&>,B` A??t AAI' 6@E,, !RAAl/:)"7.'!"&=>7!#____`ZDDZ@___A`DZZD`  #!!3#!5!53!5!3###53#5@@@@@@3!>735.>25!p6II63&'bb'&I66I&tyHHyt6@@ !3!3!3 @@ !!!!!!@I"53!54&'.7>76>75C=#ODhO~EgXu@@@ P2A&%B?ch$fqey@~ !>7.'>7uuvXXvvXXvo*؍*XvvXXvv@)3#'''7&'#5367'767.'>>mm>77VV77>mm>77VV7slRRllRRl@UU@_`__`_@UU@_`__`RllRRll`  3!3!'5!@x.=-? @.=-`` 3!!#.4673!0??0  d?00? ((!.462.462.46237!000`000000w@!!#3 ``` 3!7''."26$00((Gf*f*u(  !!35#35#%#>7#.'@@@@@@@lRRl@I66I @RllR6II#.'55>7!3.'>7 U=ӝ=U U=ӝ=U =U ݝ U==U ݝ U="%3!53!7"&'"&'"&'"&'47!@@6R66R66R66R6=@ )66))66))66))66) @%"&'5#.'!%!`6R6`6II6)66)I66I 73!#3#@```` %!5>7.'5!35!!5#356II6@@6II6@@@I66II66I` 7''773!3!%5!----- @ ----( @@`` !!!@% @@BM@@a/o/%>2!!"&'!5>23#"&'!5>2!!"&'#5 1>1 E 1>1  1>1 1>1 ; 1>1 ; 1>1 ##@##@ ##@##@ ##@##@ !!!!!!@ࠀ %533!5'!@@@@@@`  3!3!!5!!5!5!@`@@` @@@`` 5!3!5!!!5!@@@@ *.'>>7.'?'7.54>٣s  @٣٣F2 L @ $%1.'>>7.'312#1"54;12#1"54٣# @٣٣   @!55>732#!"&7>;!5.'#!#"&=!"&5@lRRl 99 I66I@f33f`VrrV @ ;NN;V```%53'3#5.'>7>7' fw\XX\wf f^ WjjW ^f@'&>54&"@ # )  : $  265264'.     )'4AN[2#!"&5463%!3!2>54."2654&!"2654&26=4&"26=4&-"##"Z,"",Z,"",    "##"=",,"",,"  -   - <        }-=6&/&6?>'&'.76$'&6&/&67,&[ EK^-<@a*  [T? $.T>* 7 0Aa]-<  T>&#1GA#0=5463!2!2#!"&463!35#"&5!#%2654&"32654&"`@```@`@@@<L!!.'>767>/.&'&6767%6'5'&$?>/.0??0`0??t7IPw  %U85'RB= 4 PU>( @?0`0??00?Oxs7J  4'RU:)1 % r7(> +#* 1< +C n *       V &] Created by iconfont elementRegularelementelementVersion 1.0elementGenerated by svg2ttf from Fontello project.http://fontello.com Created by iconfont elementRegularelementelementVersion 1.0elementGenerated by svg2ttf from Fontello project.http://fontello.com       !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~     ice-cream-roundice-cream-squarelollipop potato-stripsmilk-tea ice-drinkice-teacoffeeorangepearapplecherry watermelongrape refrigeratorgoblet-square-full goblet-square goblet-fullgoblet cold-drink coffee-cup water-cup hot-water ice-creamdessertsugar tablewareburger knife-fork fork-spoonchickenfooddish-1dish refresh-left refresh-rightwarning-outlinesetting phone-outline more-outlinefinishedviewloadingrefreshranksort mobile-phoneservicesellsold-outdeleteminuspluscheckclose d-arrow-right d-arrow-left arrow-left arrow-down arrow-rightarrow-upkeyuserunlocklocktop top-righttop-leftrightbackbottom bottom-right bottom-left moon-nightmooncloudy-and-sunny partly-cloudycloudysunnysunset sunrise-1sunrise heavy-rain lightning light-rain wind-powerwatchwatch-1timer alarm-clock map-locationdelete-location add-locationlocation-informationlocation-outlineplacediscover first-aid-kittrophy-1trophymedalmedal-1 stopwatchmicbaseballsoccerfootball basketballstar-off copy-document full-screen switch-buttonaimcropodometertime circle-checkremove-outlinecircle-plus-outlinebangzhubellclose-notification microphoneturn-off-microphonepositionpostcardmessagechat-line-squarechat-dot-squarechat-dot-round chat-squarechat-line-round chat-roundset-upturn-offopen connectionlinkcputhumbfemalemaleguidehelpnewsshiptruckbicycle price-tagdiscountwalletcoinmoney bank-cardboxpresentshopping-bag-2shopping-bag-1shopping-cart-2shopping-cart-1shopping-cart-fullsmoking no-smokinghouse table-lampschooloffice-building toilet-paper notebook-2 notebook-1files collection receivingpicture-outlinepicture-outline-round suitcase-1suitcasefilm edit-outlinecollection-tag data-analysis pie-chart data-boardreading magic-stick coordinatemouse data-linebrushheadsetumbrellascissors video-cameramobileattractmonitorzoom-outzoom-insearchcamera takeaway-boxupload2download paperclipprinter document-adddocumentdocument-checked document-copydocument-deletedocument-removeticketsfolder-checked folder-delete folder-remove folder-add folder-openedfolderedit circle-closedate caret-top caret-bottom caret-right caret-leftsharemorephonevideo-camera-solidstar-onmenu message-solidd-caret camera-solidsuccesserrorlocationpicture circle-plusinforemovewarningquestion user-solids-grids-checks-datas-fold s-opportunitys-customs-toolss-claim s-finance s-comments-flag s-marketings-goodss-helps-shops-open s-managements-ticket s-releases-home s-promotion s-operations-unfold s-platforms-order s-cooperation video-play video-pausegoodsupload sort-downsort-upc-scale-to-originaleleme delete-solidplatform-elemePK!%e(n(npublic/fonts/element-icons.woffnu[wOFFn( ڔGSUB3BOS/2<DV=IcmapT*8 ҩglyfY+Bheadbp/6"hheab$hmtxbddlocab44}`maxpe  1namee,JaÌpostfx sxc`d``bca`tq a``a cNfz"P ʱi f#Oxc`da`tB3f0b```b`ef \S-x~C sCP$W Nxu]R`ˠ vw3(%H#vw9& &֋u]wP%zޢG}x-xEzy5?ĤKcyV>;f쑽O.%V>g@ 1;Ŋ!;e왽o.>/}NlBOgGaV~5]WN^cm}'uG}61MhJ3ӂb Zӆ=kk+zlFlYw6e39؂lVl6lvlN.K7{{^A!aQ1KC_xNDq's rsgrgsrsrs rsWrWs rs7r7s rswrwsry@1!#>>3> n/oNXOg~W~w`URSjڥN[:ƥIiZEiYZ5JҦ-S/5kT?oSLO1ЪAV%E *Ab $Eb$ObU#M,1ʪWM11DcM61M;1M@L21ٔ SBSMYAL3tS~3LIB4e 1˔.lSsLC5e1ϔB|S LD,4eȔVbSnKL F0/)LL|lJgSN̔'09d'Ҕė'2>oL]@|kj;S?KMMA,3u=L=B,75 -O!V LKд ȍLشMLldӊ 75 r3Ӳ 6imL´@-BniZ%V}BnmZ*6BnkZ/vCnoZ4mChZ9NClZ>. D0!iL mJ䮦DfO%EaT䞦uEeYަEc^侦FgceF`h䁦FdmGbr䡦UGfwᦥGa|䑦GeځѦEHcچ䱦H1Ei9Ǚ6$yiM'v%yiaL[<ɴ:ɓM<ŴDSM<ʹNM;<ôX3Mە<˴bɳM{<ǴlsM<ϴvM M[ȴɋMĴKM̴M;´+MۚʴɫM{ƴkMδMM[ɴɛMŴ[MʹM;ô;M۟twe@kLyn 0]䃦[|tU ӥA>j9L!0]$dmB>iRȧL 9tM7 9t͐Mw 9tOnr!r"Gn"r:"G$rb"kաo VΟhIVƪ*'[:Z:[:gZ:Rul+UϱRu\+UϳRu|+J TJKax `[Օ0}Wk-[bIv+eIvω:!C$@Bh%Jô`H˰B,[(˴R:Pv:_i;tX$'}ng zDB/ lo2u7`4I&zfOh{r]H?'4X^utu퇚;ח|tc̞ l>h5ۏ[Y,19HY}}[?/i>ټQ , 35AIVa;5 ,( uBd3D,5\^Zsh"H5Hr A|Plv;"D ٕY"g ɶǂnrd۳q|_q|ͭ.&.4 R mv`2$5P1$?@jm"4=AnUηg,ʹFۼC -6P趏"d p^V貑qKq'll6p'? #JF|ɰ{<1'Z8;i@CCM3|{ft?ٶgc_nu:ەq-z Ą0Sea{^4@$D &M<\aơYlAl HɬnF6W4Ҷ ]6FW3^/zp䓿s LD! Ce3B"tY) >{u;dX]'X}ơ>"f P'_:_:oL`.(,-MfUMD<*N.랐>ҥ5,@Х~]^[,fMZ #X(oito9Ioއ`շRO^͟%j&N եuiI 9af\a x>@4^90j9~服ߋw \ d. _**Nݛۮcl]p^ao+-ͣyv}{o\~ l[-_߬qhdAh4̧y2a·R ;(H(nJ̥ 49(\)DL"F$pInvGw8CI]ɡo3cG6cM%f́>gh4mQclv}yv.Gl40W!E䋑5V?t#mg.G*s.͸uΣ#@Wsnsr&EHH'6.3N>iYaq,(! e"QD F2j b>_"L̠?Jlm2 Ww7ZH?־:ɴI&xz'j$ 츆}]xG;[8;$O:5 Q5hj kLksn5 j!Wh2}-޲DJV0NK&#}P1ָ|$1(QAǩq~'ɲ u~B!?~Wպc BTu/=ݻ ,:Eidvco0J߹ݷ9ݫ‰s64\g} Ťt}zGKnuevYRuӇ6Q.Ahj'pաb4D*_.QȬs2еEh4Z@:YTF)aVWػq.|KX'(]TzׄdꮕDnx0 \+C {K!>aNdstT$A[!6 J%+AAKiTJL>)zd)C4Ey&!W:@rba ΉL<Y )BA,8@5Dh1rQ_1H mcy_6gF#f`/4ލ ^zBNfLAnq@J9Nd#@@|4hcE(2ܐs;ogO|6{yh!$V& IC4 :/,G Eqºur#z"5GIȸoYGZLo:Pm6Ӿnj+t`q5%Jv8h}B r}i]<2CC ;@ f0%x#2e@@,8`JFMݳ˖,_>*}4k ;V[,ŧd~k,}UQ p]Z~:B-Mwaݖ-u?Fr~}n\R&qc z~p[)iFckpH sY}lej$=C Ab&X1K$?xR)ޣ Dclfkн[zY~MFwil7Wt:!os!/z걃 ghL&vfmX4ݐ8'V6{4ߥݍcF!<- \':.. ԃIqE=BGETL≡$8/ߕJsLK%m"n!}i|}KQQW/ _892s]×kf{-ݿ Vr??Z`d3U(ϵU-iGχ;(i_"߶||Esݴ([nrɟgV]@Y'$a`Eir%qAt O9hD"4l0(  0p{Ζ]Gbʇ?e[>\>pȏ7l2E}iי4Z1< {ˎ/Xf+EΊ=k-ouq/-F4";lnidJ3v7-OLByY?!jf}#F|p Q R榨n=xt.AQKeryF[k&-zE.$ɞ%yoHd25+N3K0󈡱C)dFSEooI˙?|U6GQ'uNH-j(0#0]Hxw&WuGJt?>vY7;\O?L\±t?&`kk0>$߁r*/$PpH<ʰmnC_eV 0`ظ掯m; 0{ =$0dVZ1ڪs*\ RǐFp`&k޻ +]'!|JGl]2_s,wv={)+Gݗ\gE;@\CӪF..m}k KrGa26^;g \T\(vQwj3\E]9dP |Y*hEtYYv>(  yt(v#{:}7{MGmx~+Ϣ^ؘ8H&`za []o6^ohMLy!Bx mSܛ5Ž򍮡!e,2F x6.@v ^Q \XuN=ָ"45ZӢk;ʊ>\-h6}:H]韬zӗM~tbա[: A0&dVTE#Q*L)񑟷֘t/g?ҋi7Lam_`d']%a0&@=Fh/F^{!f{@`*텇?p_h~ o(IP9?`i43Cfa̜y4u.fL5yRS)(^':1ȕir(p.2Zچ -n{ѓMQKa亪˵@R^57 @_ |;kI(:G` {炅AI5׍zztA=FGf3xA< xIfO(oeihĸn=:(D`{&9$U>`BѠRJ(JpV4?`BKy TЋk%<ᘗ^_} gyT1}pMgdK:HX]=Rq^1ߓ/>s/1o߾:|b̔Y+0U$UKֺvS丗=B鑽cˢ}U_}BTe易;@_Zcɘcro΃tk7fx=}$oGD!s{opxh?uoಥA"Y/,¡\ZLuyT$J:}[,#dـ_nZ+|Wq`,LU{*vx7EC73j'_+Ni^vni0hE"ƔM,@KqE<|1^p"Y#&H\ANEZBD PfA9j]dhDVhie08ȐC hi2! ph(6So G d$3A-}Tq0rsKD!Gh!4_Y'N q$\@AsnGG蟙^@GGD̀!dlf'f[7&,?jrSHz40ߎ0@yfƕ0p RHr2t;\47LdLVr- oBeE9(݂Ym7Pr]J{Y>sʱlDZB ڡdhbE4}MC@p&T= uWڛƢJSh.r2#X%3 " p MM'K@Q+' ŋ̌]1\gjUFߢJX~;u:R4i*;vZ/پAy *ޝ`Jb)-Gz2 IWB4eZD~_5#!Eq4PQ_T~.i:PwsEPLc3]a7> @_s@_$d:$U% @qtY 7o !y@|!nnrAhUol DcaM޺5k+tۛ׃K&9y2gR7xAU#g\qkBau>,#0b:QL:wSLFq] fdm.0L 9/G**"]y|.yV73fPb0Vge&0UTW)6<4bwf(d `;Z?I'HA9s"^30Oh,Ab 3N @:KQ!qNV]# OxG_U~b!=FE(1y!ꡪ'yC+H9B/E:q˪ڵͳ|ҹfccƄ c˶C|^(=`rx"GYR o?ymI{d{X,'8cqnApw +>ơ7ۂK|uR9 s'/O TcHќ :ܿ_W\Ӈ_Kw'zugm3#K_ޭ3MR|xy۱gu?!\~W|᳈#; 2Pnxߵ-X7v4v9oi|S7?Lnص--:%Wl#wݱ^,9{/jW[ 4di Q-:K`;Ԣ$3Hs Y2 Ev^iN.:``6:&k6^LţG0;fM=b:k(iv_:x N[#K[ӰB~i~|M ۄk{*@#SSa gMT]pL׹T]d&vW-hfXV)siG ]*N)s#}N&zA2(S@:7Fă$1QE8m+H7m_cXY!LLƳ[yͪUkoeK,*40>G ,VFtH\zͺ.f<\L;yÔ tsvD #Y¦*\bTo#0)b3w6YڇWuYrYw{׎=֬)|%hNu сCmF9[)/Yrɗa޵~rMDs16`BǑZe3 rJ#;IEl_Gɚ& cݦc>3xfl7d-Jܶ%1l߱`N ,$-uu'h3lOM 3qy}eK~j :L0ƥ lEQ+IwwFrJbgw}sI lJ*"+Q["ŭ:VQ  俐:wcOMIdu}$n#v71U*ӹ8P~Ի3 '#>3it[YnDx䦓BQ m )yx&˃Ū/ ŢRlGmZuXzQ.\1k޽Q=Ir(k8\3< oҏkG{!Sv2HzjֽR*jxXqV!?m@c3ځB~wZή4)K dUK,Q Y E *8)uڣgĆJQYIi!άVIYpYҸh9W@r&'eח ϋX=BP0WX^{d(FĒD]^,xb(#jVK6_q }3b={O=%m[R l;֣=g[[f-fh+0@xٚ"(ojF zO&JU soM9"rKIvx(Ol~H&8_7KH[(*=~ '\$YTߢz̖r^SWTRU9  Ԃ {s-\gT,6z6N dl(\y>yjvt&O9@N 8_ծqSX 2jEϹE3?85vO+kkZ/*Yvh@N'[Otӓ"ٹv-zKMlu ;-Cî22T[*jc|[k#&GM6 Ѹ£.mGm;^Tt{9VRz>YqJpE+/@ TY{RGS'ZHV E e^֗N}A0%PU3k&ho\gzo"rpř84.\=l7@2&Qi U)"QFst[g=K6Y"K3CvKsqȘ֬@%^|Z"_{%\(5sLtFj}b-Jn(t#5ai)YbDa.B$M&_ꋄ{,?^uaѐ2#K4ݼ'ҜKLQa,7hJtY^n_o9ꎅxօb^NJf=jQ{U53M*3!C^/[\ vsL'/Kf:GI=5Gqk&knɲNN<,+` ӆԆ: K,2Ub=d׬$zPDqٚ-4 ]&logu{T3# y>ӚȨUkbzbm!DNC&)#Z BFy'Ų9Q+LG\ևS&ߒԹ A"EA8czD ?%a,@^pE"M/pMdMl\w%BAeFW, m*.Zkf>0M7<_>qCҠ# /Z؂EMcg5E42^p1O !s!(nѡ2hg>0Yyʇ^> wّ}K@F.](>sӚ!DX]l:;Ug]1&?AnjbYۼo oxp߂F|RFr}w$s]=tt ;;SʏN~(rye~j\8d󳄵@os `I]i x!"a/h*|f&B".!bx/U&:Dkzwp`59uοuv4,|coeoW}h֍o4F_K!]elIQco.:4Kj]8]Ӈo#wu,N 7jNt.IFbbio5Gۢ{[lfxBtFoyD#Nqbu:g>H&w<^;a!t|=o^4# 6WXҜOó悁a5\\0v EnH~OǜCs,Mx9sq?AL. (j8UN(T(ˏ0j{8%(r Q:Y'k'tIDp63ƫ4=[-s+ʡtb;W^yw\y;g뮯/elңp Z>FVgٯ&|lOjkp!|QRŸY~*DxJPĝTqܹe+--;Y엚-IKW}8%<,胃ԖDeʙD|\>&gDi[gc4~5<ùLMY;_Iun]ˢ10\Բf@Ԫbj}Ujh}:5@ 2XѸZTp񃛦9T5.wk:LZh-eoh"p&(i*j>ZNW3vo%kb8%ɬ$6`oj(xjz(rOLkE= {egk&AɖM`3”>UNAH/$/khC )P,"B-P.H  Z;r%_\f8q)v?0A ySz1O|c"e[۳6~u`3-$IΈݩwt٣\lvSZgΒ#pCBUء}1F—(l”p*3|_,Ā V3vz:h,m>N8sRH]Er׉ajCRq,] zd\ʪluc 4<唕&vv;K#2!)=v^TNRj 5ޯPҕ J1|7I!fl KWm8/ Y~c4G=N$l AIPVhwutvߥ_g NpO|dN+)>2bN0]m[[朁ϮwǧwDdJ1ۛ erk)dBe}GWYY+xʬ)p,bQXP%hadU rithӇq˂qG5$%m!?~.|riOQ&*[=Umeru(nYcE+8\/(uZϑ#Gio=R_ | .2`L> *P洽M6Vx=e^eg֢A^A;:˃XEgt]ځL`?ɯ\Xŷ{m5ڦ߾o)[W6֦{λ^^o[3)AR.fQ [OoLej)ߨОP𓤎K\S>:Jlp/LpvD2}3̎B*`j+)mMNbBpŏdq|'?Cs0t;7.7C^ޜnS!05POss/@ ?m=P >i_?pO00 bIDy@pEC1Rj8TMW=9!EYh[t>?wP\st5EN~Ld1WO$ }T-:ǖ G+DZʓNٹaoCjl>ǿ ~?믱_ݎSp=nj/hJ*םщ)2BB$`sav*d! p)"\@{X8ˏwDT ާThj%_ntA'|oISfGl7ڻY -qT~^;F0~md5 Z#[URjm{s:oAۚS_V_j>ղ"W.jdg9sd67yP%GhUZ_ pd&&I|Pn3\q(w9K/hYA6oA/awh?9cv WF,vT/If>OrOo T(A6`xd"9e?he$тR(7.X@c7J&=l5ZhQ srL$\xHp`+VKOк\ok&ݨֿ_02gA)'u7IxA"5Lw/pP`5J?]fEtCy Oձ1Ůp<Md꫏Ehǒ&x͑ͳDq5$T]G\v.76w:4}f7:?2:DlF6x%iY.?&IzUoЮ"pwa GToa(cʑt6犸"d ؐ(z予CY%fq.`傘z~ v}hpv3u W6y韶s4^FCI) úyy7#D9 KT\rRa#j!'ԛTj%h& s#ZClkB0 @f+Rk(ǦiTc0(Dywn vf';QiL&#tpw͋j4QL)rl8|3A==Wڈ_7Ta)=O|Y 4M!h{p픋u"A!<-Er=@]yPϟ!2A#@`ްCƕ5ݏW%Q}P&j<1 CL%)55sd =U*6ʠxr ;WI2Ϗ%y Bt}+:|LyC +W@(*mt 4ƶ^M[cָ|Ճ#m*(CŅEG!;@"vVa{p 4(7a`oIu;FZ(mL: FRZ^K*r_ڨT.hG4~))pwUf&$-v?k0*,h^jYQZ"s&Ă`tZJ4F ͮir-MiצMsLfMXh::#P5B>|D9!LZ۱mb4"Y ]3OOq`FdiEf?' ɻN&>OMoX&\R(4((Sz#Y?0Jf tƐyM:)e*Ř(8z"^\ P hQ;2j /Ry\^R٪?]4Ū`Tl+ebϡ0j%~(x`34o0$154pBi9R;⎍$GQч \ (#(&1hE2q8_ EUXy!E 'Y2.IᶣVR p( [ʷ9}JX:EfGSM-+KV(=X%aKERP&t]V\O s^A{EcM9>NyV, X]Rb$ԋ&\Յ'kxҘCOxs<)Y;J{SVئ-kczi( p] knGBA$-g焀#L5$6ƔUڑ@:K`P<G OI կb'Ώ dGN xB~,7Ĩ&2?D#h_!BfmrXAFM*>za {*-+(%Ŕ$Qİ۷Vy)y/= .qꒄQ@7Cag} V,%r,TkVąq؎)LI66nT5az1%hPA-S` Q@ðcfI;҄bE|^L9nq,f* Aޅ)—(ld?P*bTZEsJEPq,RZvO`97!ĘLV@?[-P|VcDHr)"}t'_?'`HY-(=w3iQwd6@⊹bSQKWdB]"8PH) }gՐ8SuMgmdO w>Nz$I5(V/h`0Ih[F%hVeSn M{t?H8r墌htS*7_.qoD$+Ӣ-/]QzA70^fUU#:3=ER,(閿/]wI벭Ycsy uB+[ĈbhH$ÓDjEwOQ<.|T>,JwwDޞSfu tDK>j41d$;\rD魁P34ݽb҃;6-V1μq0 4{ީ_r`~睆-XLtb <JO&Ic%pIGS6h俊3lEd NfCC8Y5N}q$tpYنTŸO̩o4|qk¯™I%1XU1|ld[<0 Y-6yfnQ,Q"pk_4W/ ~]9Z90 PRXU6V1wJRׅ{1I:!bx4MB~H1bw?o>.8p"SETD)6$*7ю1!)‚ n=3">)yl*)r_S|d=75%KG&w@F2Tϒ77Iu[dISٟGbEfy0̴(rpN~s#@p _mbS9M \'AZ+sbɘ1U[`[a$0JE/~]c@ 6JsǫVh0z,MY cuBP^!J#0vHG$z!~\oGBO=kN6;_x75qp?~eĭ_ 텮ܛ+T#|Elc,d.,OH$Usdks0-j0O4}"I\zC2x@uްȽP`D|Ld_sik[HT"Yz0CitVh.]WnX==؜X_^?`NK~V*W- _k .(ӣ=" @]\,uBoCd6?%@4 /?/0"&P"w5AYeL=1%dk8C9^;Đ^ gwo̅*a'8Y ̢tj)*aU+5ZQ/L $YL&K]s;%;k/w"1Ci~O"^ZR?ΛxrʴElWSq8%  N<7(d)UiBXmq  9}ǦCN}ey 3L|#8Qe[70 Cق1&?~%H . %$E" .x.`ڕ|'I(A"3yllO/MbPnߡODvM[4Ff_ZQrwJxm{R~]u[ aFG|Y}}d6H# ~q[{DUl{}*7%B39D JW"F=` ̣¼5`7/e cWV#e ?9ʗŢE%w|8ys A䢡zB[w>0l2\!J pm|P t2 &BI҃2M帪=ƐB.hFa84(qlqLk%(UM$}Vz̉R^[%SBU ,}x/Ȉ~\N{+~P՘n UX$㔸p6sJfqO!/} 6n!Z-1wCjlCX熱Tx,A}>hY>rtr)[|*o'=(0NS&W7̎HDx2d̅<) #3 =O5=_]Vh3.6HjǍxG{jh6a]ktMY->W o!\9O ltj߫/NQ/($->" H{ɧҝ)i{KӣOv,ҡѠPv5nR3z7}j0 zl #j(3Z+4+BE] .6>eB_O_Ryj8< C_"&=ٕ^u`Z$o=fR-2F1S.ހAcJ3@Y5$*1c(J.RPX 66+ 7Ο)C?#\7 #sxKЇ5yúH|N/~)xiM4lc6j%=GYg͋YZ\uΐ5ε[SB .ԵROP<*3ݽLtM&zf[D%X޾fN?L7l'SG""M񡏕X^~  Qh/:`ju 񶱳'Հ򷢳TH$$LJUU@q'2\Fkb3cF1 x-P|nn?trENa{UKyI4WBUN۸IF99ZOTl&q>lk/ҵ, 5ë;8kWa%k7/ ] g_@bbfQ*?; Z+$wJ %B`c@'/{_n?e)h;δ#-H% WٝN]tBY>+ X=L3Ş1I DDI1|8S?N_]Gwfno/w{'9\.5I/O7ZZKir}C_V/•X(}P(h%(J4"iIňXmݻ!ݙٿ3}G|;s$f!15*K0~'ռAzs\g QZ"xvYwZ aQ&8MVc]^m'TV{/׷sh&B::r'%Ud 3iJ :;:?~7)G|v<-2/ ËIvs=67}c5_1=k~ؑ%_W{\_R%(_MyAjjiF rZiq7c9F#qF9},֋. :tZÚ)7 ̈gS#7pZvV:k֑ޖAwցR1/@Q{e[-پ98!8N+EF#؎c^o/>9w!UkEhͣKKkټ$t6o~?mB3<RHFi=g#>Ǐ+̮M{tϓ^ƕM~`k' &" /#[*Jl|fYH ^5+ ƻ1o"N%|q`G _j/HA }]>wZSC@*ogkߏ=LYpPʿ]/Ga= tukiZ-/в趠GK/~m qW{NIZ Y'Z N5>C--0{=_m&D􉋔^٠dB={?E70ʟd_WYJG3.y1d?-cXkcb7UT&5dtt+ىaE8 6,5 Yzܻkвw^0^SM¬ f0 }d=;8ML~Ϗ4!E!uTU^\#N1~0~͸Γ_mZ7sfA(GRi>S+ȼE% r,@\U>c29:l=փ ;xsS;53Zә黼XFDxR39_elߓFѱο<:Fl$.=g'>ĔBf<uƳ.HcxW8TF9e&̐ ( 0ZS(``DLxOqiJ: J.L3R(n H8*!vL!a7ksG ]caNJݧ+cOS"+F$uLr뒹;d=KhIYgv1\K#Q^(cDbcswD e~^䉋U6u&'0"߉xc`d``L6_Y@mL $ 6} Jxc`d``n@0JG!xca```ţxba;en.FnZh<,lh 4 B  v @  ZP dX V2Fd6ZB2bHxd^L\lP Z !!h!" "##r#$$$%&&&&'^''(d())\))*.**+V+,N,~,-*--.P../$/00t01$12L223d34H45556P6778,8z89699::z:;;,;x;<<<<=@=r=>>n>?6??@8@j@AA>A~ABBBCLCCD^DDE2EEF&F`FGG0GXGHHXHHIIZIIIJ:JlJJK K:KL:LHLVLdLrLLM"MMNNTNhNNO2OvOOPNPzPQQ6QvQQQRRBRRRSS0SZSSST Tx];N@)JHAreD)Spuz)%p :~;53;3 vb]f'n{/F#'a p>^=\UA~n߅[6n%ܡ-#=nF1nf9n[V5nv=;N3n`#L!qwPDGa``s'{>/x !x(x$G1x, x"')x*x&g9x.x!^%x)^x%^W5x-^ x#ބ7-x+ކx'ޅw=x/އ >#(>$>O3,> "/+*&o;.!~')~%~_7-~#?/+'?F 608H4ݠA `' SSӂ7kLʷxsaZ* YzP+ˬʌղ6i)Yf,q\BJj"Z0.ḐBEwάХ(TM4E_IޙQ!lޒs;qKw*ֈn{yƛTs{I.F0ݱI}5shEdb*=^\f= EJվЃfLLRl/n9+: ,%OG̈0sSV.m̄'ScΨW\ -oJQٞPj`ҹ>j(%&eT$Wu"Rs*A_T[Zdʡ垫uMpDU0cK;wm+gbvH'˙)ưSf3w'~!W+Zz=^ԟ{]{2*OWLU lMdM9Ǣd#42TuX T֑ %#N=hI#lȕ\^t(d9Rg$5aejLU];\IvDvof͎9wYOLf*ں1+XYdžO*gCUArM`#fّr/q@]hܧZr l_4Tr"CRZE.JvA,#`Hө+TrG CdiJ"sBIG1ӄP$H) KClsEQ%`q V3nJSqdq YQ1ͧq{oL9[d.MHQdN#*AVԇUf9^`:~Z:N\5[c$n.,ЊktYp"B5^)CHCovZOnKa(_4-#;<'Ŷ*$[yuOo&넲dY`,t/CF]n*cMXWAr5aLC]2PAh!i *]vMz&+F m9`EtSUGU+!BsWkU*Eϟ>t](uËZKv4Т$#jMkYgD⩦ޥ8)r2+y꣹;{iCPK!W&Empublic/fonts/element-icons.ttfnu[ 0GSUB8BOS/2=I|Vcmap8 ҩ8*glyf+Bhead"6hhea$hmtxddloca}`d4maxp1 nameÌ$aposts͈ \i?-_< 罆罆  ,DFLTliga2PfEd@\,, "  +AEa"-DGc""*DR 24h0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      0  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ ` a b c defghijklmnopqrst u""v##w$$x%%y&&z''{((|))}**~++--..//00112233445566778899::;;<<==>>??@@AADDEEGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXXYYZZ[[\\]]^^__``aaccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~     n.FnZh<,lh 4 B  v @  ZP dX V2Fd6ZB2bHxd^L\lP Z !!h!" "##r#$$$%&&&&'^''(d())\))*.**+V+,N,~,-*--.P../$/00t01$12L223d34H45556P6778,8z89699::z:;;,;x;<<<<=@=r=>>n>?6??@8@j@AA>A~ABBBCLCCD^DDE2EEF&F`FGG0GXGHHXHHIIZIIIJ:JlJJK K:KL:LHLVLdLrLLM"MMNNTNhNNO2OvOOPNPzPQQ6QvQQQRRBRRRSS0SZSSST T7!+2656R6@)66)@)66)@@@)66)6))66)@)6H+>F&>>53./676&'&>#.'&.?&676'&'75* ;?'@ZDDZ~^^OUW73#5>65>6+"&'#5&/#"!76&+'4&";'54&"3#23!26?`e@p% <4$`$4< %.I: !".I: /(4v4K  K@%c  @ d  '"++"D' %5 &$ %%5 &$ */ / p f  f#.:@5>732+"!!.'.>7!7.7>?%!264&#!"6)@'6/&($x$(&/6'4(P\mR@7G< )6 2N9!!E9N2GSSr A@5 OpX =A37!#33.3732+!.'#"&46;>75>732+"!!@Da@tG@9#p#9@G_6)0 VhaDr8_')6#'7;?CG>7!.'.'5467!.'!!!26=4&#!"3#;+3#3#vv &&!1#r#1!&&bYY0@@@@@@@@@@|ss 2!@!3 u 3!@!2 Vhh@@@@@@|@#',032+#!"&'#"&?>;'463!27!!'!!7 1' < '1  ;G 7b K%%   " ^^@@@@@ @ ")07CL%>7'>7!%.'.'67%!677&'&'.'>7>4&" 74&/.'67676.'>?>#1A,.||., F[ #,   AX 6=Ɩ=6 u}  F1g T.]].T g3HM3(aBN(m@zz@m(NPhC6\63#&/."&'&7>766767>.?.#>7>76'.&X $97HX5"'#6P.J&9#tE/   H  15Z4/9@)%6--5'(3$P 77M: B^x(  @Gn k>G (=  9w  80fS)A61n H>@4@L6767#"&463!2+&'&67&'&'#.'&6>7.'%>7.'*$Mu9$6XzgWWLR"(;SEYg Z[yntDZZDDZZDZZDDZZiI=S;S39sXY ZTV!#:TAWxWZYqwZZZDDZZDDZ>ZDDZZDDZ'7''7''7'73'.'&67,=57.8a jo"w[U||K`(7.86>,woj a`K||U@3<ENW`i>".7.7.>>75#"&46;2+>4&">4&">4&">4&"7>4&"7>4&" 1"gg5L8&?'XlX'?&8L5gg"1@@ )66R66)66R66)66R66)66R66)66R66)66R66,*]nK#LC)4hEEh4)CL#Kn]*,C6R66R66R66R66R66R66R66R66R66R66R66R6@@ #'+!4&#!"3!265!!.'>3#3#@ )66)@)66I@@@@ `6)@)66))6``D@'E7671>25!>7&'.#&#'"&.75463!232#!"&46; 5>'':$)E }{v| 1(%9#)G{@{``q g|r_ccD@&32#!"&46;.75463!2>'5! ``{@{7}}cc,rrA@ &!4'!!>32#!"&46;.'47!%N)YY``}@@@vJ`Vhh~`~A@$32#!"&46;.'47!>74'! ``}@@cmm%N)~`~/mmvJ`I)9D'32#!"&46;5&=4673'&>!>3>.&/# ;^.Ro7`` HB `Rb1 P1T &\[ J00@>moUޫ S  {:E l .`X),?  k)32'#.'463!2>7.!2#!"&463>75Y47[5Ym6II*.lRRl4]f[0Vim``I66IRllR@ #-%!!>3#!.'463!232675.#$$A@(77(@I6@6I@  `$$;6))66II6x^#0=JV!5!;2>=%!#".=462"&=46"&'5>%"&'5>!2#!"&46"5D&f&D5"mf4]H'{ 1VD3&D66D&3m&I]44DffffB #.>7>3"'3!.'!.' %>.kOXXw7D " AP88PXO98Od: XvU (@OjVksX^;8GG88GGxs139GJ: /@'/7>J=4>>76#5.%3&67."6."!36.">7!!2#!"&461= uLLu =1ę@ UrU M%,%%,%~  9*IXXI*9 0aaֹ'F7CC7F'((((}}G1:BHNT"&/&/.>?'.467>27>!767!2?'&"76&?"&&.4."# m.4.#"  n=UZ3iv3vۏ  #'f(m #".4.m  "#=ZGvv a L$,0%>7!.'463!2!.'#76#%6!5@MBM@[dd[$$Z $    @-NN-?;ll;A$$ $ ќ@@>-4?"!26=4!./.=4675>7.'!3!26?  #5 00 5#ۣ=@)  )@ @; 1@. !! .@1 ڞk k@@'-9462>=462"&5.'5462%3&'&"&53#F99F#M@@; 1:V = V:1vZR`@':F462>=462"&5.'5462.'>7"&5>7.'#F99F#FYlRRlYF 3KK33KK: 1:V = V:1ammajTTjjTTjD%0;F%7.'./.>7&676/676.6.?>.^ B &GS; )7 &KOPFR OFO6,V9aw;QD%'"8 %'"9 #PK& 7)  :SG& NGN REQQ#CQ6!.'5&&673>73.'3."36.#"6!3!265%!>7!_@2iY' ",6))6, [@ZDDZ@__~6R6E $5 $anL``YD!> Ac6,E+)66)+E+DZZD__)66)90 &O `zz !)5>7!&!2#!"&467!.'5."H66H~@.٣$6$m36IH724響 $$  ,5#"&463!2+!&>!.'!2#!"&46``^v1 1v٣$@AAV]]VH )32#.=462>.'3>7.'&!]Vkj{٣@n]^W 2M%-0t٣e&#+ )5462#.46;.>73.'>76 ]NcbVp@٣zjk2 R#46nl٣t/.%@  -.'>>7.'7"&4622"&546٣((/@٣٣٬( @LXd3#'''7.'#367'76'&'#37?7'76?35#'./7.'>>7.q+$ VV.++FF++# VV.++FFC -::-"n!&DC !n"-::-"n!&DC !____DZZDDZZ@K>!C6KK KK=!C6KK ' ;@;"-8++0";@; ;@;".7++3";M____>ZDDZZDDZ@!)1?>/.76&/&?75#.'5#.O   F# !lDQi.Q[hnm@lR@l! #F   h[.iQ4@mRl@  )5>>7."&46%.'>264&%.'>264&0??00??0(d0??00??0(<0??00??0(?00??00??((A?00??00??((A?00??00??(('3%6/.>%"&46;2#"&463!2#"&463!2# % R  @@K!  #/&'6>7..'>>7.  ))⪪))____DZZDDZZ44* FF FF5____>ZDDZZDDZ@ &3@MZg2"&=462"&=46%+"&46;2+"&46;262"/&462"/&4"&4?62"&4?62}       E  @/  E     2   ;%'.'367#"&4673"&532#.'5>2>#.'&Wjj{@m^^E] ] Wkjz@m^^eN$-0te%$,J % 2N$-0te%$,3G/&4?6!.?62/!'&462"&4?!76"/&462* # ` ` # *#) % `  `  *#)  ` `  )* # `  `  )`)# `  ` #)&* $ ` `  ))  `  `  )) # ` `  *&@)462&'&471624>1"/"&5   )    )     :`` #,7!>75%!.'!.'>7!'"&462$$@$@$ )66))66)((`$$`@ $$6))66))6(G8?F#"&46;>7#"&546;2.'6;2+.67>7%.'>`23 G7\``>b rr  Cd#19Ɩ6II6I66IdsWZmE:@ppMu"ǼI66I6II@+4J32#'#"&=!"&=#!!"&7>;5>75.''"&=.?62 @ff3Y9 lRRl@I66III#  #` à````@@ VrrV;NN;JJ # # @+4J32#'#"&=!"&=#!!"&7>;5>75.'6"/&>5462 @ff3Y9 lRRl@I66I$  #I` à````@@ VrrV;NN;$ $ # JA#'4A#"&463!5463!2!2+#!"&55#!!"&54623"&5462@@@```@@@@@ !264&#!"` 462!2#!"&5!"&463``` %'& 6." $   #  7'&"?264/76.  #  $  $  $ D#62"&47 &4'62"&47 &4  K  8  K  8    @@     @@ D!62 "'&4762 "'&47  8  K  8   U  U U   264' 64&"a K  8    @@ t4 &"2764&"@ U  U+8  K  2764'&"U 8  K   U  Ut2 27 27564'&"  @@  (   P   e A+46;2+32+&'&6>7.' h }fhiRllRRllh gh sffdlRRllRRl@ 3>7.'.'>75.'!"&=>7!"&RllRRllRmmm6)@)6ZDDZlRRllRRlBmmmm`)66)``DZZD`L,?"3!2654&#%!!.'>2"&=46.!!5>76@@)66))66IvEEV``q]\%@6))66))6'A@ gG@&^VW@,5>"3!2654&#%!!.'>2"&=4675.'!5>@@)66))66IlRRlm@6))66))6@RllR@@mmL!"&5"&4762"'<     Y    A!"&463!2"&562"&47b   @   !!264&#!"265&"264'@    @   a!"3!2764'&"S           !2#!"&46"'&4762          @%4&"'&"2764&"       Z~  2  A%"3!2654&"264'&"`   `7    !%!2#!"&5462"&4762@    )    L #/?>7&3&&76$%3!21#!"514!2#!"&46321+.5146qfbv ?9oq!e`2  @ w>P]?gdMjX@  4 67.77'.'&7J3;Gtߩ> p&w+ d M͍/@O>tl d ⨨+w@!2)&'&67>%!676&'&.>.Vj j>~knkgi3#O`ok8=~#aw]++jjva(-ڄAll$!Oa sOPdK9TUJ7>Bpo)!%!&'&67>%!676&'&Vj j>~knkgi3#O`o@jjva(-ڄAll$!Oa sOPd*/.!2>5.'!.'&67>76! h_ 'IQ jKp*K; W8]qtd maVW =DQ?' tKJ^ ;K*InQ`s~cdTk[ @ $1=JWdq~%>7.'.'>72"&=462"&=4662/&462"/&4%46;2+"&%46;2+"&&4?62"&4?62"RllRRllRmmmm  . #- (  -  . g@@@@ -  .  .  - lRRllRRlBmmmm@@@@} -# .  .  -   .  - (  -  . @ !-&76 #6&'&"3!21#!"5143!21#!"514S([vxxv[(C)HghigH)  @   @  VTTVzNLLNz@ @ &3?K7!2#!"&463!21#!"514'>7#.'2"&=46.?6262/&4 @  @ `Ɩ@zz  D # D   D # D  Ɩzz@``  D # D D # D  &2>7!2#!"&467>7#.'2"&=46.?6262/&4 @ÌAqq D # D   D # D `pp ``  D # D D # D D*7DQ^/.!>76&!".5>7>762"&=4632"&=4632"&=4632"&=46# g_ )APcKLj Vlp1WD$nX}VU \s"]";CO?( _BKc`LLsm$DX0ZRjYOb````````D(=%.'>7>765>7./..?623.? a}nX}VU _s{`FXVF# g_ )APZ $ ee@aZRjYOa`A gGHh";CO?( _BGaH    D*.26:>/.!>76&!".5>7>763#73#3#73#73## g_ )APcKLj Vlp1WD$nX}VU \sb@@@@`@@@@`@@]";CO?( _BKc`LLsm$DX0ZRjYOb@@@ @@@@@ ",312#1"5475''#53%7>=4&/ @@i&00&@c  c@ @ `86&&68 )   @@ $%19A%>7.'.'>72"&=46;21+"5145##5!353!5mmmm @@@mmmmC  @@ '09BKT]fo%>7.'.'>75##5!353!5"&462"&462'"&462"&462%.762.76''&4>7'&>2mmmm(@@@@#  $  $  # mmmmC=L $  # $# # @ $%.>!>7.'.'>72"&'746#264&"#5#"&463!2#٣٣@$6$$6$_@`C٣٣|$$6$$E %6CO%>7.'.'>7%"&7%26'32+"&=462%&>&!6.6٣80 $80 $Z Sn1/;+ .C Ro1/;, @C٣٣C SS S1nS / ,;/1nS / ,;@ *26.'>5>7%>4&".'>7!5!!)! zzƖ$$6$$6II66II$ffoLzzY勋9@Ɩ$6$$6$AI66II66I@@a@ "#/!3!21#!"514.'>5>73!21#!"514  @  zzƖ  zzY勋9@Ɩ a@ ">!3!21#!"514.'>5>732+"&=#"&46;5462  @  zzƖ```` zzY勋9@Ɩ```a@ "+7!3!21#!"514.'>5>7%>4&".'>7  @  zzƖ)66R66)DZZDDZZ zzY勋9@Ɩ6R66R6AZDDZZDDZa@ *.'>5>7%>4&".'>7 zzƖ)66R66)DZZDDZZzzY勋9@Ɩ6R66R6AZDDZZDDZ@ $>>7.'.'>7'2"&546>7.'5.'>RllRRllRmmmmrWhhWr٣lRRllRRlBmmmm=A1??1AQ5DZZD5Q@ #!>7.'.'>7&7>76٣٣J J ٣٣DJ K @;?O!>7.'%!!.'>32+"&=#"&46;5462!5%!2#!"&=46$$$$6II66II````@$@$$$@I6@6II66I``` @@@ @&,59EQ>7%!2.'4637#27674&#'3"'&'&63#!2#!"&467!2#!"&46@lRRl`mm] "_A:s^ !`@:m@@RllR@mm r! @: @r! @: @3<FP!5.'#"&/&>;5463!232+32#!"&463!>7326?6&+5#"3Ot! 2 - YY . 2 !tO`lRRlB .YY. fM%#``#&Mf @RllR   @@ #(4!>7.'.'>7#63277!#67!2&"&6mmmmH #@%)'u')%6::mmmmC=  ``{@@ ").3?!>7.'.'>733#535#5#63277!#67!2&"&6mmmm@@@@ #@%)'u')%6::mmmmC@@@`  ``{@ !>7.'.'>7&76٣٣;@8z(@٣٣DnNFXn@@`%3>75#"&46;5#"&46;5#"&46;5.'!32+32+32+32#!"&46;5#.'>7!$``````$$``````$@`6II66II6$ `` $$ `` $@I66II6@6IA '77&76  ' 76'& 7&'.6&'6&'.&Ãf]w2wppwwpq#+>@N_LI ^IG#)" (<=MCfppw2wppw8N@>+#- IL)#GI^M=<(!@#Y%7>7%6.&76$762///.?'&>7'&>7'&462 Eu?r_E@s_E DtH8V0h^V2f  - # .-- $ --- # - $ - # .-- $ ---   GvDE_r??F^q>rGuD 0]e4V^2H  - # --- $ --. # - $ - # --- $ --.  @ %+17>EKQW.'>7'>7.'67&%'6777'&'7'6767&%&'7%6&''6&'7٣٢(!/m"2!* ## .m,' !"', !"2!)y)!2.. ##J ! 'Y ! ,@;٣٣p.#9':7*8%1?? 8  ? \7*8%/0%8*?2? 88 ? A&.;G%>7..'>&67&''67.'76&'%>. '&76  3;8;X?-K20\-0UHf8]uU?)[&W;~8;@DC##Bu]8Mf0;%6/76&/&"7.?'.>?>2/+rr,'!& c "(" c &!'Ɣx%%8 %ݜ''  ''% i@'7%!.'>7!>7!>7.'%!!.'>I6@6II6$$$$$$$@6II6@6II@6II66I@$@$$$@$$$@I6@6II66I .=3+"&51#4623213"&=#"&467#.46;5462@@@ @@&>76&'5.'&6%312#1"54`nc}}cn!ߘ  F;yyyy;F= @ @ $1>K!>7.'.'>72"&=462"&=46%46;2+"&%46;2+"&٣٣n@٣٣D[@!%!2#!"&5462"&5!"&463!2@@`@@ -<E!>7.'.'>7>7"&5.'"&.>?>>.٣٣mmz!@D$ 3$=#   ٣٣DmmfC?9G-  @ $%1!>7.'.'>72"&5463!21#!"514٣٣  ٣٣D @ (!>7.'.'>762"/&462٣٣+    ٣٣DR   @ #!2#!"&46>7.'.'>7`@٣٣`٣٣D@ #/!2#!"&46462"&>7.'.'>7`@ ٣٣@٣٣D@ #/49>C!>7.'.'>7'>7.'.'>77&'6'7/7٣٣RllRRllRmmm----٣٣DlRRllRRlBmmmm----@'-#5>!.'!>3!21#!"5143"&$$mm @ $6$@$@@$A@mm@ $$@-3??!&'732#!#"&46;>75>2.3"&%".762@.`7`r$6$2W#.6X$6$    @@@@6/%S-@u$$ 1%.<$:Q$$@    @@ E>7.'.'>5.'54623>7546232+"&4636II66II6RllRRll2z_@_z@I66II66IAlRRllRRl@z  __  z@`@$GUa.5>75.'>=7"'7;>7546232+"&46;5"&'.=462".762-lRRl@I66IO?5@3Ze.e.7@@_z@@.TS%&    0.@#RllR,@l6II6.I $8 9@y4X4e."_  z@@C)c6  +K    (.676.'?(,   1+O7  ()56B"3!2654&#%!!.'>"&463!21#!"5143!21#!"514@)66)@)66I$$6$$[   @6))66))6$6$$6$  !)!>7%!!.'>"&'326?$$$I66I$#KTKU282$$@$6II6$?"" +,8?!>7.'!&'>7!3!21#!"51453!21#!"514r$$$#I6@6II6 @ @ E[$$$v }6II6`6I  '09%!>7.'!7&'>7!"&4623"&462!"&462$$$#I6@6II6,,j,$$$v }6II6`6I-,,,,,, $0<H?3>7.'&?.5>7"'".4>323".4>32!".4>32R`٣$#\:(,mbj(- *ːː4f-5y@0=  ,  ,  , %!>7.'!7&'>7!$$$#I6@6II6$$$v }6II6`6I $%12>?3>7.'&?.5>7"'3!21#!"51473!21#!"514R`٣$#\:(,mb @  (- *ːː4f-5y@00  $?3>7.'&?.5>7&'RfѬ$!Z8(*x\(, (ȔǕ8h,5|B.  (45AJVWc!>7.'%!!.'>>4&".'>773!21#!"514>4&".'>7%3!21#!"514$$@$$@6II66II$$6$$6II66II  $$6$$6II66IIJ  $$$@$@I66II6@6I$6$$6$AI66II66I `$6$$6$AI66II66I  (4!>7.'%!!.'>2>4.#.'>7Jllllll11.>>.MggMMggllllIO3:3>..>JgMMggMMg (4!>7.'%!!.'>2>4.#.'>7Jllllll22.>>.MggMMggllllIO3:3>..>JgMMggMMg!C#!>754&'5!.'5>753>75.'!.'5>7!6II6@6I"9FlRRllR@6II66I":ElR@RllR@I66II6#:F`@RllRRl@I66II6#:Fb>RllRRl#''7>'&'7>'&6?6?'.[8 .2;[-ZOEA KZOEA KZ.[8 .2;[----[;2. 8[.ZK AEOZK AEOZ-[;2. 8[<--@(1:CLU^gpy!>7.'%!!.'>72#54632#546!2#546"&=33"&=3!"&=346;#"&546;#"&46;#"&%+5325+532+532@$$$$6II66II@@@@@@$$$$@I66II66I@@@@@@C>'.3!4&/.=.4>2!"&/.>76$= %$!=E=! )1$5 ,e)$ $ A"> 1!$T#<$$<# > B+$+-%  @@ $%1>7.'.'>7'312#1"543!21#!"514mmmm @ mmmmC=   %&26%>7.'.'>7;21+"514;12#1"=4'__`_xwxj(%(/`__`9wxwx(%(@#(:?Q#53+"&=335'53#5##546;2!5%!2#!"/&4?6!5!7!"3!2?64/&@@@@@@]GG#R cc G#Q dd  `PP@ p  p P@ p  p @ &3LX%'"&'3267>54&'.#">2%7.46767>54&'.#"26.'>7["PVP"[4EG~`,/0+[.4EG~3["PXO!>,/0+[F #!@"+L#!?H?c[[[,/0X4EG~3[!OZO!,/0+[.4EG~3["PXO! ?$+L#!?$+L@'3!!>73!.'>7>7.'.'>7$$$@I66II66II66II6RllRRll@$$$6II66II66II66IAlRRllRRl/ %/!2!.'&63!>77'!!7!>?LdBBdLV摑N C,^,C =?KK? J~ '#BO@@c*22*c$07;DM7#"&5463!232+".7#".7>2367!!3'#7'#>4&">4&"!@ 6\#GRG##GRG#>J>-M 6B"--D--"--D--` *I--I**I--Ij""'h`A ``-D--D--D--D-  $0<M]a%>7.'.'>7'3!21#!"514>7.'.'>7"&46;2&'"&46;2&/'6II66II6RllRRllR @ 6II66II6RllRRll `Z @%9*@*@I66II66IAlRRllRRl I66II66IAlRRllRRl  h 0 0`[".!'&"7#!"&547%62>4&".'>7@,z  %X,$$6$$6II66IIBB2 q e$6$$6$AI66II66I`[ &27!'&"!5#!"&547%62>4&".'>7@,@  %X,$$6$$6II66II> q e$6$$6$AI66II66I@)2#5!!3!"&5463!2!%!2#!"&546.462@@@@n$$6$$`@ @@$6$$6$ /;G>7&'7.'467>7&'7.'46.'>7'>7.'ŗ"쯯#ŗ"쯯#}쯯쯗ŗ;;"@^^@";>#c{{c#>;"@^^@";>#c{{c#>{cc{{cc{>^@@^^@@^!%IU^!#532#!"&'&'.=!!#!"&'&'.546767>3!2.'>7'>4&"  R @@ R   DZZDDZZD)66R66@   @    _ZDDZZDDZ>6R66R6#GKOS4&'&'.#!"3!26767>5#!"&'&'.546767>3!2!!!!!!   8 @ **** **8**  <    x**  **x** *&@@@@@#/!'%!2#!"&54?6!!%3'#'3+"&5=l  22@(@ T @88@` @&/;DP!!5!!)!!!!#!"&53!21#!"514!>4&".'>77>4&".'>7 `  `@@ @ `$$6$$6II66II$$6$$6II66II@@@` $6$$6$AI66II66I?$6$$6$AI66II66I@%!%!2#!"&5465.'#5>7`@I66I@lRRl@@@6II6RllR@(/3+5!#"&=#!%>732#!"&546;!.'!! lRRl@I66I@``@@RllR6II @@)-.462.462"&46;2!2#!"&'!!(,(\ "_` @ {R (((( @  f$-!2#!!2#!#"&46!.462.462`7p ````(,(@ @@@ ((((@)-06.462.462"&46;2!2#!"&'!!%'762!(,(\ "_` @ {Ro\\+<8 (((( @  f@nn@#!5%!2#!"&=463#3#'3#3#`@@@@@@@@@@@@@@@ "&*.#3#"&=463!35732#!735''3#'3#3#8@PxHh..@@@@@@@@@xH.."7!62#!"&54`  ` @ % {@  !-1!3!21#!"514 !%!2#!"&7>312#1"=4#3#@ @ c`cM qPqr @@ @@   @$-159!%!2#!"&546!!3#!5.'7!5>'3#3#3#@r@I66IRlln@@@`@6II6lRRl` ``` @#'+/?!%!2#!"&546!!!!!!%3#3#!!3'!2#!"&546`@n@@@@@@@@@@@@@ "+!!467#!>73>7.'.462SRl-__mA]]AA]$$6$$lR Dthzzm}aa}}6R66R6@$%12>##!%!2#!"&546;21+"514;21+"514;21+"514`@``@. @@ @$%12>?K!%!2#!"&5463#;21+"514;21+"514;21+"514;21+"514`@@@ @@@ @!%!2#!"&5467!!7!!@N@`@@@@@(-87!!7!2#!>!5%!!.'>75%!/&'$@`@ I&P$0??``@#ll#`$`:6I!(`@$?00?aMM@ VV +!!7!!3!53!#!5#!!#!"&5476 @`\R  @@@Xg  4!%!2#!"&5463121#1"514'>67/& @@@@2O}  2O| @@@@@@' e (d @ $8>7.'.'>3121#1"514'7>6?/&٣٣@@@@.D  *A  ٣٣D@@@@ .b0b@ +/?!5.'!3!!3>7#!!.'>7!5%!!.'5>$$$@@@$6II66II$$$$@$$$$@I6@6II66IA@@@$@$$@$@ #'7!5.'!!>7!!.'>7!5%!!.'5>$$$$@6II66II$$$$@$$$$@I6@6II66IA@@@$@$$@$ 7!%!2#!"&54653!33#3#3##!#5#535#535#5 @@@@@@`@@@`@@@"3462#!"&5463!2#!!76. &?6762@@`5D $  iLME # qOi L@@762%!2/&"&'46B@#  #E@  !.;H%#'##7#"&5#"&463!2+#!!2"&=4672"&=4672"&=46oJooJo@@   @@@@@f >73'.'>!.'56! ՙ@)_bC!3# rr+||+t@@!65555&#77#&Y@@ 3#3#53!5377''7@@@@Z----Y-=---@`@@@@-----=---@ !-3#!.'!7!!5>>7.'.'>7@@$$?6II6RllRRllRmmm@$$eI6@@6IlRRllRRlBmmmm@@#GHTh";26767>54&'&'.#'32+"&'&'.546767>312#1"=47"&=4&+"&46;22  2222  22>@/ /@>>@/ /@h @``)6 2222  2222 @ /@>>@/ /@>>@/ `@6)!0%#"&5#"&463!2++#'##!!%"&4?76'g@@oJooJH  }m %    ^#b .;!3!53>74767!733##!"&=#.'3!&767#7!$$=n% FI66I}}  `'$$G9QOFF@`@@6II6ED.)980@'3?5.'62.'>7.'54>2."267%2675."٣D<"I66II66I"7!..'@$6$@I66I:А$$6IIv4!*6B&'&6767&>>'.7>'>&'&>.kJ==c189p!["o981c=>Z >;;k#4  4#k;;> Z>V)  8V*4.BJ.5*KA%!7'#!"&5463!2%3#@``@Ȱ@0(@@+4!>7.'%!!.'>!2#!"&46.462$$$$6II66II$$6$$$$$$@I66II66I$6$$6$+5#.'#3#>75#5!.'!>@lRRl@٣I66I@RllR@@@٣6II/%32#!"&46;5!.'>7!!>7.' @6II66II6$$$$I66II66I@$$$$D*%"/$'&76$>7.'!2#!"&46}  }wrw|D{WƖ}  }m{D|wrwƖƖ|D:%"/$'&76$>7.'546232+"&=#"&463}  }wrw|D{WƖv```}  }m{D|wrwƖƖ|````D%"/$'&76$>7.'}  }wrw|D{WƖƑ}  }m{D|wrwƖƖ@!-9!!'!#37>3!232#!"&546>7.'.'>7 . 1 .DZZDDZZD___@@]]ZDDZZDDZB____@!-!!!5!#!"&5#"&5463!2#32+"&46@ @ @@@  7!2#!"&46#' @@-==.@B>-=- 7!2#!"&46%7 73@.-@@-=-E,62"'&472764'&"7.67Z<;88OOKK.h88<;=%%(f' $ &-23$ 88<;KKOO.i;<88=(f'&& $ &- $41@+/CGKO%#"&'&'.546767>;5!32+!!5!34.#!"!5!3#73#   EE   @@ v @@@@@ \     @E  @@@@"!!!'!#!"&546533##5#5@ @N@@@@@@@"!!!'!#!"&546!!3#!!@ @@@@@@@@'!!!!#!"&5467'7&`@L.-@@@@--@&*.!%!2#!"&546%+53!#5463!2!!!!@n`@@@@@@@@@@@@`@@@"'!!!!#!"&546'77''&`@C[.Z[-ZZ-[Z.@@@@Z.[[.Z[-ZZ-@'!!!!#!"&546!!&`@@@@@@@@!%!2#!"&546!!3#!!`@@@@@@@!!'%!!2#!"&5467'7f --@ --#!!'%!!2#!"&546'77''f [.ZZ.[[.ZZ.@@Z.[[.ZZ.[[.!!'%!!2#!"&546!!f @@`@#!!'%!!2#!"&546533##5#5f @@@`@@ $!!5!'#7>3!"&5463!!232n`|2: N9 `p@@ `@ !!'%!!2#!"&546f @U 7'77' 1!5!!f9h1Gpp@.^pbpgN@@@%1'&46276/"&47>7.'.'>7[  ZZ# [[ #ZZ  ٣٣Z  [[ #ZZ# [[  ٣٣D@7CO[gs!#"&=!"&=#!!546232#!"&546;546232+"&4632+"&46732+"&4632+"&46732+"&4632+"&46 @@@@@@@@@@@@   @   `@@ !@@ @@@  >.7%.>%&>&[X!"S`7JO3&JM.&ZY5M^#i(.W],L2i"%.'>%.'>0??00??0??00??0??00???00??00??00??00??00??00??>/.76&/&l   A ! l! A  #/<E7'#!"&5463!2!5>7.72>5."4>2.7264&"ZDDZZDDZ>-2.6R6"7&>23#I66IF:p $ r:@6II6@!v  u!  !! @ &2!>7.'#'.#!"2>4.#.'>7$$$$t. .551AA1mmm$$$$]]M7<7A11Ammmm@ .'>'&"276.c    +@c   + @ &.'>'&"2?>/764&"h  hh  hh* hh  @{h  hh  hh *hh  ` &>7>7.'>4&".'>7p;KTŗTK;p$$6$$WttWWtt VAUZ[UAV$6%%6$sWWttWWs)3"&5463!2#%'&"!&"2>5."`@E    -2.6R6@E " %,,)66@ '.'>#";26=3264&+54&"  @k  @ 4.'>264&"46''&76&'7>>""3""%5 X#S5 W#2D@44 =  (9, =  '8@ .'>3!264&#!""t@E @ !.'>"2676&>4&""",@&&,,@ *.'>>4&"3>76&'&>,B` A??t AAI' 6@E,, !RAAl/:)"7.'!"&=>7!#____`ZDDZ@___A`DZZD`  #!!3#!5!53!5!3###53#5@@@@@@3!>735.>25!p6II63&'bb'&I66I&tyHHyt6@@ !3!3!3 @@ !!!!!!@I"53!54&'.7>76>75C=#ODhO~EgXu@@@ P2A&%B?ch$fqey@~ !>7.'>7uuvXXvvXXvo*؍*XvvXXvv@)3#'''7&'#5367'767.'>>mm>77VV77>mm>77VV7slRRllRRl@UU@_`__`_@UU@_`__`RllRRll`  3!3!'5!@x.=-? @.=-`` 3!!#.4673!0??0  d?00? ((!.462.462.46237!000`000000w@!!#3 ``` 3!7''."26$00((Gf*f*u(  !!35#35#%#>7#.'@@@@@@@lRRl@I66I @RllR6II#.'55>7!3.'>7 U=ӝ=U U=ӝ=U =U ݝ U==U ݝ U="%3!53!7"&'"&'"&'"&'47!@@6R66R66R66R6=@ )66))66))66))66) @%"&'5#.'!%!`6R6`6II6)66)I66I 73!#3#@```` %!5>7.'5!35!!5#356II6@@6II6@@@I66II66I` 7''773!3!%5!----- @ ----( @@`` !!!@% @@BM@@a/o/%>2!!"&'!5>23#"&'!5>2!!"&'#5 1>1 E 1>1  1>1 1>1 ; 1>1 ; 1>1 ##@##@ ##@##@ ##@##@ !!!!!!@ࠀ %533!5'!@@@@@@`  3!3!!5!!5!5!@`@@` @@@`` 5!3!5!!!5!@@@@ *.'>>7.'?'7.54>٣s  @٣٣F2 L @ $%1.'>>7.'312#1"54;12#1"54٣# @٣٣   @!55>732#!"&7>;!5.'#!#"&=!"&5@lRRl 99 I66I@f33f`VrrV @ ;NN;V```%53'3#5.'>7>7' fw\XX\wf f^ WjjW ^f@'&>54&"@ # )  : $  265264'.     )'4AN[2#!"&5463%!3!2>54."2654&!"2654&26=4&"26=4&-"##"Z,"",Z,"",    "##"=",,"",,"  -   - <        }-=6&/&6?>'&'.76$'&6&/&67,&[ EK^-<@a*  [T? $.T>* 7 0Aa]-<  T>&#1GA#0=5463!2!2#!"&463!35#"&5!#%2654&"32654&"`@```@`@@@<L!!.'>767>/.&'&6767%6'5'&$?>/.0??0`0??t7IPw  %U85'RB= 4 PU>( @?0`0??00?Oxs7J  4'RU:)1 % r7(> +#* 1< +C n *       V &] Created by iconfont elementRegularelementelementVersion 1.0elementGenerated by svg2ttf from Fontello project.http://fontello.com Created by iconfont elementRegularelementelementVersion 1.0elementGenerated by svg2ttf from Fontello project.http://fontello.com       !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~     ice-cream-roundice-cream-squarelollipop potato-stripsmilk-tea ice-drinkice-teacoffeeorangepearapplecherry watermelongrape refrigeratorgoblet-square-full goblet-square goblet-fullgoblet cold-drink coffee-cup water-cup hot-water ice-creamdessertsugar tablewareburger knife-fork fork-spoonchickenfooddish-1dish refresh-left refresh-rightwarning-outlinesetting phone-outline more-outlinefinishedviewloadingrefreshranksort mobile-phoneservicesellsold-outdeleteminuspluscheckclose d-arrow-right d-arrow-left arrow-left arrow-down arrow-rightarrow-upkeyuserunlocklocktop top-righttop-leftrightbackbottom bottom-right bottom-left moon-nightmooncloudy-and-sunny partly-cloudycloudysunnysunset sunrise-1sunrise heavy-rain lightning light-rain wind-powerwatchwatch-1timer alarm-clock map-locationdelete-location add-locationlocation-informationlocation-outlineplacediscover first-aid-kittrophy-1trophymedalmedal-1 stopwatchmicbaseballsoccerfootball basketballstar-off copy-document full-screen switch-buttonaimcropodometertime circle-checkremove-outlinecircle-plus-outlinebangzhubellclose-notification microphoneturn-off-microphonepositionpostcardmessagechat-line-squarechat-dot-squarechat-dot-round chat-squarechat-line-round chat-roundset-upturn-offopen connectionlinkcputhumbfemalemaleguidehelpnewsshiptruckbicycle price-tagdiscountwalletcoinmoney bank-cardboxpresentshopping-bag-2shopping-bag-1shopping-cart-2shopping-cart-1shopping-cart-fullsmoking no-smokinghouse table-lampschooloffice-building toilet-paper notebook-2 notebook-1files collection receivingpicture-outlinepicture-outline-round suitcase-1suitcasefilm edit-outlinecollection-tag data-analysis pie-chart data-boardreading magic-stick coordinatemouse data-linebrushheadsetumbrellascissors video-cameramobileattractmonitorzoom-outzoom-insearchcamera takeaway-boxupload2download paperclipprinter document-adddocumentdocument-checked document-copydocument-deletedocument-removeticketsfolder-checked folder-delete folder-remove folder-add folder-openedfolderedit circle-closedate caret-top caret-bottom caret-right caret-leftsharemorephonevideo-camera-solidstar-onmenu message-solidd-caret camera-solidsuccesserrorlocationpicture circle-plusinforemovewarningquestion user-solids-grids-checks-datas-fold s-opportunitys-customs-toolss-claim s-finance s-comments-flag s-marketings-goodss-helps-shops-open s-managements-ticket s-releases-home s-promotion s-operations-unfold s-platforms-order s-cooperation video-play video-pausegoodsupload sort-downsort-upc-scale-to-originaleleme delete-solidplatform-elemePK!^J``public/images/moosend_logo.pngnu[PNG  IHDR<ѶtEXtSoftwareAdobe ImageReadyqe<IDATx]mh}X-J ՊL'@tWh]8ńPS5֥G$i)ܴ1 uq1) M|c-8'b-q"+F{"#ҌR"$_CC'M(O2>~~E7F-%-(aM2qOp4RcMdhr`554d̴|MdO?oL;wqfըIrEHY>O=^}'ƲUΝcd._uІn^ yCN{O+"?y鸓(QI@x]0;e|2M GlsRitSkT"G۟x--)煦u쿳ؕ]s^ϏKӟ\oz?oe-|[O\cnШ4:VQEݦx]uB24 M9sz Pim`x5XwC4hh sPGH5J`v" ܽLT#AQ Y6jCq~ kPDW&?KAJXG!bM0[%u6.!GQgJw 2; 4sbVMi@mQɨ/Ǐ9k">fNfhh4ASt{T*ͯawaB&`1N-L]A{un Mbacm!Á{*!9&Pț`W 8VS>\aH<3EB2/'s=d0LcTEf0.[l0U꼚h;k8I_~.SfH稯,+?TDᗎO3pQx=Bgޓ1}LU&\5\QSX 9ᗶ,Qg$#zJeQ"s9lXqpSߥ2sz~y,rhOtr4xćpY˞DE\Lx32w&IXښlkdD9χQyK~"7oNND+0i/_J_ֹ) bXIC92q_J(K ɒ-͝T,|n*d 䧻Ѹa^'4e3qu6/]" 0Nȴ"^[>"=`s<2{ hM>Cc)1aS.d]"oLf!tho\ l‘.?h=[/۷U>L_NY P$(C5u.65 S=RX s*A\ȷ h]-xVk*d1 _ 3JY2_$`HᅨoWȋ>?oBЈǾ1zV 䔂03en"1\1t`塞x7˅s4җ~, r=Z '&D^t\ZՔK\/mFVE,qcZ`iɹzv̗߬ dJDYgKfԱ¼!'DJrXL2uJrO=ìbU0!iŞ *a+Cy!@a# g>%!ZD#qIwZn?0G -kRu ]2ݦ{.Ƞ#EQyc'G=29# h[{eH|ք×S]7j;{rS!~DFQPqd}ZD _8b-o:/;byla}?v7i m;.'ҠKU 0y\[(JU8B ̣O {~zf8n|=$9kᎽkvWw'>XqGoTj;tp> &CN@l D"3R3;?.:ŵ~~Fdͧ Ə55"~/ HBhk{q흹ˈ6?GZr0OCp:IGmm ? ` ^@+BDMTw4t#| .,d;cIh>И|ȺN5IQy} ,bxZq:O{QVn: M@L@;\ۛ4M>eCdĻjhf(~6@:h9\wcf)Ҧ F8%ť@8$8IP% e4?m1'!ҍt~OCkĊdMʹӯ8Hgjih}h4pc b dV>nIENDB`PK!eELL public/images/stripe-connect.pngnu[PNG  IHDRD; OiCCPICC ProfileH\SW$@dDaE)JH #ƄFJ[DVV@D-8Pb*;{{]2Y@@š"=d`(dhewy} 7W18șB "mgTH,SqKTJMb<n4>_ n3Գ ЏMRD r@B<"?pO|fXZȡ,?,<xUΰn7sEG [PmI{\š&dw!?4 9pi^LV% A+))%j.)>c9Kh6yUIbo"qb d*PY"7!Jc16re*~;l4"DKϒke|Rqb>XrHI#RLE( 䎵I|{x^Y^'"TzfX|l\x .Q'/р B (a@4_pr DMk(@иuB!Խ1|ozthdj$]c̓MOj_ޠ%1J$q3<ǣ56FٞAx@F$ܚ*)x k32cCzƙpy8x jڸUMC|QsŝRQ)N_uĚ9TUPsޣc6v;5v k.`GT<lxr?kTUR^A D3U#N͒K,E,T0r{DMdg"~1os{ BW]p7ЃO) f?a` Lu,3rf {~gp\m~3 ^~AHa b" Dh$IE2lD(9"Yl@"!r@n!n/=4@Q(Qh":FEh Dkh#z=^C;gh|`LsҰ,Lʰ kZ ։`p"Y\Ñx.|ވ¯^N0'JL~BS)~X2BHS j"5ZImޡѱՙ#YSO}w4C KK)ih;iih/t=F//O2tGtutu/>ףqUлףOwWҿg0mkoԠSCaаpIÇ a2Eӌ.#(ǨhQQdUG;Ӂc1333&dXðޘ 7 65fޔefkҴnb6l&f=Í /樹ylm,,-",d-NZX2--s,XbXZIXeXS^ksHkVv~G$b6wml,5vVvjOgۋٷٿqptHq֡ᩣ#ϱȱ)iSUg39y%ERruvntA;B:f 7ǭЭH#F>e7*mQm>{ow=pţ[F!I bјMcnz1{}[cSsmĎc/e%=ۯoߟnuO:>aM?`k@g +0#pK`gu?&Am0xG3'<=Dr0 ׏;{< - m3 K v/&<;>7+bvHBdT< W3nSQ Q]-Ư'>F byc9MiqB܄ GωoK`$LMKx,UڜFJKNۑ7)lI]^';N9)ySL՛ʟz Q˯e23{\:3ap[ Z%z*iv@nqB#J6H^Dly3w /%oo>9?#P+=5ri2WYs{Q D1Y\`?/((VO2~?j>8Xֈ4jm7u66wwſO#yp#ˏR8Vtxω[>9SN:}Oqڎ 8sC{ou/^lnos稜G/]>q%WyW_q=7:o o>wů^pp݊{j~smow/F(iNxDASCIIScreenshot pHYs%%IR$iTXtXML:com.adobe.xmp 404 Screenshot 68 EiDOT"("" ~pSIDATx] |յg$} !!@BpA*uK׾ںkEUZwmW[.ԟK,*,*$B=3}ysgoB3w;{s`$ 0(% % 0(`P@Q`Lˉu V|@ W&.9?0”!n82?!/DG·8'਒T:+ՅJ3By|c^~ Klc>hؐSW57W?R rzTԬf /=䩦(0!hGamuc_ ])ⶳs8E(_Ed)x4+I:DK\)RȕglЁ[ 0?7?tX\hʚ,\}bAHJ]7iQ8}n2MrxasM Q`QZERBI LG o*v2-JQ)ī,0cQyzl^<>.qq me?SQ&IdnRYVPhtyqy{y [a_˜S[nW?JT(+)dj14!!2GH՚+F*ߥ+'ґF٠%c>vm\5/R|W;aяJ,3rb|`<ˁ(5G>)_~ƒBU_)3eOF\SSOmy`yO7]{蓰B9qUE( SL3$?5OnPoRmӥkWyʙخ|AT$*ΚOaP/a ,jowjc7[E F(oSsQM?M჏^Wۍ@GeQ8N8^dRo(+d$5T,I$"55 I&$v?IEn'c/Z|c3 :9zͣ"8Val`aU 9IؖJJ@aV .AUqJr5{c$]bvv7haOZzy3Y0(ފi[jeI?L~5!MmT(""<3~,. PyCKQ ˍAmVS -CʹLq`ې_dS*< cXӀa!4iNFoo#xǩB 7qbqL% M!)ǠS}.ĊKt]fz)َBfߞ${kj,_AOai0|QߪK)x_n~UY%c2ek7eQ&*ن(,Sypb3> :$}hG5 koZ$yXD b&&ö'zեed @Dzz+2 #ut5(:*PqΟ_򕨷DF%%#є SZ F1bǭI?欼 !NKc75 ,d>N\v+|Q OL0d@JZǧ;Vt׷(UR(޷Rߏ9@?wB@jb%*+CB%VfPH♅B8wzwXԌs ٖU#}h/N 6N).р/8m 7Eo#~* ;}`ϥ>a= MbZ (O&|mYD@~[uarE*O.AwOV/efEIQD%KJ $ |;U :ъÎT7G!7=t`Y[}ü$XfUNI%Sgp7mpm!>3#=ь9Ύ 78lnʊ k_GL)i. 87̰GiI/6^Xi`PIaRԔ(یT)Gz8aC'5vH=oxiCɠ)Y_[NR2PNQ48R s-8V Λ/v՟6CQ 3꼳S!XX[q8wq%rғǘ xFyEH%0|O5<z}jhRej@ goW536yEydh^hi'[ߍ?n܇~gRINMUa5Ӳ3OoGV^:Fi]ͼRYH1/x EN7{ $lIeCNYդ7YýfIm[;^m|ơ:߄VDFQ^\`BLąx,wÚ"]kUT~z\t.X:;|c'ުA=w=韾x3D<֯B?V/WCR(+^O|WUL_-[X.W~_c6deBKa^[]UW҂v'!#;C-]A(D oN}O@8'ڐ݅$&fˀGj,]==]Plm+\ZX?ruA Bn% >_LB) U;P(؟l=?PViB {(zG/YcgB!]V9E)<,Ȯ^؊&o74|ӿ[5 ]$]5zM~]>7߲B FH|?H?VqCpDJpՉd)7wSQ'7],^uWW&z%D NhWAx(U Q{__]_OVboM.CGd"?O-=:fQ Kk7q|1T$#C JF'2f.Hu;: KΧ2'~:8 #@t܇沟(n6IJ6C //prU$'%}9]m lDC]PMXrjL, 5̣8޷7qr[*̢!!o޾p\8,^ӎ}\3n *HSACX揌OV1I򒯴)5Cw \8dj3o%ZMpꏕ{#Q#Xpba;שUW<܌a w,AQ:^MMYlz+IHJ@Tk~(ŏi:ౡ V]t`J}6~EJ$)N+BIOny#tFo9J 'I/ 2#k 49UJ9$X!ƙY8C u{r-{B%3g\X:U(VO'#,Fiap/O*`?D~Os*T){hsQ%//JE5/H=q:K_9?̤շu6ЩN>(D>%kcXsx{*_((fD!{R;(",,TOJxCۦ}0 }ÚTN=z:huim[ڶf"-$P~zG(AY꿠,GVlծ lV:(){w֎!R +TW.,G9PנxߊҕvV_>KkW*oG߅cgbW{ g#{NL ԋ%LFϺ`fy$tw[?vؾv- #(?շ74޾4ʲ;TV_VTS1.Ze8:7U4)~ k«V3)/^*IyP'[pE`VMVq9#_ųpʣ!i_}yvqL%@SL~߬W_N%d[-QѤU\Z\83T{\/[ ~'ϊĝAz2ƲC/m;U*Qp",w +q92ۂ_;UÂd\Bxic @O ?J\wa}G2'|eYPb]Qw0o4-XNJ99>^|{ٟFy`a7~19J:y)69%q))KF|+p?_+Ϛ3oZ꠱WǤߥ RqrMx?ٔo2WR-iAV M=4mV$ ip_C|45( QsGȫl<7|#cmE3\,B:Kщ.{1r%#1tQW{mlGc5nBxq$Bxճ")'Mnn~舶73s͚KG;_9h.x^z_3B7ر; _?Y&nF'b|\%å 0Vxo[Vcg m{NzĻo!>ٸ?R/ۃ(T3 7p6|?rRlpc3YփQo~XFo8Z<:ҨquIxP׎@%Q\7s1Jh' M@Aƪ5mcU߷F*Y( kys[P;에qNPݱ> ;ܸ0<)7"Vn VHtjk6 'Q,ȸ. uR:h> kz,y-#Rn}v<)6R.߷?P"/y#zv!rq\<\ؼf*Sx#daؕ^O`NP,mj r!6'Ve N!rSx3_W;AY K*@j89e\T-܉J_8$7 TC\[ףK F8tMePL Mk88Z+"hJljfG'.iI<ډiE3f؏-m%$Sc7qbC߉\ a/aʢe$ػ. 5\Z||BoR|ǿǁ_wgԽ \T*Q4_8-/''h{ yLJGpо_>;K,faChגQþ4,wytY<"]ox{+=l?`CMq NIP>PĴBՂ+O)WVt{AxeY4Ih_ه?ݪ 0\xi!IDAT]UE' IrTW}F ꊀHFD%*q3 sﯾs½3~rZ{鮪K X|[ڶ(\rqqqy}]ݢ:•OY>Hxz) 4S3󡁁&Tg||]]VFҖz݇*Yms?{pR52uщdpv.֡xƖ=e|dӟPz<:u:=wĭ y|~)JP{ SUW߀<'Jq%Booo阿%~A)/cCѫqX~5^^z]{k:39W B~:Ug2~=]X̊_p&Lɷ_]oCU'Lo FK V.-Ri3h)z ?/1=ҋ0]2C}0{}=~`?]߉ا~,t##4KM]=ۓOENI [޹'mVR/V)W"P\ok/iGR,ޖÁaӾqOv6pW0@%/O+]\g>;?7WW1bB|>3KJ$ ][zr[8B\m+"Gfʻ;Ql,/<)?<8 mq)m:m!u8ʋQ3/-dt<3PXVǖlG>+ \o\D"E2QtrH]LCy5'.q+>48}cyc~mb& 7D~ĝ@Оϓ)@ N|,Y 6=$HP{ij+Q\Oðޱ/3PEY|,۞[т^S@[CYnm /[1:KsSQ]Z[>5 O0 oz~*Y=]v3z8{@YsRoWsڀ ֖CXLN@3P^\YM? #cؘR 7z {Srs[j0o%Oߚ]\IhBשO O (nVΧgH@NSbF"F3Gţ] ,]3Xoij/M?魴ہMm;q|;8O7kkh9D{Cf9 K~I%^U>:ߺBs?NSPʎ|Vd'w~q^x# FZ^6Q:oM@nq~}p_tRvQ@0q9~KI<0մ(Zк}"`cdՕ(-.gAEfKL1ktb]fx wĤƌfWr^T|m*dBQsƴDd) 'מ{en E1-mKH/i_BlƲhS*'ժqMs&eaݑ2SsOJ>^P؄G;`t7y(+PB^'?߃}\1BJᅗ1yrֵ|Z?@82 #maU?&c*WŰj_!V|4{@D<C#:zV3/5Yhn\{AA40,=-Dzc}/>6M,Z{efn\{uq>!!uj__\%J'k/Xy lkc1t`idz+L;\ßCzq]k|8xLJ~1\iT?ƷCy]!-p#9KuROcE.j ,XJŠ-/o'(77"$, >t@oQqZP|S36~ Fz=r^_YO]IJ8M^Tf4̡j0{l,$LwdaCBj.&2Ȉ.[Sc/([Pdf;o1XW$!M8H{@e} {&F?e ||LC6\i] N+ >!4P~Lǧ-pi#P?3?=׈&T2^~ϊ4L1ma6YGdNKS_#!W<%xFӄNM幵yvΉA~Ld?^C~M sLTһm,Utd#?JQmyy0,#79Lmw>=y2R ٠rI\pH=_[*A&a]5q=,f\ Ƞ7ОSS:q9ŹStJPG('hy=&++d 줢 %+O a:.GOӯJ gzb=0\h$>dmø_گ*-@MQ&V<2T_7'c&.!ឫox$ƔW_/46r8'(s֥`K* C=wðP u/ܧ n5f}!;#Iᆇp1|GE{hP(hgx(] cɤıT1JXJBQRY0 c@Z,1EG)}~j wo^}O_K@iMX>!"8wBp[_ow Wocfvi熵PXJ]Yt^'/9D(ʤ+ ]:zJYH5*nUJ`wwAZ1ֽc e+jOQ,Q}fzPKGoqy(NC[c2}X3bp,y:UӋ__ۯ5H[ra7!/ZDq}&~%EzU\mnmgrMe1 m,@:;)䈇 YaE!mv.O~S KOhK ]Hoç9.f=|;3TbHø5n>x'pquWM.\/G086=Z|%׹ 9ntf2ss)VmXDŽ>/:6oa\*Q2NQ>^Bߐhs2y;zz⯪_GP. 1(Ԣ£AmQIc+_Rv)N䗣Zōc1up[thAp8rSnEhd4PYL#N~]d#@ 񻿏; WfU4ދ ("۔))9L!D0{`y5_ƲB#X$xcǯKLeA4XSFSY2~2~l`?ڏY[? ] m[?ޜ^ ~cL {ؼ0$~7=pMIe?Ѩm m~N-s6¯ʌ1@mM?P5DPZY?ډ] ks#z>ßGR^ߛI7!Mcz|UM,. Ṣ׋{4}5cD=E(}?4ejv Sfgbއ3˛Y <"7<_ˏ$k$&+.i~y*mOle2kM26$K^/{?l>76qc 熸']K"jP; <ʚ"X#Ð[miGEǘ<;VFz+Z2МU19wP>fz' f&R_Vrөۄyq`%(=;X)o Ἦ  PpE9~TPk-}f'X|H@}e8n_?lE: ߓչ-"(ta%t?6gc6c̎ 5flv7LuT di7 Mv1CLN=7۽2Up4H ޤߧo.1y64Xk2C2=U^7ە݌Z x£FCodW%]r~dܞ`b3ظsߑ%wMŵ#YM΅M< ş۵jZ\?J 5ʎy[ge/ÕpR0$B+bOGbH_wk;3(qP[.C^D {7oVUE*qGFk (Y509CٓZ>>ANUN"OK"Pߙ %NfeH`W@hKy52us75JT;ϔsd ?ý;]KՔYW Mڄy"2(Y53G$ lQ zeyg|ӍO%/4v"d-:]yJd#'gL߃lAѷ(eRoF2QlD<{]Zg%gte'Re/u@ Ӏ}QQEElj-l3կY^#{5quEY~lO a|/7fH9WTyu."ֹm,y[y>I*י6ٛGy&0'BvͺEKPz=f1#6fgy.P*m /Ms&Ê|q1jC\[vgrC]a΢ OQ %.9%?K~Ͽ>=D@1[ٽD{s*bk^P.@i.Nɽ(.DUy9<<&&,m"/g󘒙[i%1iq `{x)0Q dD7'lUgIY^]4޵H&L6`ۓm!m?upQUNPi P|{ wwVpר,$1aĤܸC[3qz7WO4)6 C/DP[9KV=,Zro je-#_Sxv$?'sn3@9R~J\ݠEx." ?ēQ'/' !J8K0u4#(;PIM ՞UR ޯ-9_ܛjXݐ_Rv$?i' 3/{(=vJCbPŮVe/s_E?\ſ;G}/LQĞw&KC~e8C-it. "ʛ/Fe&q1ůߖ'+J"9λGt &3S /#eaPdQP2S,=Ɓet;PC,%ͿCPO B9nȒXځ J ;^W?XG#$d k\X6oU;Q_C; Rԇ,2E׊unm4.5>q uT5 t@~bm ђ8eԟr߻.{@GH5g*- 4Qs Y,`مF;P]V?!.2g8zEkbܢ5BbFqtܒGA}c~gÈ/̩C4\`/ٲ !.tXh->Zbe,;hKw‹7\a%0bJ*탖{T}4Uڪuƅe.PYZ #Ŵ;#*]СCxc u1,GUWȃgKX|; o,-Aq %)|߱%;OO~ƪ Ò%K, %0r@;'w"E~8z(VXG'99OZs1k.ǟY>5q%hsw77 G϶> DL2&"4OtՒ%K, ( 8z&X(k*yyy())AUؔ-L{:Z$`IE"B@@5GarIENDB`PK!?[public/images/google_map.pngnu[PNG  IHDR^PLTEW>{W:1C8?5>48/>4@6<4?5A8>3?5ϜU90=4C;=3>4B97/:3||_uN>5.ƿCP^?E;>4SE)m6<2;AVGѵE:jJ~僵L&H>\FDC?W?5>{=u&"W@6;]XA8)m%kE|B~B}>ZGj9}L4{LB/eC8$U:1O;p$!ǢLSD9A7d!7-9C8?5k# B\?5)YC80/.#s^=>35-w&"_ X3)!51g"iqN,.Y=o@B73sl93ٻ͹4h[SOE:1+&^ ϢSEu|u3,1+.(~($¤ּήaJyjb\{KroGG8ȉʨВ=)3;2jх%]c][?>>R<8/Ҵ3!h.Pc~=AdڜΤ#4y*Xa4)C6f""5`x,XC^CYsУ!cpOJz\˙u"rZDF&WRm1h,|M(/@צH)Ig޽TDaNl`%ۜ<=p6_Ⱦ۲AGU"BsAxQ"M8Y=Ь|U!0 dPUB,aݮ{iȐpetiEBgKC F{E),^DEd>D5v^oqԇ Q"RN[ "pLjUʢD)H]BNÒn]0R\"v9= ɱYY!NSuN(%]w~m{\(Tд,I[qۯȾ㲌>~%Ma<t2c9TAFs㊜DG+JmSQ"MװAMӪ9tOq4>D "hD0"5>6gm+$JVmneΡ_0P#yoD-–|:ܬƐzYP$5OFV&m+a#O4+a͘!GSÂ幊fukHjF9a42rc-?1=_R&Ba8q,ٌF %p8-D I/=N8"Ҝ >{@SMBScx Uw({,m~[ H=DU5^$!T:x Ipg_r,7ߢP#(7i1?1D.eM!fנrGy \h^+ҝ"ݐ_Y6DwVM-iCH)(Y\?Ha'B&9ce[EM<l<|!B@ rqHx̚6eCa)G_hs<,s7&tм;oIyU(RL[%"0: /=pWM E31w}wI0cyQdw. ՉKJ__@?,!=^=~ssBw$9K"( -sgye`عq'"PFD"%L{FN$"= 3(dS}WˤPH%< B D*|$G x8& G"= 7?-j 5!R!gKpA"pCfq,?C[W4_YptjHE=9 *ۄZdJz읳c΢KPeȩs":ud+"1g ȱMLu,Bx|m]07ggEFԪO:B2CЂcBKP w,t(7WAETsIޓ1?M ZΟwݯ Qҫ\{t?CLy~J{hԄмPL:{iZIqޫߎ sّ1 Q6wI2#ZqiAH+zu xo@AKHt")n@p3qze\"JzEKx8hwp9}Q Hx]S_yWB"7^.+@~|5AhXe! R ! ġPBC^)k Q|&@u!Hyl *EC^n =2!@TKh|^]Cq&sՒ|H " }:̇Lr W$^BI&ydA=^IzU$’ HYz%-p7riyHT*D۞)Qr$4dQ<$$j3$(U$$F$Գ<ɬѭ*_R흩d- .j ֫lILH9oWYU9g5yQ^I$lb.I¨mg-a$OK-jYW=u(O (Nܲoߞ#7ݻ{wmgĔ~ IENDB`PK!g#ݐݐpublic/js/styler_app.jsnu[;;;/*! For license information please see styler_app.js.LICENSE.txt */ (()=>{var __webpack_modules__={44988:(e,t,n)=>{"use strict";var i=n(48970),r=n.n(i),o=n(81337),s=n.n(o),a=n(41955),l=n.n(a),c=n(75652),u=n.n(c),d=n(24650),f=n.n(d),p=n(71937),h=n.n(p),v=n(22428),m=n.n(v),_=n(34354),g=n.n(_),b=n(45614),y=n.n(b),x=n(67186),w=n.n(x),C=n(62618),S=n.n(C),k=n(82626),$=n.n(k),O=n(85517),T=n.n(O),E=n(44242),j=n.n(E),I=n(7626),P=n.n(I),M=n(87563),A=n.n(M),N=n(26426),L=n.n(N),D=n(57099),R=n.n(D),z=n(43229),F=n.n(z),V=n(42173),B=n.n(V),H=n(30272),U=n.n(H),q=n(16473),W=n.n(q),G=n(73591),X=n.n(G),Z=n(70538),K=n(1802),J=n(39903),Y=n(66073),Q=n.n(Y),ee=n(82492),te=n.n(ee);function ne(e,t,n,i,r,o,s,a){var l,c="function"==typeof e?e.options:e;if(t&&(c.render=t,c.staticRenderFns=n,c._compiled=!0),i&&(c.functional=!0),o&&(c._scopeId="data-v-"+o),s?(l=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),r&&r.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(s)},c._ssrRegister=l):r&&(l=a?function(){r.call(this,(c.functional?this.parent:this).$root.$options.shadowRoot)}:r),l)if(c.functional){c._injectStyles=l;var u=c.render;c.render=function(e,t){return l.call(t),u(e,t)}}else{var d=c.beforeCreate;c.beforeCreate=d?[].concat(d,l):[l]}return{exports:e,options:c}}const ie=ne({name:"ff_color_picker",props:["item"],methods:{handleChange:function(e){this.item.value=e}}},(function(){var e=this,t=e._self._c;return t("div",{staticClass:"ff-control-content"},[t("div",{staticClass:"ff-control-field"},[t("label",{staticClass:"ff-control-title"},[e._v("\n "+e._s(e.$t(e.item.label))+"\n ")]),e._v(" "),t("div",{staticClass:"ff-control-input-wrapper"},[t("el-color-picker",{attrs:{size:"mini","show-alpha":""},on:{"active-change":e.handleChange},model:{value:e.item.value,callback:function(t){e.$set(e.item,"value",t)},expression:"item.value"}})],1)])])}),[],!1,null,null,null).exports;const re=ne({name:"photo_widget",props:["value","design_mode","enable_clear","for_advanced_option"],data:function(){return{app_ready:!1,design_mode_name:this.design_mode||"small",enable_clear_name:this.enable_clear,image_size:"",for_editor_advance_option:this.for_advanced_option||!1}},methods:{initUploader:function(e){var t=this,n=wp.media.editor.send.attachment;return wp.media.editor.send.attachment=function(e,i){t.image_url=i.url,t.image_size=i.filesizeHumanReadable,wp.media.editor.send.attachment=n},wp.media.editor.open(),!1}},computed:{image_url:{get:function(){return this.value||""},set:function(e){this.$emit("input",e)}},image_name:function(){var e,t,n=this.image_url,i=n.substring(n.lastIndexOf("/")+1,null==n?void 0:n.length);(null===(e=i)||void 0===e?void 0:e.length)>15&&(i=i.slice(0,15)+"..."+i.substring(i.lastIndexOf(".")-2,null===(t=i)||void 0===t?void 0:t.length));return i}},mounted:function(){window.wpActiveEditor||(window.wpActiveEditor=null),this.app_ready=!0}},(function(){var e,t=this,n=t._self._c;return t.app_ready?n("div",{staticClass:"ff_file_upload_wrap",class:"ff_photo_"+t.design_mode_name},[t.for_editor_advance_option?n("div",{staticClass:"ff_photo_card",class:"ff_photo_"+t.design_mode_name},[t.app_ready?n("div",{staticClass:"wpf_photo_holder"},[t.image_url?n("img",{staticStyle:{"max-width":"100%"},attrs:{src:t.image_url}}):t._e(),t._v(" "),n("div",{staticClass:"photo_widget_btn",on:{click:t.initUploader}},[n("span",{staticClass:"dashicons dashicons-cloud-upload"})]),t._v(" "),"yes"==t.enable_clear_name&&t.image_url?n("div",{staticClass:"photo_widget_btn_clear",on:{click:function(e){t.image_url=""}}},[n("span",{staticClass:"dashicons dashicons-trash"})]):t._e()]):t._e()]):[n("div",{staticClass:"el-button el-button--upload el-button--default is-plain",on:{click:t.initUploader}},[n("i",{staticClass:"el-icon el-icon-upload"}),t._v(" "),n("span",[t._v(t._s("Upload Media"))])]),t._v(" "),(null===(e=t.image_url)||void 0===e?void 0:e.length)>0?n("div",{staticClass:"mt-2"},[n("div",{staticClass:"ff_file_upload_result"},[n("div",{staticClass:"ff_file_upload_preview"},[n("img",{attrs:{src:t.image_url}})]),t._v(" "),n("div",{staticClass:"ff_file_upload_data"},[n("el-button",{staticClass:"el-button--icon",attrs:{type:"danger",icon:"el-icon-delete",size:"mini"},on:{click:function(e){t.image_url=""}}}),t._v(" "),t.image_name?n("div",{staticClass:"ff_file_upload_description"},[t._v("\n "+t._s(t.image_name)+"\n ")]):t._e(),t._v(" "),t.image_size?n("div",{staticClass:"ff_file_upload_size"},[t._v("\n "+t._s(t.image_size)+"\n ")]):t._e()],1)])]):t._e()]],2):t._e()}),[],!1,null,null,null).exports;const oe=ne({name:"SliderWithUnit",props:["label","item","config","units"],emits:["update:itemValue","update:itemType"],data:function(){return{options:this.units&&this.units.length>0?this.units:["px","em","rem","custom"],min:0,max:100,step:1}},methods:{setConfig:function(e){var t,n,i,r,o,s;if(e||(e=this.item.type),"px"===e)n=(null===(r=this.config)||void 0===r?void 0:r.px_max)||100,t=(null===(o=this.config)||void 0===o?void 0:o.px_min)||0,i=(null===(s=this.config)||void 0===s?void 0:s.px_step)||1;else if("%"===e){var a,l,c;t=(null===(a=this.config)||void 0===a?void 0:a.percent_min)||0,n=(null===(l=this.config)||void 0===l?void 0:l.percent_max)||100,i=(null===(c=this.config)||void 0===c?void 0:c.percent_step)||1}else if("em"===e||"rem"===e){var u,d,f;t=(null===(u=this.config)||void 0===u?void 0:u.em_rem_min)||0,n=(null===(d=this.config)||void 0===d?void 0:d.em_rem_max)||10,i=(null===(f=this.config)||void 0===f?void 0:f.em_rem_step)||.1}else if("deg"===e){var p,h,v;t=(null===(p=this.config)||void 0===p?void 0:p.deg_min)||0,n=(null===(h=this.config)||void 0===h?void 0:h.deg_max)||360,i=(null===(v=this.config)||void 0===v?void 0:v.deg_step)||1}else if("grad"===e){var m,_,g;t=(null===(m=this.config)||void 0===m?void 0:m.grad_min)||0,n=(null===(_=this.config)||void 0===_?void 0:_.grad_max)||400,i=(null===(g=this.config)||void 0===g?void 0:g.grad_step)||1}else if("rad"===e){var b,y,x;t=(null===(b=this.config)||void 0===b?void 0:b.rad_min)||-6.23,n=(null===(y=this.config)||void 0===y?void 0:y.rad_max)||6.23,i=(null===(x=this.config)||void 0===x?void 0:x.rad_step)||.001}else if("turn"===e){var w,C,S;t=(null===(w=this.config)||void 0===w?void 0:w.turn_min)||-1,n=(null===(C=this.config)||void 0===C?void 0:C.turn_max)||1,i=(null===(S=this.config)||void 0===S?void 0:S.turn_step)||.01}else{var k,$,O;t=(null===(k=this.config)||void 0===k?void 0:k.other_min)||0,n=(null===($=this.config)||void 0===$?void 0:$.other_max)||100,i=(null===(O=this.config)||void 0===O?void 0:O.other_step)||1}this.min=Number(t||0),this.max=Number(n||100),this.step=Number(i||1)}},computed:{itemValue:{get:function(){return this.item.value?isNaN(this.item.value)?void 0:+this.item.value:void 0},set:function(e){void 0===e||0===e&&""===this.item.value||0===e&&"0"===this.item.value||this.$emit("update:itemValue",e)}},itemType:{get:function(){return this.item.type||"px"},set:function(e){var t=this;e&&e!==this.itemType&&(this.$emit("update:itemType",e),this.isCustomType?setTimeout((function(){t.$refs.customInputValue&&t.$refs.customInputValue.focus()}),100):this.setConfig(e),this.$emit("update:itemValue",""))}},customValue:{get:function(){return"custom"===this.item.type&&this.item.value||""},set:function(e){e!==this.customValue&&(this.itemValue=e)}},isCustomType:function(){return"custom"===this.item.type}},created:function(){this.setConfig()}},(function(){var e=this,t=e._self._c;return t("div",{staticClass:"ff-type-control ff-type-control-slider"},[t("div",{},[t("label",{staticClass:"ff-control-title"},[e._v("\n\t\t\t"+e._s(e.$t(e.label))+"\n\t\t")]),e._v(" "),t("div",{staticClass:"ff-type-value ff-control-input-wrapper"},[t("el-select",{attrs:{size:"mini",placeholder:e.$t("Unit")},model:{value:e.itemType,callback:function(t){e.itemType=t},expression:"itemType"}},e._l(e.options,(function(e){return t("el-option",{key:e,attrs:{label:e,value:e}})})),1)],1)]),e._v(" "),t("div",{staticClass:"ff-type-slider"},[e.isCustomType?t("el-input",{ref:"customInputValue",staticClass:"ff-type-custom",attrs:{type:"text",size:"mini"},model:{value:e.customValue,callback:function(t){e.customValue=t},expression:"customValue"}}):t("el-slider",{attrs:{"show-input":"","input-size":"mini",min:e.min,max:e.max,step:e.step},model:{value:e.itemValue,callback:function(t){e.itemValue=t},expression:"itemValue"}})],1)])}),[],!1,null,null,null).exports;const se=ne({name:"ff_background_image",props:["item","valueItem"],components:{SliderWithUnit:oe,PhotoWidget:re},data:function(){return{image:"",positionOptions:[{label:"Default",value:""},{label:"Center Center",value:"center center"},{label:"Center Left",value:"center left"},{label:"Center Right",value:"center right"},{label:"Top Center",value:"top center"},{label:"Top Left",value:"top left"},{label:"Top Right",value:"top right"},{label:"Bottom Center",value:"bottom center"},{label:"Bottom Left",value:"bottom left"},{label:"Bottom Right",value:"bottom right"},{label:"Custom",value:"custom"}],sizeOptions:[{label:"Default",value:""},{label:"Auto",value:"auto"},{label:"Cover",value:"cover"},{label:"Contain",value:"contain"},{label:"Custom",value:"custom"}],attachmentOptions:[{label:"Default",value:""},{label:"Scroll",value:"scroll"},{label:"Fixed",value:"fixed"}],repeatOptions:[{label:"Default",value:""},{label:"Repeat",value:"repeat"},{label:"No-repeat",value:"no-repeat"},{label:"Repeat-x",value:"repeat-x"},{label:"Repeat-y",value:"repeat-y"}]}},watch:{"valueItem.image.url":function(e){""===e&&this.resetImage()}},methods:{handleChange:function(e){this.valueItem.color=e},resetImage:function(){this.valueItem.image.attachment="",this.valueItem.image.repeat="",this.valueItem.image.position.value="",this.valueItem.image.position.valueX.value="",this.valueItem.image.position.valueX.type="px",this.valueItem.image.position.valueY.value="",this.valueItem.image.position.valueY.type="px",this.valueItem.image.size.value="",this.valueItem.image.size.valueX.value="",this.valueItem.image.size.valueX.type="px",this.valueItem.image.size.valueY.value="",this.valueItem.image.size.valueY.type="px"}},computed:{isGradient:function(){return"gradient"===this.valueItem.type},hasPrimaryColor:function(){return!!this.valueItem.gradient.primary.color},hasSecondaryColor:function(){return!!this.valueItem.gradient.secondary.color}}},(function(){var e=this,t=e._self._c;return t("div",{staticClass:"ff-control-content ff-control-background"},[t("div",{staticClass:"ff-control-background-head"},[t("div",{staticClass:"ff-control-field"},[t("label",{staticClass:"ff-control-title ff-control-title-auto"},[e._v("\n\t\t\t\t\t"+e._s(e.$t(e.item.label))+"\n\t\t\t\t")]),e._v(" "),t("div",{staticClass:"ff-control-input-wrapper ff-control-input-wrapper-auto"},[t("el-switch",{attrs:{"active-value":"gradient","inactive-value":"classic","active-color":"#1A7EFB","inactive-color":"#1A7EFB","active-text":e.$t("Gradient"),"inactive-text":e.$t("Classic")},model:{value:e.valueItem.type,callback:function(t){e.$set(e.valueItem,"type",t)},expression:"valueItem.type"}})],1)])]),e._v(" "),t("div",{staticClass:"ff-control-background-body"},[e.isGradient?[t("div",{staticClass:"ff-control-field"},[t("div",{staticClass:"ff-type-control"},[t("label",{staticClass:"ff-control-title"},[e._v("\n "+e._s(e.$t("Primary Color"))+"\n\t\t\t\t\t\t")]),e._v(" "),t("div",{staticClass:"ff-control-input-wrapper"},[t("el-color-picker",{attrs:{size:"mini","show-alpha":""},on:{"active-change":function(t){return e.valueItem.gradient.primary.color=t}},model:{value:e.valueItem.gradient.primary.color,callback:function(t){e.$set(e.valueItem.gradient.primary,"color",t)},expression:"valueItem.gradient.primary.color"}})],1)])]),e._v(" "),e.hasPrimaryColor?t("div",{staticClass:"ff-control-field"},[t("slider-with-unit",{attrs:{label:e.$t("Location"),item:e.valueItem.gradient.primary.location,config:{px_max:1e3,percent_max:100},units:["%","px","custom"]},on:{"update:itemValue":function(t){return e.valueItem.gradient.primary.location.value=t},"update:itemType":function(t){return e.valueItem.gradient.primary.location.type=t}}})],1):e._e(),e._v(" "),t("div",{staticClass:"ff-control-field"},[t("div",{staticClass:"ff-type-control"},[t("label",{staticClass:"ff-control-title"},[e._v("\n "+e._s(e.$t("Secondary Color"))+"\n\t\t\t\t\t\t")]),e._v(" "),t("div",{staticClass:"ff-control-input-wrapper"},[t("el-color-picker",{attrs:{size:"mini","show-alpha":""},on:{"active-change":function(t){return e.valueItem.gradient.secondary.color=t}},model:{value:e.valueItem.gradient.secondary.color,callback:function(t){e.$set(e.valueItem.gradient.secondary,"color",t)},expression:"valueItem.gradient.secondary.color"}})],1)])]),e._v(" "),e.hasSecondaryColor?t("div",{staticClass:"ff-control-field"},[t("slider-with-unit",{attrs:{label:e.$t("Location"),item:e.valueItem.gradient.secondary.location,config:{px_max:1e3,percent_max:100},units:["%","px","custom"]},on:{"update:itemValue":function(t){return e.valueItem.gradient.secondary.location.value=t},"update:itemType":function(t){return e.valueItem.gradient.secondary.location.type=t}}})],1):e._e(),e._v(" "),e.hasPrimaryColor&&e.hasSecondaryColor?t("div",{staticClass:"ff-control-field"},[t("div",{staticClass:"ff-type-control"},[t("label",{staticClass:"ff-control-title"},[e._v("\n "+e._s(e.$t("Type"))+"\n\t\t\t\t\t\t")]),e._v(" "),t("div",{staticClass:"ff-control-input-wrapper"},[t("el-select",{attrs:{size:"mini",placeholder:e.$t("Select")},model:{value:e.valueItem.gradient.type,callback:function(t){e.$set(e.valueItem.gradient,"type",t)},expression:"valueItem.gradient.type"}},e._l([{label:"Radial",value:"radial"},{label:"Linear",value:"linear"}],(function(n,i){return t("el-option",{key:n.value+i,attrs:{label:e.$t(n.label),value:n.value}})})),1)],1)])]):e._e(),e._v(" "),e.hasPrimaryColor&&e.hasSecondaryColor?t("div",{staticClass:"ff-control-field"},["linear"===e.valueItem.gradient.type?t("slider-with-unit",{attrs:{label:e.$t("Angle"),units:["deg","grad","rad","turn","custom"],item:e.valueItem.gradient.angle},on:{"update:itemValue":function(t){return e.valueItem.gradient.angle.value=t},"update:itemType":function(t){return e.valueItem.gradient.angle.type=t}}}):t("div",{staticClass:"ff-type-control"},[t("label",{staticClass:"ff-control-title"},[e._v("\n "+e._s(e.$t("Position"))+"\n\t\t\t\t\t\t")]),e._v(" "),t("div",{staticClass:"ff-control-input-wrapper"},[t("el-select",{attrs:{size:"mini",placeholder:e.$t("Select")},model:{value:e.valueItem.gradient.position,callback:function(t){e.$set(e.valueItem.gradient,"position",t)},expression:"valueItem.gradient.position"}},e._l(e.positionOptions.filter((function(e){return""!==e.value&&"custom"!==e.value})),(function(n,i){return t("el-option",{key:n.value+i,attrs:{label:e.$t(n.label),value:n.value}})})),1)],1)])],1):e._e()]:[t("div",{staticClass:"ff-control-field"},[t("photo-widget",{attrs:{enable_clear:"yes",for_advanced_option:!1},model:{value:e.valueItem.image.url,callback:function(t){e.$set(e.valueItem.image,"url",t)},expression:"valueItem.image.url"}})],1),e._v(" "),e.valueItem.image.url?[t("div",{staticClass:"ff-control-field"},[t("label",{staticClass:"ff-control-title"},[e._v("\n "+e._s(e.$t("Position"))+"\n\t\t\t\t\t\t")]),e._v(" "),t("div",{staticClass:"ff-control-input-wrapper"},[t("el-select",{attrs:{size:"mini",placeholder:e.$t("Select")},model:{value:e.valueItem.image.position.value,callback:function(t){e.$set(e.valueItem.image.position,"value",t)},expression:"valueItem.image.position.value"}},e._l(e.positionOptions,(function(n,i){return t("el-option",{key:n.value+i,attrs:{label:e.$t(n.label),value:n.value}})})),1)],1)]),e._v(" "),"custom"===e.valueItem.image.position.value?t("div",{staticClass:"ff-control-field"},[t("slider-with-unit",{attrs:{label:e.$t("X Position"),item:e.valueItem.image.position.valueX,config:{px_max:800,px_min:-800,em_rem_max:100,em_rem_min:-100}},on:{"update:itemValue":function(t){return e.valueItem.image.position.valueX.value=t},"update:itemType":function(t){return e.valueItem.image.position.valueX.type=t}}}),e._v(" "),t("slider-with-unit",{attrs:{label:e.$t("Y Position"),item:e.valueItem.image.position.valueY,config:{px_max:800,px_min:-800,em_rem_max:100,em_rem_min:-100}},on:{"update:itemValue":function(t){return e.valueItem.image.position.valueY.value=t},"update:itemType":function(t){return e.valueItem.image.position.valueY.type=t}}})],1):e._e(),e._v(" "),t("div",{staticClass:"ff-control-field"},[t("label",{staticClass:"ff-control-title"},[e._v("\n "+e._s(e.$t("Attachment"))+"\n\t\t\t\t\t\t")]),e._v(" "),t("div",{staticClass:"ff-control-input-wrapper"},[t("el-select",{attrs:{size:"mini",placeholder:e.$t("Select")},model:{value:e.valueItem.image.attachment,callback:function(t){e.$set(e.valueItem.image,"attachment",t)},expression:"valueItem.image.attachment"}},e._l(e.attachmentOptions,(function(n,i){return t("el-option",{key:n.value+i,attrs:{label:e.$t(n.label),value:n.value}})})),1)],1)]),e._v(" "),t("div",{staticClass:"ff-control-field"},[t("label",{staticClass:"ff-control-title"},[e._v("\n "+e._s(e.$t("Repeat"))+"\n\t\t\t\t\t\t")]),e._v(" "),t("div",{staticClass:"ff-control-input-wrapper"},[t("el-select",{attrs:{size:"mini",placeholder:e.$t("Select")},model:{value:e.valueItem.image.repeat,callback:function(t){e.$set(e.valueItem.image,"repeat",t)},expression:"valueItem.image.repeat"}},e._l(e.repeatOptions,(function(n,i){return t("el-option",{key:n.value+i,attrs:{label:e.$t(n.label),value:n.value}})})),1)],1)]),e._v(" "),t("div",{staticClass:"ff-control-field"},[t("label",{staticClass:"ff-control-title"},[e._v("\n "+e._s(e.$t("Size"))+"\n\t\t\t\t\t\t")]),e._v(" "),t("div",{staticClass:"ff-control-input-wrapper"},[t("el-select",{attrs:{size:"mini",placeholder:e.$t("Select")},model:{value:e.valueItem.image.size.value,callback:function(t){e.$set(e.valueItem.image.size,"value",t)},expression:"valueItem.image.size.value"}},e._l(e.sizeOptions,(function(n,i){return t("el-option",{key:n.value+i,attrs:{label:e.$t(n.label),value:n.value}})})),1)],1)]),e._v(" "),"custom"===e.valueItem.image.size.value?t("div",{staticClass:"ff-control-field"},[t("slider-with-unit",{attrs:{label:e.$t("X Size"),item:e.valueItem.image.size.valueX,config:{px_max:1e3,em_rem_max:100}},on:{"update:itemValue":function(t){return e.valueItem.image.size.valueX.value=t},"update:itemType":function(t){return e.valueItem.image.size.valueX.type=t}}}),e._v(" "),t("slider-with-unit",{attrs:{label:e.$t("Y Size"),item:e.valueItem.image.size.valueY,config:{px_max:1e3,em_rem_max:100}},on:{"update:itemValue":function(t){return e.valueItem.image.size.valueY.value=t},"update:itemType":function(t){return e.valueItem.image.size.valueY.type=t}}})],1):e._e()]:e._e()]],2)])}),[],!1,null,null,null).exports;const ae=ne({name:"UnitValue",components:{SliderWithUnit:oe},props:["item","valueItem"]},(function(){var e=this;return(0,e._self._c)("slider-with-unit",{attrs:{label:e.$t(e.item.label),config:e.item.config,units:e.item.units,item:e.valueItem},on:{"update:itemValue":function(t){return e.valueItem.value=t},"update:itemType":function(t){return e.valueItem.type=t}}})}),[],!1,null,null,null).exports;const le=ne({name:"ff_width",components:{SliderWithUnit:oe},props:["item"]},(function(){var e=this;return(0,e._self._c)("slider-with-unit",{attrs:{label:e.$t(e.item.label),config:{px_max:1e3,em_rem_max:62},units:["%","px","em","ram","custom"],item:e.item},on:{"update:itemValue":function(t){return e.item.value=t},"update:itemType":function(t){return e.item.type=t}}})}),[],!1,null,null,null).exports;const ce=ne({name:"ff_around_item",props:["item","valueItem"],data:function(){return{options:this.item.options||["px","em","rem","custom"],min:0,max:1200,step:1}},watch:{"valueItem.top":function(e){this.isCustomType||(e>this.max?e=this.max:ethis.max?e=this.max:ethis.max?e=this.max:ethis.max?e=this.max:e-1:e.valueItem.top},on:{change:function(t){var n=e.valueItem.top,i=t.target,r=!!i.checked;if(Array.isArray(n)){var o=e._i(n,null);i.checked?o<0&&e.$set(e.valueItem,"top",n.concat([null])):o>-1&&e.$set(e.valueItem,"top",n.slice(0,o).concat(n.slice(o+1)))}else e.$set(e.valueItem,"top",r)}}}):"radio"==(e.isCustomType?"text":"number")?t("input",{directives:[{name:"model",rawName:"v-model",value:e.valueItem.top,expression:"valueItem.top"}],attrs:{min:e.min,step:e.step,max:e.max,placeholder:"",type:"radio"},domProps:{checked:e._q(e.valueItem.top,null)},on:{change:function(t){return e.$set(e.valueItem,"top",null)}}}):t("input",{directives:[{name:"model",rawName:"v-model",value:e.valueItem.top,expression:"valueItem.top"}],attrs:{min:e.min,step:e.step,max:e.max,placeholder:"",type:e.isCustomType?"text":"number"},domProps:{value:e.valueItem.top},on:{input:function(t){t.target.composing||e.$set(e.valueItem,"top",t.target.value)}}}),e._v(" "),t("label",[e._v("Top")])]),e._v(" "),t("li",["checkbox"==(e.isCustomType?"text":"number")?t("input",{directives:[{name:"model",rawName:"v-model",value:e.valueItem.right,expression:"valueItem.right"}],attrs:{disabled:"yes"==e.valueItem.linked,min:e.min,step:e.step,max:e.max,placeholder:"",type:"checkbox"},domProps:{checked:Array.isArray(e.valueItem.right)?e._i(e.valueItem.right,null)>-1:e.valueItem.right},on:{change:function(t){var n=e.valueItem.right,i=t.target,r=!!i.checked;if(Array.isArray(n)){var o=e._i(n,null);i.checked?o<0&&e.$set(e.valueItem,"right",n.concat([null])):o>-1&&e.$set(e.valueItem,"right",n.slice(0,o).concat(n.slice(o+1)))}else e.$set(e.valueItem,"right",r)}}}):"radio"==(e.isCustomType?"text":"number")?t("input",{directives:[{name:"model",rawName:"v-model",value:e.valueItem.right,expression:"valueItem.right"}],attrs:{disabled:"yes"==e.valueItem.linked,min:e.min,step:e.step,max:e.max,placeholder:"",type:"radio"},domProps:{checked:e._q(e.valueItem.right,null)},on:{change:function(t){return e.$set(e.valueItem,"right",null)}}}):t("input",{directives:[{name:"model",rawName:"v-model",value:e.valueItem.right,expression:"valueItem.right"}],attrs:{disabled:"yes"==e.valueItem.linked,min:e.min,step:e.step,max:e.max,placeholder:"",type:e.isCustomType?"text":"number"},domProps:{value:e.valueItem.right},on:{input:function(t){t.target.composing||e.$set(e.valueItem,"right",t.target.value)}}}),e._v(" "),t("label",[e._v("Right")])]),e._v(" "),t("li",["checkbox"==(e.isCustomType?"text":"number")?t("input",{directives:[{name:"model",rawName:"v-model",value:e.valueItem.left,expression:"valueItem.left"}],attrs:{disabled:"yes"==e.valueItem.linked,min:e.min,step:e.step,max:e.max,placeholder:"",type:"checkbox"},domProps:{checked:Array.isArray(e.valueItem.left)?e._i(e.valueItem.left,null)>-1:e.valueItem.left},on:{change:function(t){var n=e.valueItem.left,i=t.target,r=!!i.checked;if(Array.isArray(n)){var o=e._i(n,null);i.checked?o<0&&e.$set(e.valueItem,"left",n.concat([null])):o>-1&&e.$set(e.valueItem,"left",n.slice(0,o).concat(n.slice(o+1)))}else e.$set(e.valueItem,"left",r)}}}):"radio"==(e.isCustomType?"text":"number")?t("input",{directives:[{name:"model",rawName:"v-model",value:e.valueItem.left,expression:"valueItem.left"}],attrs:{disabled:"yes"==e.valueItem.linked,min:e.min,step:e.step,max:e.max,placeholder:"",type:"radio"},domProps:{checked:e._q(e.valueItem.left,null)},on:{change:function(t){return e.$set(e.valueItem,"left",null)}}}):t("input",{directives:[{name:"model",rawName:"v-model",value:e.valueItem.left,expression:"valueItem.left"}],attrs:{disabled:"yes"==e.valueItem.linked,min:e.min,step:e.step,max:e.max,placeholder:"",type:e.isCustomType?"text":"number"},domProps:{value:e.valueItem.left},on:{input:function(t){t.target.composing||e.$set(e.valueItem,"left",t.target.value)}}}),e._v(" "),t("label",[e._v("Left")])]),e._v(" "),t("li",["checkbox"==(e.isCustomType?"text":"number")?t("input",{directives:[{name:"model",rawName:"v-model",value:e.valueItem.bottom,expression:"valueItem.bottom"}],attrs:{disabled:"yes"==e.valueItem.linked,min:e.min,step:e.step,max:e.max,placeholder:"",type:"checkbox"},domProps:{checked:Array.isArray(e.valueItem.bottom)?e._i(e.valueItem.bottom,null)>-1:e.valueItem.bottom},on:{change:function(t){var n=e.valueItem.bottom,i=t.target,r=!!i.checked;if(Array.isArray(n)){var o=e._i(n,null);i.checked?o<0&&e.$set(e.valueItem,"bottom",n.concat([null])):o>-1&&e.$set(e.valueItem,"bottom",n.slice(0,o).concat(n.slice(o+1)))}else e.$set(e.valueItem,"bottom",r)}}}):"radio"==(e.isCustomType?"text":"number")?t("input",{directives:[{name:"model",rawName:"v-model",value:e.valueItem.bottom,expression:"valueItem.bottom"}],attrs:{disabled:"yes"==e.valueItem.linked,min:e.min,step:e.step,max:e.max,placeholder:"",type:"radio"},domProps:{checked:e._q(e.valueItem.bottom,null)},on:{change:function(t){return e.$set(e.valueItem,"bottom",null)}}}):t("input",{directives:[{name:"model",rawName:"v-model",value:e.valueItem.bottom,expression:"valueItem.bottom"}],attrs:{disabled:"yes"==e.valueItem.linked,min:e.min,step:e.step,max:e.max,placeholder:"",type:e.isCustomType?"text":"number"},domProps:{value:e.valueItem.bottom},on:{input:function(t){t.target.composing||e.$set(e.valueItem,"bottom",t.target.value)}}}),e._v(" "),t("label",[e._v("bottom")])]),e._v(" "),t("li",[t("span",{staticClass:"ff-linked ff_item_linkable",class:"yes"==e.valueItem.linked?"ff_item_linked":"",on:{click:function(t){return e.handleLinkable()}}},["yes"==e.valueItem.linked?t("span",{staticClass:"dashicons dashicons-editor-unlink"}):t("span",{staticClass:"dashicons dashicons-admin-links"})])])])])])}),[],!1,null,null,null).exports;const ue=ne({name:"ff_border_config",components:{ff_around_item:ce},props:["item"],data:function(){return{borderTypes:{solid:"Solid",double:"Double",dotted:"Dotted",dashed:"Dashed",groove:"Groove",ridge:"Ridge"}}},methods:{handleColorChange:function(e){this.item.value.border_color=e}}},(function(){var e=this,t=e._self._c;return t("div",{staticClass:"ff_border_config"},[e.item.label?t("div",{staticClass:"ff_section_title"},[e._v("\n "+e._s(e.item.label)+"\n ")]):e._e(),e._v(" "),t("div",{staticClass:"ff-control-content"},[t("div",{staticClass:"ff-control-field ff_input_wrapper_full"},[t("el-checkbox",{attrs:{"true-label":"yes","false-label":"no"},model:{value:e.item.value.status,callback:function(t){e.$set(e.item.value,"status",t)},expression:"item.value.status"}},[e._v(e._s(e.item.status_label))])],1),e._v(" "),"yes"==e.item.value.status?[t("div",{staticClass:"ff-control-field ff_each_style",staticStyle:{"margin-top":"15px"}},[t("label",{staticClass:"ff-control-title"},[e._v("\n "+e._s(e.$t("Border Type"))+"\n ")]),e._v(" "),t("div",{staticClass:"ff-control-input-wrapper"},[t("el-select",{attrs:{size:"mini",placeholder:e.$t("Select")},model:{value:e.item.value.border_type,callback:function(t){e.$set(e.item.value,"border_type",t)},expression:"item.value.border_type"}},e._l(e.borderTypes,(function(n,i){return t("el-option",{key:i,attrs:{label:e.$t(n),value:i}})})),1)],1)]),e._v(" "),t("div",{staticClass:"ff-control-field ff_each_style"},[t("label",{staticClass:"ff-control-title"},[e._v("\n "+e._s(e.$t("Border Color"))+"\n ")]),e._v(" "),t("div",{staticClass:"ff-control-input-wrapper"},[t("el-color-picker",{attrs:{size:"mini","show-alpha":""},on:{"active-change":e.handleColorChange},model:{value:e.item.value.border_color,callback:function(t){e.$set(e.item.value,"border_color",t)},expression:"item.value.border_color"}})],1)]),e._v(" "),t("ff_around_item",{staticClass:"mb-3",attrs:{item:{label:"Border Width",key:"borderWidth"},valueItem:e.item.value.border_width}}),e._v(" "),e.item.value.border_radius?t("ff_around_item",{attrs:{item:{label:"Border Radius",key:"borderRadius"},valueItem:e.item.value.border_radius}}):e._e()]:e._e()],2)])}),[],!1,null,null,null).exports;var de=n(18446),fe=n.n(de),pe=n(47065);const he=ne({name:"ff_typegraphy",components:{SliderWithUnit:oe},props:["item","valueItem"],data:function(){return{visible:!1,hasChange:!1,fontWeights:{100:100,200:200,300:300,400:400,500:500,600:600,700:700,800:800,900:900,"":"Default",normal:"Normal",bold:"Bold"},transforms:{"":"Default",uppercase:"Uppercase",lowercase:"Lowercase",capitalize:"Capitalize",normal:"Normal"},fontStyles:{"":"Default",normal:"Normal",italic:"Italic",oblique:"Oblique"},textDecorations:{"":"Default",underline:"Underline",overline:"Overline",oblique:"Oblique","line-through":"Line Through",none:"None"},default:(new pe.ZT).value}},computed:{isChanged:function(){return fe()(this.default,this.valueItem)}},methods:{reset:function(){(0,pe.By)(this.valueItem,this.default)}}},(function(){var e=this,t=e._self._c;return t("div",{staticClass:"ff-control-content"},[t("div",{staticClass:"ff-control-field"},[t("label",{staticClass:"ff-control-title"},[e._v("\n "+e._s(e.$t(e.item.label))+"\n ")]),e._v(" "),t("div",{staticClass:"ff-control-input-wrapper"},[t("el-popover",{attrs:{width:"300"},model:{value:e.visible,callback:function(t){e.visible=t},expression:"visible"}},[t("div",{staticClass:"ff_type_settings"},[t("slider-with-unit",{attrs:{label:e.$t("Font Size"),item:e.valueItem.fontSize},on:{"update:itemValue":function(t){return e.valueItem.fontSize.value=t},"update:itemType":function(t){return e.valueItem.fontSize.type=t}}}),e._v(" "),t("div",{staticClass:"ff-type-control"},[t("label",{staticClass:"ff-control-title"},[e._v("\n "+e._s(e.$t("Font Weight"))+"\n ")]),e._v(" "),t("div",{staticClass:"ff-type-value"},[t("el-select",{attrs:{size:"mini",placeholder:e.$t("Select")},model:{value:e.valueItem.fontWeight,callback:function(t){e.$set(e.valueItem,"fontWeight",t)},expression:"valueItem.fontWeight"}},e._l(e.fontWeights,(function(n,i){return t("el-option",{key:i,attrs:{label:e.$t(n),value:i}})})),1)],1)]),e._v(" "),t("div",{staticClass:"ff-type-control"},[t("label",{staticClass:"ff-control-title"},[e._v("\n "+e._s(e.$t("Transform"))+"\n ")]),e._v(" "),t("div",{staticClass:"ff-type-value"},[t("el-select",{attrs:{size:"mini",placeholder:e.$t("Select")},model:{value:e.valueItem.transform,callback:function(t){e.$set(e.valueItem,"transform",t)},expression:"valueItem.transform"}},e._l(e.transforms,(function(n,i){return t("el-option",{key:i,attrs:{label:e.$t(n),value:i}})})),1)],1)]),e._v(" "),t("div",{staticClass:"ff-type-control"},[t("label",{staticClass:"ff-control-title"},[e._v("\n "+e._s(e.$t("Font Style"))+"\n ")]),e._v(" "),t("div",{staticClass:"ff-type-value"},[t("el-select",{attrs:{size:"mini",placeholder:e.$t("Select")},model:{value:e.valueItem.fontStyle,callback:function(t){e.$set(e.valueItem,"fontStyle",t)},expression:"valueItem.fontStyle"}},e._l(e.fontStyles,(function(n,i){return t("el-option",{key:i,attrs:{label:e.$t(n),value:i}})})),1)],1)]),e._v(" "),t("div",{staticClass:"ff-type-control"},[t("label",{staticClass:"ff-control-title"},[e._v("\n "+e._s(e.$t("Text Decoration"))+"\n ")]),e._v(" "),t("div",{staticClass:"ff-type-value"},[t("el-select",{attrs:{size:"mini",placeholder:e.$t("Select")},model:{value:e.valueItem.textDecoration,callback:function(t){e.$set(e.valueItem,"textDecoration",t)},expression:"valueItem.textDecoration"}},e._l(e.textDecorations,(function(n,i){return t("el-option",{key:i,attrs:{label:e.$t(n),value:i}})})),1)],1)]),e._v(" "),t("slider-with-unit",{attrs:{label:e.$t("Line Height"),item:e.valueItem.lineHeight},on:{"update:itemValue":function(t){return e.valueItem.lineHeight.value=t},"update:itemType":function(t){return e.valueItem.lineHeight.type=t}}}),e._v(" "),t("slider-with-unit",{attrs:{label:e.$t("Letter Spacing"),item:e.valueItem.letterSpacing,config:{px_min:-100,em_rem_min:-10}},on:{"update:itemValue":function(t){return e.valueItem.letterSpacing.value=t},"update:itemType":function(t){return e.valueItem.letterSpacing.type=t}}}),e._v(" "),t("slider-with-unit",{attrs:{label:e.$t("Word Spacing"),item:e.valueItem.wordSpacing,config:{px_min:-100,em_rem_min:-10}},on:{"update:itemValue":function(t){return e.valueItem.wordSpacing.value=t},"update:itemType":function(t){return e.valueItem.wordSpacing.type=t}}})],1),e._v(" "),t("el-button",{staticClass:"el-button--icon",attrs:{slot:"reference",type:"mini"},slot:"reference"},[t("i",{staticClass:"el-icon-edit"})])],1),e._v(" "),e.isChanged?e._e():t("el-button",{staticClass:"el-button--icon",attrs:{type:"mini",icon:"el-icon-refresh-right"},on:{click:e.reset}})],1)])])}),[],!1,null,null,null).exports;const ve=ne({name:"ff_allignment_item",props:["item"],methods:{alignment:function(e){this.item.value=e}}},(function(){var e=this,t=e._self._c;return t("div",{staticClass:"ff-control-content"},[t("div",{staticClass:"ff-control-field"},[t("label",{staticClass:"ff-control-title"},[e._v("\n "+e._s(e.$t(e.item.label))+"\n ")]),e._v(" "),t("div",{staticClass:"ff-control-input-wrapper"},[t("el-button-group",[t("el-button",{class:"left"==e.item.value?"ff_align_active":"",attrs:{size:"mini",icon:"dashicons dashicons-editor-alignleft"},on:{click:function(t){return e.alignment("left")}}}),e._v(" "),t("el-button",{class:"center"==e.item.value?"ff_align_active":"",attrs:{size:"mini",icon:"dashicons dashicons-editor-aligncenter"},on:{click:function(t){return e.alignment("center")}}}),e._v(" "),t("el-button",{class:"right"==e.item.value?"ff_align_active":"",attrs:{size:"mini",icon:"dashicons dashicons-editor-alignright"},on:{click:function(t){return e.alignment("right")}}})],1)],1)])])}),[],!1,null,null,null).exports;const me=ne({name:"ff_boxshadow",components:{SliderWithUnit:oe},props:["item","valueItem"],data:function(){return{visible:!1,position:{outline:"Outline",inset:"Inset"},boxshadowDefault:(new pe.i6).value}},computed:{isChanged:function(){return fe()(this.boxshadowDefault,this.valueItem)}},methods:{handleChange:function(e){this.valueItem.color=e},reset:function(){(0,pe.By)(this.valueItem,this.boxshadowDefault)}}},(function(){var e=this,t=e._self._c;return t("div",{staticClass:"ff-control-content"},[t("div",{staticClass:"ff-control-field"},[t("label",{staticClass:"ff-control-title"},[e._v("\n "+e._s(e.$t(e.item.label))+"\n ")]),e._v(" "),t("div",{staticClass:"ff-control-input-wrapper"},[t("el-popover",{attrs:{width:"300"},model:{value:e.visible,callback:function(t){e.visible=t},expression:"visible"}},[t("div",{staticClass:"ff_type_settings"},[t("div",{staticClass:"ff-type-control"},[t("label",{staticClass:"ff-control-title"},[e._v("\n "+e._s(e.$t("Color"))+"\n ")]),e._v(" "),t("div",{staticClass:"ff-type-value",staticStyle:{"margin-left":"200px"}},[t("el-color-picker",{attrs:{size:"mini","show-alpha":""},on:{"active-change":e.handleChange},model:{value:e.valueItem.color,callback:function(t){e.$set(e.valueItem,"color",t)},expression:"valueItem.color"}})],1)]),e._v(" "),t("slider-with-unit",{attrs:{label:e.$t("Horizontal"),item:e.valueItem.horizontal,config:{px_max:30,px_min:-30,em_rem_max:4,em_rem_min:-4}},on:{"update:itemValue":function(t){return e.valueItem.horizontal.value=t},"update:itemType":function(t){return e.valueItem.horizontal.type=t}}}),e._v(" "),t("slider-with-unit",{attrs:{label:e.$t("Vertical"),item:e.valueItem.vertical,config:{px_max:30,px_min:-30,em_rem_max:4,em_rem_min:-4}},on:{"update:itemValue":function(t){return e.valueItem.vertical.value=t},"update:itemType":function(t){return e.valueItem.vertical.type=t}}}),e._v(" "),t("slider-with-unit",{attrs:{label:e.$t("Blur"),item:e.valueItem.blur,config:{px_max:30,em_rem_max:4}},on:{"update:itemValue":function(t){return e.valueItem.blur.value=t},"update:itemType":function(t){return e.valueItem.blur.type=t}}}),e._v(" "),t("slider-with-unit",{attrs:{label:e.$t("Spread"),item:e.valueItem.spread,config:{px_max:30,em_rem_max:4}},on:{"update:itemValue":function(t){return e.valueItem.spread.value=t},"update:itemType":function(t){return e.valueItem.spread.type=t}}}),e._v(" "),t("div",{staticClass:"ff-type-control"},[t("label",{staticClass:"ff-control-title"},[e._v("\n "+e._s(e.$t("Position"))+"\n ")]),e._v(" "),t("div",{staticClass:"ff-type-value"},[t("el-select",{attrs:{size:"mini",placeholder:e.$t("Select")},model:{value:e.valueItem.position,callback:function(t){e.$set(e.valueItem,"position",t)},expression:"valueItem.position"}},e._l(e.position,(function(n,i){return t("el-option",{key:i,attrs:{label:e.$t(n),value:i}})})),1)],1)])],1),e._v(" "),t("el-button",{staticClass:"el-button--icon",attrs:{slot:"reference",type:"mini"},slot:"reference"},[t("i",{staticClass:"el-icon-edit"})])],1),e._v(" "),e.isChanged?e._e():t("el-button",{staticClass:"el-button--icon",attrs:{type:"mini",icon:"el-icon-refresh-right"},on:{click:e.reset}})],1)])])}),[],!1,null,null,null).exports;const _e=ne({name:"ff_breakwithtitle",props:["item"]},(function(){var e=this,t=e._self._c;return t("div",{staticClass:"ff-control-content"},[t("div",{staticClass:"ff-control-field"},[t("div",{staticClass:"ff-control-title-breaker"},[e._v("\n "+e._s(e.$t(e.item.label))+"\n ")]),e._v(" "),t("p",[e._v(e._s(e.item.value))])])])}),[],!1,null,null,null).exports;const ge=ne({name:"ff_tabs",props:["item","valueItem"],components:{ff_border_config:ue,ff_typography:he,ff_boxshadow:me,ff_width:le,ff_unit_value:ae,ff_allignment_item:ve,ff_color_picker:ie,ff_around_item:ce}},(function(){var e=this,t=e._self._c;return t("div",{staticClass:"ff-control-content"},[t("div",{staticClass:"ff-control-field"},[t("el-tabs",{staticStyle:{border:"none","box-shadow":"none"},attrs:{type:"border-card",stretch:!0}},e._l(e.item.tabs,(function(n){return t("el-tab-pane",{key:n.key,attrs:{label:n.label}},e._l(n.value,(function(n,i){return t("div",{key:i,staticClass:"ff_each_style"},["color"==n.key||"backgroundColor"==n.key?t("ff_color_picker",{attrs:{item:n}}):"width"==n.key&&"ff_unit_value"!==n.element?t("ff_width",{attrs:{item:n}}):"border"==n.key?t("ff_border_config",{attrs:{item:n}}):"typography"==n.key?t("ff_typography",{attrs:{item:{label:"Typography"},valueItem:n.value}}):"boxshadow"==n.key?t("ff_boxshadow",{attrs:{item:{label:"Box Shadow"},valueItem:n.value}}):"padding"==n.key?t("ff_around_item",{attrs:{item:{label:"Padding",key:"padding"},valueItem:n.value}}):"margin"==n.key?t("ff_around_item",{attrs:{item:{label:"Margin",key:"margin"},valueItem:n.value}}):e._e(),e._v(" "),"ff_unit_value"==n.element?t("ff_unit_value",{attrs:{item:n,"value-item":n.value}}):e._e(),e._v(" "),"ff_allignment_item"==n.element?t("ff_allignment_item",{attrs:{item:n}}):e._e()],1)})),0)})),1)],1)])}),[],!1,null,null,null).exports;var be=ne({name:"ff_radio_checkbox",components:{Ff_around_item:ce,ff_color_picker:ie,ff_border_config:ue},props:["item"]},(function(){var e=this,t=e._self._c;return t("div",{staticClass:"ff_border_config"},[e.item.label?t("div",{staticClass:"ff_section_title"},[e._v("\n "+e._s(e.$t(e.item.label))+"\n ")]):e._e(),e._v(" "),t("div",{staticClass:"ff-control-content"},[t("div",{staticClass:"ff-control-field ff_input_wrapper_full mb-3"},[t("el-checkbox",{attrs:{"true-label":"yes","false-label":"no"},model:{value:e.item.status,callback:function(t){e.$set(e.item,"status",t)},expression:"item.status"}},[e._v(e._s(e.$t(e.item.status_label)))])],1),e._v(" "),"yes"==e.item.status?[t("div",{staticClass:"mb-3"},[t("ff_color_picker",{attrs:{item:e.item.value.color}})],1),e._v(" "),t("div",{staticClass:"mb-3"},[t("ff_color_picker",{attrs:{item:e.item.value.active_color}})],1),e._v(" "),t("div",{staticClass:"mb-3"},[t("ff_around_item",{attrs:{item:e.item.value.margin,"value-item":e.item.value.margin.value}})],1),e._v(" "),t("div",{staticClass:"mb-3"},[t("ff_border_config",{attrs:{item:e.item.value.border}})],1),e._v(" "),"yes"===e.item.value.border.value.status?t("div",[t("div",{staticClass:"ff-control-field ff_input_wrapper_full"},[t("el-checkbox",{attrs:{"true-label":"yes","false-label":"no"},model:{value:e.item.value.border.value.radio_border_status,callback:function(t){e.$set(e.item.value.border.value,"radio_border_status",t)},expression:"item.value.border.value.radio_border_status"}},[e._v(e._s(e.$t("Radio Border Same as Checkbox")))])],1)]):e._e()]:e._e()],2)])}),[],!1,null,null,null);function ye(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var i,r,o,s,a=[],l=!0,c=!1;try{if(o=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;l=!1}else for(;!(l=(i=o.call(n)).done)&&(a.push(i.value),a.length!==t);l=!0);}catch(e){c=!0,r=e}finally{try{if(!l&&null!=n.return&&(s=n.return(),Object(s)!==s))return}finally{if(c)throw r}}return a}}(e,t)||function(e,t){if(!e)return;if("string"==typeof e)return xe(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return xe(e,t)}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function xe(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,i=new Array(t);n tr:nth-child(2n) > td{background-color:").concat(t.value,"!important}"))}))})),t&&(t="".concat(this.custom_selector," .ff-el-input--content table.ff-table.ff-checkable-grids thead tr th { ").concat(t," }")),n&&(n="".concat(this.custom_selector," .ff-el-input--content table.ff-table.ff-checkable-grids tbody tr td{ ").concat(n," }"));var r=t+n+i;this.pushStyle("#ff_gridtable_style",r)}},radio_checkbox_style:{deep:!0,handler:function(){var e="",t="",n=this.radio_checkbox_style.radio_checkbox&&"yes"==this.radio_checkbox_style.radio_checkbox.status;if(n){var i=this.radio_checkbox_style.radio_checkbox.value;e=this.generateCheckableStyles(i.color.value,i.active_color.value,i.border.value,i.margin.value)}if(this.hasValue(this.radio_checkbox_style.size.value.value,"strict")){var r=this.getResolveValue(this.radio_checkbox_style.size.value.value,this.radio_checkbox_style.size.value.type);e+="\n ".concat(this.custom_selector," .ff-el-group input[type=checkbox]").concat(n?":after":"",",\n ").concat(this.custom_selector," .ff-el-group input[type=radio]").concat(n?":after":""," {\n height: ").concat(r,";\n width: ").concat(r,";\n }\n ")}this.radio_checkbox_style.color&&this.radio_checkbox_style.color.value&&(t=this.generateChecboxRadioStyles(this.radio_checkbox_style.color.value));var o=e+t;this.pushStyle("#ff_radio_checkbox",o)}},submit_button_style:{deep:!0,handler:function(){var e=this,t="",n="",i="";Q()(this.submit_button_style,(function(t,i){"all_tabs"!==i&&(n+=e.extractStyle(t,i,""))})),Q()(this.submit_button_style.all_tabs.tabs,(function(n,r){"normal"==r?Q()(n.value,(function(n,i){t+=e.extractStyle(n,i,"")})):"hover"==r&&Q()(n.value,(function(t,n){i+=e.extractStyle(t,n,"")}))})),t&&(t="".concat(this.custom_selector," .ff_submit_btn_wrapper .ff-btn-submit, ").concat(this.custom_selector,".ffs_custom_wrap .ff_submit_btn_wrapper .ff-btn-submit { ").concat(t," }")),i&&(i="".concat(this.custom_selector," .ff_submit_btn_wrapper .ff-btn-submit:hover, ").concat(this.custom_selector,".ffs_custom_wrap .ff_submit_btn_wrapper .ff-btn-submit:hover { ").concat(i," }")),n&&(n="".concat(this.custom_selector," .ff-el-group.ff_submit_btn_wrapper { ").concat(n," }"));var r=t+n+i;this.pushStyle("#ff_submit_button_style",r)}},next_button_style:{deep:!0,handler:function(){var e=this,t="",n="";Q()(this.next_button_style.all_tabs.tabs,(function(i,r){"normal"==r?Q()(i.value,(function(n,i){t+=e.extractStyle(n,i,"")})):"hover"==r&&Q()(i.value,(function(t,i){n+=e.extractStyle(t,i,"")}))})),t&&(t="".concat(this.custom_selector," .step-nav .ff-btn-next { ").concat(t," }")),n&&(n="".concat(this.custom_selector," .step-nav .ff-btn-next:hover { ").concat(n," }"));var i=t+n;this.pushStyle("#ff_next_button_style",i)}},prev_button_style:{deep:!0,handler:function(){var e=this,t="",n="";Q()(this.prev_button_style.all_tabs.tabs,(function(i,r){"normal"==r?Q()(i.value,(function(n,i){t+=e.extractStyle(n,i,"")})):"hover"==r&&Q()(i.value,(function(t,i){n+=e.extractStyle(t,i,"")}))})),t&&(t="".concat(this.custom_selector," .step-nav .ff-btn-prev { ").concat(t," }")),n&&(n="".concat(this.custom_selector," .step-nav .ff-btn-prev:hover { ").concat(n," }"));var i=t+n;this.pushStyle("#ff_prev_button_style",i)}},step_header_style:{deep:!0,handler:function(e){var t=this,n="";if(e.activeColor.value){var i=e.activeColor.value,r=e.inActiveColor.value||"#333",o=e.textColor.value||"#fff";n="".concat(this.custom_selector," .ff-step-titles li.ff_active:before, ").concat(this.custom_selector," .ff-step-titles li.ff_completed:before { background: ").concat(i,"; color: ").concat(o,"; } ").concat(this.custom_selector," .ff-step-titles li.ff_active:after, ").concat(this.custom_selector," .ff-step-titles li.ff_completed:after { background: ").concat(i,";} ").concat(this.custom_selector," .ff-step-titles li:after { background: ").concat(r,";} ").concat(this.custom_selector," .ff-step-titles li:before, ").concat(this.custom_selector," .ff-step-titles li { color: ").concat(r,"; } ").concat(this.custom_selector," .ff-step-titles li.ff_active, ").concat(this.custom_selector," .ff-step-titles li.ff_completed { color: ").concat(i," }"),n+="".concat(this.custom_selector," .ff-el-progress-bar { background: ").concat(i,"; color: ").concat(o,"; } ").concat(this.custom_selector," .ff-el-progress { background-color: ").concat(r,"; }")}var s="";Q()(e,(function(e,i){if(["height","width","margin","boxshadow","border"].includes(i))s+=t.extractStyle(e,i);else if("textPosition"===i){var r=t.generateAroundProperty("{replace}",e.value);r&&(s+="position:relative;",n+="".concat(t.custom_selector," .ff-el-progress .ff-el-progress-bar span {position:absolute;").concat(r,"}"))}})),s&&(s.includes("height")&&(n+="".concat(this.custom_selector," .ff-el-progress .ff-el-progress-bar {display:flex;align-items:center;justify-content:end;}")),n+="".concat(this.custom_selector," .ff-el-progress {").concat(s,"}")),n&&this.pushStyle("#ff_step_header_style",n)}},range_slider_style:{deep:!0,handler:function(e){var t="";if(e.activeColor.value){var n=e.activeColor.value,i=e.inActiveColor.value,r=e.textColor.value;i||(i="#e6e6e6"),r||(r="#3a3a3a"),t="".concat(this.wrapper_selector," .rangeslider__fill { background: ").concat(n,"; } ").concat(this.wrapper_selector," .rangeslider { background: ").concat(i,"; } ").concat(this.wrapper_selector," .rangeslider__handle { color: ").concat(r,"; }")}if(this.hasValue(e.handleSize.value.value,"strict")){var o=this.getResolveValue(e.handleSize.value.value,e.handleSize.value.type);t+="\n ".concat(this.wrapper_selector," .rangeslider__handle { height: ").concat(o,"; width: ").concat(o,";}\n ")}if(this.hasValue(e.height.value.value,"strict")){var s=this.getResolveValue(e.height.value.value,e.height.value.type);t+="\n ".concat(this.wrapper_selector," .rangeslider--horizontal { height: ").concat(s,";}\n ")}this.pushStyle("#ff_range_slider_style",t)}},net_promoter_style:{deep:!0,handler:function(e){var t="",n="",i="";if(e.activeColor.value){var r=e.activeColor.value;n+="background-color: ".concat(r,";"),t+="".concat(this.custom_selector," .ff_net_table tbody tr td label:hover:after { border-color: transparent;}")}if(e.color.value&&(n+="color: ".concat(e.color.value,";")),n&&(t+="".concat(this.custom_selector," .ff_net_table tbody tr td input[type=radio]:checked + label { ").concat(n," }"),t+="".concat(this.custom_selector," .ff_net_table tbody tr td input[type=radio] + label:hover { ").concat(n,"}")),e.inActiveColor.value&&(i+="color: ".concat(e.inActiveColor.value,";")),e.inActiveBgColor.value&&(i+="background-color: ".concat(e.inActiveBgColor.value,";")),this.hasValue(e.height.value.value)&&(i+="height:".concat(this.getResolveValue(e.height.value.value,e.height.value.type),";")),this.hasValue(e.lineHeight.value.value)&&(i+="line-height:".concat(this.getResolveValue(e.lineHeight.value.value,e.lineHeight.value.type),";")),i&&(t+="".concat(this.custom_selector," .ff_net_table tbody tr td input[type=radio] + label { ").concat(i," }")),"yes"===e.border.value.status){var o=this.extractStyle(e.border,"border","");if(o){o+="border-left: 0;border-radius: 0;",t+="".concat(this.custom_selector," .ff_net_table tbody tr td {").concat(o,"}");var s=e.border.value.border_width,a=e.border.value.border_radius,l=e.border.value.border_color,c=e.border.value.border_type,u="",d="";l&&(u+="border-color: ".concat(l,";")),c&&(u+="border-style: ".concat(c,";")),this.hasValue(s.right)&&(t+="".concat(this.custom_selector," .ff_net_table tbody tr td:last-of-type {\n border-right-width: ").concat(this.getResolveValue(s.right,s.type),";\n }")),this.hasValue(s.left)&&(u+="border-left-width: ".concat(this.getResolveValue(s.left,s.type),";")),this.hasValue(a.top)&&(u+="border-top-left-radius: ".concat(this.getResolveValue(a.top,a.type),";")),this.hasValue(a.bottom)&&(u+="border-bottom-left-radius: ".concat(this.getResolveValue(a.bottom,a.type),";")),this.hasValue(a.right)&&(d+="border-top-right-radius: ".concat(this.getResolveValue(a.right,a.type),";")),this.hasValue(a.left)&&(d+="border-bottom-right-radius: ".concat(this.getResolveValue(a.left,a.type),";")),u&&(t+="".concat(this.custom_selector," .ff_net_table tbody tr td:first-of-type { overflow:hidden;").concat(u,"}")),d&&(t+="".concat(this.custom_selector," .ff_net_table tbody tr td:last-child {overflow:hidden;").concat(d,"}"))}}this.pushStyle("#ff_net_promoter_score",t)}},payment_summary_style:{deep:!0,handler:function(){var e=this,t="",n="",i="";Q()(this.payment_summary_style.all_tabs.tabs,(function(r,o){"TableHead"==o?Q()(r.value,(function(n,i){t+=e.extractStyle(n,i,"")})):"TableBody"==o?Q()(r.value,(function(t,i){n+=e.extractStyle(t,i,"")})):"TableFooter"==o&&Q()(r.value,(function(t,n){i+=e.extractStyle(t,n,"")}))})),t&&(t="".concat(this.custom_selector," .ff-el-group .ff_payment_summary table thead tr th { ").concat(t," }")),n&&(n="".concat(this.custom_selector," .ff-el-group .ff_payment_summary table tbody tr td{ ").concat(n," }")),i&&(i="".concat(this.custom_selector," .ff-el-group .ff_payment_summary table tfoot tr th{ ").concat(i," }"));var r=t+n+i;this.pushStyle("#ff_payment_summary",r)}},stripe_inline_element_style:{handler:function(){this.has_stripe_inline_element&&jQuery("form.frm-fluent-form").trigger("fluentform_update_stripe_inline_element_style",[this.stripe_inline_element_style])},deep:!0},payment_coupon_style:{deep:!0,handler:function(){var e=this,t="",n="";Q()(this.payment_coupon_style.all_tabs.tabs,(function(i,r){"button"==r?Q()(i.value,(function(n,i){t+=e.extractStyle(n,i,"")})):"buttonHover"==r&&Q()(i.value,(function(t,i){n+=e.extractStyle(t,i,"")}))})),t&&(t="".concat(this.custom_selector," .ff-el-group .ff-el-input--content .ff_input-group .ff_input-group-append span { ").concat(t," }")),n&&(n="".concat(this.custom_selector," .ff-el-group .ff-el-input--content .ff_input-group .ff_input-group-append span:hover { ").concat(n," }"));var i=t+n;this.pushStyle("#ff_payment_coupon",i)}},image_or_file_button_style:{deep:!0,handler:function(){var e=this,t="",n="";Q()(this.image_or_file_button_style.all_tabs.tabs,(function(i,r){"button"==r?Q()(i.value,(function(n,i){t+=e.extractStyle(n,i,"")})):"buttonHover"==r&&Q()(i.value,(function(t,i){n+=e.extractStyle(t,i,"")}))})),t&&(t="".concat(this.custom_selector," .ff-el-group .ff-el-input--content .ff_file_upload_holder span.ff_upload_btn { ").concat(t," }")),n&&(n="".concat(this.custom_selector," .ff-el-group .ff-el-input--content .ff_file_upload_holder span.ff_upload_btn:hover { ").concat(n," }"));var i=t+n;this.pushStyle("#image_or_file_button_style",i)}},customize_preset:function(){this.customize_preset||""===this.preset_name.trim()||this.applyStylesWithAutoResolve()}},methods:{changePreset:function(){""==this.preset_name&&(this.customize_preset=!1)},pushStyle:function(e,t){jQuery(e).html('")},extractStyle:function(e,t,n){var i="";if("backgroundColor"==t)e.value&&(i+="background-color: ".concat(e.value,";"));else if("backgroundImage"==t)i+=this.generateBackgroundImage(e.value);else if("color"==t||"active_color"==t)e.value&&(i+="color: ".concat(e.value,";"));else if("color_asterisk"==t)e.value&&(i+="color: ".concat(e.value," !important;"));else if("margin"==t||"padding"==t)i+=this.generateAroundDimention(t,e.value);else if("border"==t||"hover_border"==t){if("yes"!=e.value.status)return"";i+="border-style: ".concat(e.value.border_type,";"),e.value.border_color&&(i+="border-color: ".concat(e.value.border_color,";")),i+=this.generateAroundDimentionBorder(e.value.border_width),i+=this.generateAroundDimentionBorderRadius("border",e.value.border_radius)}else if("typography"==t)i+=this.generateTypegraphy(e.value);else if("des_margin"==t)i+=this.generateAroundDimention("margin",e.value);else if("des_padding"==t)i+=this.generateAroundDimention("padding",e.value);else if("boxshadow"==t)i+=this.generateBoxshadow(e.value);else if("allignment"==t)i+=this.generateAllignment(e.value);else if("placeholder"==t)i+=this.generatePlaceholder(e.value);else if("width"==t){var r=e.value,o=e.type||"custom";r&&"object"===we(r)&&(o=r.type,r=r.value),this.hasValue(r)&&(i+="width: ".concat(this.getResolveValue(r,o),";"))}else if("height"==t){var s=e.value;this.hasValue(s.value)&&(i+="height: ".concat(this.getResolveValue(s.value,s.type),";"))}return i&&n?n+"{ "+i+" } ":i},generateAroundProperty:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],i="";return this.hasValue(t.top)&&(i+="".concat(e.replace("{replace}",n?"top-left":"top"),":").concat(this.getResolveValue(t.top,t.type),";")),this.hasValue(t.right)&&(i+="".concat(e.replace("{replace}",n?"top-right":"right"),":").concat(this.getResolveValue(t.right,t.type),";")),this.hasValue(t.left)&&(i+="".concat(e.replace("{replace}",n?"bottom-right":"left"),":").concat(this.getResolveValue(t.left,t.type),";")),this.hasValue(t.bottom)&&(i+="".concat(e.replace("{replace}",n?"bottom-left":"bottom"),":").concat(this.getResolveValue(t.bottom,t.type),";")),i},generateAroundDimention:function(e,t){var n=t.type||"px";return"yes"==t.linked?this.hasValue(t.top)?"".concat(e,": ").concat(this.getResolveValue(t.top,n),";"):"":this.generateAroundProperty("".concat(e,"-{replace}"),t)},generateAroundDimentionBorder:function(e){var t=e.type||"px";return"yes"==e.linked?this.hasValue(e.top)?"border-width: ".concat(this.getResolveValue(e.top,t),";"):"":this.generateAroundProperty("border-{replace}-width",e)},generateAroundDimentionBorderRadius:function(e,t){if(!t)return"";var n=t.type||"px";return"yes"==t.linked?this.hasValue(t.top)?"".concat(e,"-radius: ").concat(this.getResolveValue(t.top,n),";"):"":this.generateAroundProperty("".concat(e,"-{replace}-radius"),t,!0)},generateTypegraphy:function(e){var t,n="";return this.hasValue(e.fontSize.value)&&(n+="font-size: ".concat(this.getResolveValue(e.fontSize.value,e.fontSize.type),";")),e.fontWeight&&(n+="font-weight: ".concat(e.fontWeight,";")),e.transform&&(n+="text-transform: ".concat(e.transform,";")),e.fontStyle&&(n+="font-style: ".concat(e.fontStyle,";")),e.textDecoration&&(n+="text-decoration: ".concat(e.textDecoration,";")),this.hasValue(e.lineHeight.value)&&(n+="line-height: ".concat(this.getResolveValue(e.lineHeight.value,e.lineHeight.type),";")),this.hasValue(e.letterSpacing.value)&&(n+="letter-spacing: ".concat(this.getResolveValue(e.letterSpacing.value,e.letterSpacing.type),";")),this.hasValue(null===(t=e.wordSpacing)||void 0===t?void 0:t.value)&&(n+="word-spacing: ".concat(this.getResolveValue(e.wordSpacing.value,e.wordSpacing.type),";")),n},generateBackgroundImage:function(e){var t="";if("classic"===e.type){var n=e.image;if(t+="background-image: url('".concat(n.url,"');"),n.position.value){var i=n.position.value;"custom"===i?(this.hasValue(n.position.valueX.value)&&(t+="background-position-x: ".concat(this.getResolveValue(n.position.valueX.value,n.position.valueX.type),";")),this.hasValue(n.position.valueY.value)&&(t+="background-position-y: ".concat(this.getResolveValue(n.position.valueY.value,n.position.valueY.type),";"))):t+="background-position: ".concat(i,";")}if(n.repeat&&(t+="background-repeat: ".concat(n.repeat,";")),n.attachment&&(t+="background-attachment: ".concat(n.attachment,";")),n.size.value){var r,o,s=n.size.value;if("custom"===s)this.hasValue(n.size.valueX.value)&&(r=this.getResolveValue(n.size.valueX.value,n.size.valueX.type)),this.hasValue(n.size.valueY.value)&&(o=this.getResolveValue(n.size.valueY.value,n.size.valueY.type)),r||(r="auto"),o||(o="auto"),s=r+" "+o;t+="background-size: ".concat(s,";")}}else{var a="",l=e.gradient.primary,c=e.gradient.secondary;l.color&&c.color&&(a+="".concat(l.color," ").concat(this.getResolveValue(l.location.value||0,l.location.type)),a+=", ".concat(c.color," ").concat(this.getResolveValue(c.location.value||0,c.location.type)),"radial"===e.gradient.type?t+="background-image: radial-gradient(at ".concat(e.gradient.position,", ").concat(a,");"):t+="background-image: linear-gradient(".concat(this.getResolveValue(e.gradient.angle.value||0,e.gradient.angle.type),", ").concat(a,");"))}return t},generateBoxshadow:function(e){var t="",n=e.horizontal.value,i=e.vertical.value,r=e.blur.value,o=e.spread.value;return this.hasValue(n)&&(n=this.getResolveValue(n,e.horizontal.type)),this.hasValue(i)&&(i=this.getResolveValue(i,e.vertical.type)),this.hasValue(r)&&(r=this.getResolveValue(r,e.blur.type)),this.hasValue(o)&&(o=this.getResolveValue(o,e.spread.type)),(n||i||r||o)&&(t+="box-shadow: ".concat(n||0," ").concat(i||0," ").concat(r||0," ").concat(o||0," ").concat(e.color||""),"inset"==e.position&&(t+=" "+e.position),t+=";"),t},generateAllignment:function(e){var t="";return t+="text-align: ".concat(e,";")},generatePlaceholder:function(e){var t="";return t+="color: ".concat(e,";")},generateChecboxRadioStyles:function(e){var t="";return t+="color: ".concat(e,";"),"".concat(this.custom_selector," .ff-el-form-check { ").concat(t," }")},generateCheckableStyles:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};t||(t="black");var r=e||"black",o="border-width:1px;",s="border-radius:1px;",a="solid",l=!1,c=this.generateAroundDimention("margin",i)||"margin-left: 3px;";return"yes"===n.status&&(r=n.border_color||r,o=this.generateAroundDimentionBorder(n.border_width),s=this.generateAroundDimentionBorderRadius("border",n.border_radius),a=n.border_type,"yes"===n.radio_border_status&&(l=!0)),"".concat(this.custom_selector," .ff-el-group input[type=checkbox],\n ").concat(this.custom_selector," .ff-el-group input[type=radio] {\n -webkit-transform: scale(1);\n transform: scale(1);\n width: 21px;\n height: 15px;\n margin-right: 0px;\n cursor: pointer;\n font-size: 12px;\n position: relative;\n text-align: left;\n border: none;\n box-shadow: none;\n -moz-appearance: initial;\n } ").concat(this.custom_selector," .ff-el-group input[type=checkbox]:before,\n ").concat(this.custom_selector," .ff-el-group input[type=radio]:before {\n content: none;\n } ").concat(this.custom_selector," .ff-el-group input[type=checkbox]:after,\n ").concat(this.custom_selector,' .ff-el-group input[type=radio]:after {\n content: " ";\n background-color: #fff;\n display: inline-block;\n ').concat(c,"\n padding-bottom: 3px;\n color: #212529;\n width: 15px;\n height: 15px;\n border-color: ").concat(r,";\n border-style: ").concat(a,";\n ").concat(o,"\n padding-left: 1px;\n ").concat(s,"\n padding-top: 1px;\n -webkit-transition: all .1s ease;\n transition: all .1s ease;\n background-size: 9px;\n background-repeat: no-repeat;\n background-position: center center;\n position: absolute;\n box-sizing: border-box;\n } ").concat(this.custom_selector," .ff-el-group input[type=checkbox]:checked:after, ").concat(this.custom_selector," .ff-el-group input[type=radio]:checked:after {\n ").concat(o,"\n background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E\");\n background-color: ").concat(t,";\n -webkit-transition: all 0.3s ease-out;\n transition: all 0.3s ease-out;\n color: #fff;\n border-color: ").concat(t,";\n } ").concat(this.custom_selector," .ff-el-group input[type=radio]:after {\n ").concat(l?s:"border-radius: 50%;","\n font-size: 10px;\n padding-top: 1px;\n padding-left: 2px;\n } ").concat(this.custom_selector," .ff-el-group input[type=radio]:checked:after {\n background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E\");\n }")},generateNetPromoterStyles:function(e){var t="";if("yes"==e.value.status){var n=e.value.border_color,i=e.value.border_width.bottom,r=e.value.border_radius.top,o=e.value.border_type,s="\n .ff_net_table tbody tr td {\n border: ".concat(i,"px ").concat(o," ").concat(n,";\n border-right-width: ").concat(i,"px;\n border-left: 0;\n }.ff_net_table tbody tr td:last-of-type {\n border-right-width: ").concat(i,"px;\n };\n .ff_net_table tbody tr td:last-child {\n border-radius: 0 ").concat(r,"px ").concat(r,"px 0;\n }.ff_net_table tbody tr td:first-of-type {\n border-left: ").concat(i,"px ").concat(o," ").concat(n,";\n } \n .ff_net_table tbody tr td:first-of-type {\n border-left: ").concat(i,"px ").concat(o," ").concat(n,";\n border-radius: ").concat(r,"px 0 0 ").concat(r,"px;\n }");t+="".concat(this.custom_selector," { ").concat(s," }")}return t},generateCheckboxRadio:function(e){var t="";if(e&&"yes"==e.value.status){var n=e.value.border_color,i=e.value.border_width.bottom,r=e.value.border_radius.top,o=e.value.border_type,s="";s+=".ff_net_table tbody tr td {\n border: ".concat(i,"px ").concat(o," ").concat(n,";\n border-right-width: ").concat(i,"px;\n border-left: 0;\n };"),s+=".ff_net_table tbody tr td:last-of-type {\n border-right-width: ".concat(i,"px;\n };\n .ff_net_table tbody tr td:last-child {\n border-radius: 0 ").concat(r,"px ").concat(r,"px 0;\n };"),s+=".ff_net_table tbody tr td:first-of-type {\n border-left: ".concat(i,"px ").concat(o," ").concat(n,";\n };\n .ff_net_table tbody tr td:first-of-type {\n border-left: ").concat(i,"px ").concat(o," ").concat(n,";\n border-radius: ").concat(r,"px 0 0 ").concat(r,"px;\n }"),t+="".concat(this.custom_selector," { ").concat(s," }")}return t},getSettings:function(){var e=this;this.loading=!0,FluentFormsGlobal.$get({action:"fluentform_get_form_styler",form_id:this.form_vars.form_id,with_all_form_styles:"yes"}).then((function(t){e.preset_name=t.data.preset_style,e.is_multipage=t.data.is_multipage,e.has_section_break=t.data.has_section_break||t.data.has_html_input,e.has_tabular_grid=t.data.has_tabular_grid,e.has_range_slider=t.data.has_range_slider,e.has_net_promoter=t.data.has_net_promoter,e.has_stripe_inline_element=t.data.has_stripe_inline_element,e.has_payment_summary=t.data.has_payment_summary,e.has_payment_coupon=t.data.has_payment_coupon,e.has_image_or_file_button=t.data.has_image_or_file_button,e.has_custom_style=t.data.styles;for(var n={},i=function(){var t=ye(o[r],2),i=t[0],s=t[1];if(s.style){var a=JSON.parse(s.style);Q()(a,(function(t,n){void 0!==e[n]&&(a[n]=te()(structuredClone(e[n]),t))})),s.style=a}n[i]=s},r=0,o=Object.entries(t.data.presets);r0&&void 0!==arguments[0]?arguments[0]:"",n=null===(e=this.presets[this.preset_name])||void 0===e?void 0:e.style;"ffs_custom"===this.preset_name.trim()&&(n=this.saved_custom_styles),void 0!==n&&(n=JSON.parse(JSON.stringify(n))),t&&jQuery(".fluentform").removeClass(t+"_wrap"),this.applyStyle(n),this.input_styles_watch_handler()},resetStyle:function(){var e=this.$options.data.call(this),t={label_styles:e.label_styles,container_styles:e.container_styles,input_styles:e.input_styles,placeholder_styles:e.placeholder_styles,sectionbreak_styles:e.sectionbreak_styles,gridtable_style:e.gridtable_style,radio_checkbox_style:e.radio_checkbox_style,submit_button_style:e.submit_button_style,asterisk_styles:e.asterisk_styles,inline_error_msg_style:e.inline_error_msg_style,success_msg_style:e.success_msg_style,error_msg_style:e.error_msg_style,range_slider_style:e.range_slider_style,net_promoter_style:e.net_promoter_style,step_header_style:e.step_header_style,next_button_style:e.next_button_style,prev_button_style:e.prev_button_style,stripe_inline_element_style:e.stripe_inline_element_style,payment_summary_style:e.payment_summary_style,payment_coupon_style:e.payment_coupon_style,image_or_file_button_style:e.image_or_file_button_style};this.applyStyle(t)},getResolveValue:function(e,t){return"custom"===t?e:e+t},hasValue:function(e){return void 0!==e&&""!==e}},computed:{maybeEnableCustomization:function(){return""!=this.preset_name&&"ffs_inherit_theme"!==this.preset_name||"ffs_custom"==this.preset_name},showCustomizer:function(){return 1==this.customize_preset||"ffs_custom"==this.preset_name}},mounted:function(){this.getSettings(),window.addEventListener("selectionFired",this.handleElmSelection),this.input_styles_watch_handler()}};const Oe=ne({name:"form_styler",mixins:[$e],methods:{saveSettings:function(){var e=this;this.loading=!0;var t=this.generateStyle(),n=1==this.customize_preset||"ffs_custom"==this.preset_name?"ffs_custom":this.preset_name;FluentFormsGlobal.$post({action:"fluentform_save_form_styler",form_id:this.form_vars.form_id,style_name:n,form_styles:JSON.stringify(t)}).then((function(i){e.$notify.success(i.data.message),e.preset_name=n,e.saved_custom_styles=t})).fail((function(e){})).always((function(){e.loading=!1}))},exportStyle:function(){var e=this,t=this.generateStyle();FluentFormsGlobal.$post({action:"fluentform_save_form_styler",form_id:this.form_vars.form_id,style_name:this.preset_name,form_styles:t}).then((function(t){if(1==t.success){var n={format:"json",form_id:e.form_vars.form_id,action:"fluentform_export_form_style",style_name:e.preset_name,nonce:window.fluent_forms_global_var.fluent_forms_admin_nonce};location.href=window.fluent_forms_global_var.ajaxurl+"?"+jQuery.param(n)}})).fail((function(e){})).always((function(){}))},importStyle:function(){var e=this,t=this.existing_form_styles[this.selected_import.type][this.selected_import.form_id].styles,n=this.existing_form_styles[this.selected_import.type][this.selected_import.form_id].type;Q()(t,(function(t,n){e[n]=t})),this.preset_name=n},handleElmSelection:function(e){var t=e.detail.type||"";"label"==t?this.activeName="label_styles":"input"==t?this.activeName="input_styles":"checkable"==t?this.activeName="radio_checkbox_style":"submitBtn"==t?this.activeName="submit_button_style":"sectionBrk"==t&&(this.activeName="sectionbreak_styles")},importStyleJson:function(){var e=this;this.loading=!0;var t=jQuery("#fileUpload")[0].files[0];if(t){var n=new FormData;n.append("form_id",this.form_vars.form_id),n.append("format","json"),n.append("file",t),n.append("action","fluentform_import_form_style"),n.append("fluent_forms_admin_nonce",window.fluent_forms_global_var.fluent_forms_admin_nonce),jQuery.ajax({url:window.fluent_forms_global_var.ajaxurl,type:"POST",data:n,contentType:!1,processData:!1,success:function(t){1==t.success&&location.reload(),e.loading=!1},error:function(t){var n;e.loading=!1,e.clear();var i=(null==t?void 0:t.message)||(null==t||null===(n=t.responseJSON)||void 0===n?void 0:n.message);i&&e.$fail(i)}})}else this.loading=!1},clear:function(){this.loading=!1,jQuery("#fileUpload").val("")}}},(function(){var e=this,t=e._self._c;return t("div",{directives:[{name:"loading",rawName:"v-loading",value:e.loading,expression:"loading"}],staticClass:"styler_wrapper"},[t("el-button",{staticClass:"ffs_save_settings",attrs:{type:"primary",size:"mini"},on:{click:function(t){return e.saveSettings()}}},[e._v(e._s(e.$t("Save Settings"))+"\n ")]),e._v(" "),t("el-tabs",{attrs:{type:"border-card"}},[t("el-tab-pane",{attrs:{label:e.$t("General")}},[t("div",{staticClass:"ff_form_style_selector"},[t("div",{staticClass:"ff_form_style_selector_head"},[t("div",[e._v(e._s(e.$t("Form Style Template")))]),e._v(" "),t("div",["ffs_custom"==e.preset_name?t("el-button",{attrs:{type:"default",size:"mini"},on:{click:function(t){return e.resetStyle()}}},[e._v("\n "+e._s(e.$t("Reset"))+"\n ")]):e._e(),e._v(" "),"ffs_custom"==e.preset_name?t("el-button",{attrs:{type:"info",size:"mini"},on:{click:function(t){return e.exportStyle()}}},[e._v("\n "+e._s(e.$t("Export"))+"\n ")]):e._e()],1)]),e._v(" "),t("el-select",{attrs:{placeholder:e.$t("Select Preset Styles")},on:{change:e.changePreset},model:{value:e.preset_name,callback:function(t){e.preset_name=t},expression:"preset_name"}},e._l(e.presets,(function(n,i){return t("el-option",{key:i,attrs:{value:i,label:n.label}},[e._v(e._s(n.label)+"\n ")])})),1),e._v(" "),t("div",{staticClass:"ff_form_style_selector_footer"},[e.maybeEnableCustomization&&"ffs_custom"!=e.preset_name?t("el-checkbox",{model:{value:e.customize_preset,callback:function(t){e.customize_preset=t},expression:"customize_preset"}},[e._v("\n "+e._s(e.$t("Customize Selected Preset"))+"\n ")]):e._e()],1)],1),e._v(" "),e.showCustomizer||e.customize_preset?[t("el-collapse",{attrs:{accordion:""},model:{value:e.activeName,callback:function(t){e.activeName=t},expression:"activeName"}},[t("el-collapse-item",{attrs:{title:e.$t("Label Styles"),name:"label_styles"}},[t("style-editor",{attrs:{editor_styles:e.label_styles}})],1),e._v(" "),t("el-collapse-item",{attrs:{title:e.$t("Input & Textarea"),name:"input_styles"}},[t("style-editor",{attrs:{editor_styles:e.input_styles}})],1),e._v(" "),t("el-collapse-item",{attrs:{title:e.$t("Placeholder"),name:"placeholder_styles"}},[t("style-editor",{attrs:{editor_styles:e.placeholder_styles}})],1),e._v(" "),e.has_section_break?t("el-collapse-item",{attrs:{title:e.$t("Custom Html & Section Break Style"),name:"sectionbreak_styles"}},[t("style-editor",{attrs:{editor_styles:e.sectionbreak_styles}})],1):e._e(),e._v(" "),e.has_tabular_grid?t("el-collapse-item",{attrs:{title:e.$t("Grid Table Style"),name:"gridtable_style"}},[t("style-editor",{attrs:{editor_styles:e.gridtable_style}})],1):e._e(),e._v(" "),t("el-collapse-item",{attrs:{title:e.$t("Radio & Checkbox Style"),name:"radio_checkbox_style"}},[t("style-editor",{attrs:{editor_styles:e.radio_checkbox_style}})],1),e._v(" "),e.has_range_slider?t("el-collapse-item",{attrs:{title:e.$t("Range Slider Style"),name:"range_slider_style"}},[t("style-editor",{attrs:{editor_styles:e.range_slider_style}})],1):e._e(),e._v(" "),e.has_net_promoter?t("el-collapse-item",{attrs:{title:e.$t("Net Promoter Style"),name:"net_promoter_style"}},[t("style-editor",{attrs:{editor_styles:e.net_promoter_style}})],1):e._e(),e._v(" "),e.has_payment_summary?t("el-collapse-item",{attrs:{title:e.$t("Payment Summary Style"),name:"payment_summary_style"}},[t("style-editor",{attrs:{editor_styles:e.payment_summary_style}})],1):e._e(),e._v(" "),e.has_payment_coupon?t("el-collapse-item",{attrs:{title:e.$t("Payment Coupon Style"),name:"payment_coupon_style"}},[t("style-editor",{attrs:{editor_styles:e.payment_coupon_style}})],1):e._e(),e._v(" "),e.is_multipage?[t("el-collapse-item",{attrs:{title:e.$t("Multi Page - Header Style"),name:"step_header_style"}},[t("style-editor",{attrs:{editor_styles:e.step_header_style}})],1),e._v(" "),t("el-collapse-item",{attrs:{title:e.$t("Multi Page - Next Button Style"),name:"next_button_style"}},[t("style-editor",{attrs:{editor_styles:e.next_button_style}})],1),e._v(" "),t("el-collapse-item",{attrs:{title:e.$t("Multi Page - Previous Button Style"),name:"prev_button_style"}},[t("style-editor",{attrs:{editor_styles:e.prev_button_style}})],1)]:e._e(),e._v(" "),e.has_image_or_file_button?t("el-collapse-item",{attrs:{title:e.$t("Image or File Button Style"),name:"image_or_file_button_style"}},[t("style-editor",{attrs:{editor_styles:e.image_or_file_button_style}})],1):e._e(),e._v(" "),t("el-collapse-item",{attrs:{title:e.$t("Submit Button Style"),name:"submit_button_style"}},[t("style-editor",{attrs:{editor_styles:e.submit_button_style}})],1)],2)]:e._e()],2),e._v(" "),t("el-tab-pane",{attrs:{label:e.$t("Misc")}},[t("el-collapse",{attrs:{accordion:""},model:{value:e.activeName,callback:function(t){e.activeName=t},expression:"activeName"}},[t("el-collapse-item",{attrs:{title:e.$t("Container Styles"),name:"container_styles"}},[t("style-editor",{attrs:{editor_styles:e.container_styles}})],1),e._v(" "),t("el-collapse-item",{attrs:{title:e.$t("Asterisk Styles"),name:"asterisk_styles"}},[t("style-editor",{attrs:{editor_styles:e.asterisk_styles}})],1),e._v(" "),t("el-collapse-item",{attrs:{title:e.$t("Inline Error Message Styles"),name:"help_msg_style"}},[t("style-editor",{attrs:{editor_styles:e.inline_error_msg_style}})],1),e._v(" "),t("el-collapse-item",{attrs:{title:e.$t("After Submit Success Message Styles"),name:"success_msg_style"}},[t("style-editor",{attrs:{editor_styles:e.success_msg_style}})],1),e._v(" "),t("el-collapse-item",{attrs:{title:e.$t("After Submit Error Message Styles"),name:"error_msg_style"}},[t("style-editor",{attrs:{editor_styles:e.error_msg_style}})],1)],1)],1),e._v(" "),t("el-tab-pane",{attrs:{label:e.$t("Import")}},[t("h4",[e._v(e._s(e.$t("Import Styles From Another Form")))]),e._v(" "),t("hr"),e._v(" "),t("div",{staticClass:"ff_form_style_selector"},[t("label",[e._v(e._s(e.$t("Select an Existing Form to Apply Style")))]),e._v(" "),t("el-select",{attrs:{"value-key":"form_id",placeholder:e.$t("Select Form To Apply")},on:{change:function(t){return e.importStyle()}},model:{value:e.selected_import,callback:function(t){e.selected_import=t},expression:"selected_import"}},[t("el-option-group",{key:"Custom_Styles",attrs:{label:e.$t("Custom Styles")}},e._l(e.existing_form_styles.custom,(function(e){return t("el-option",{key:e.form_id,attrs:{label:e.form_title,value:{form_id:e.form_id,type:"custom"}}})})),1),e._v(" "),t("el-option-group",{key:"general_styles",attrs:{label:e.$t("General Styles")}},e._l(e.existing_form_styles.predefined,(function(e){return t("el-option",{key:e.form_id,attrs:{label:e.form_title,value:{form_id:e.form_id,type:"predefined"}}})})),1)],1),e._v(" "),t("div",{staticClass:"overline-title-sep"},[t("span",[e._v("or")])]),e._v(" "),t("div",{staticClass:"ff_form_style_import_wrap"},[t("label",[e._v(e._s(e.$t("Import Fluent Form Style")))]),e._v(" "),t("div",{staticClass:"ff_form_style_import"},[t("input",{staticClass:"file-input",attrs:{type:"file",id:"fileUpload"},on:{click:e.clear}}),e._v(" "),t("el-button",{attrs:{type:"primary",icon:"el-icon-success",loading:e.loading},on:{click:e.importStyleJson}},[e._v("\n "+e._s(e.$t("Import"))+"\n ")])],1)])],1)])],1),e._v(" "),t("div",{attrs:{id:"ff_container_styles"}}),e._v(" "),t("div",{attrs:{id:"ff_label_styles"}}),e._v(" "),t("div",{attrs:{id:"ff_input_styles"}}),e._v(" "),t("div",{attrs:{id:"ff_placeholder_styles"}}),e._v(" "),t("div",{attrs:{id:"ff_sectionbreak_styles"}}),e._v(" "),t("div",{attrs:{id:"ff_gridtable_style"}}),e._v(" "),t("div",{attrs:{id:"ff_radio_checkbox"}}),e._v(" "),t("div",{attrs:{id:"ff_submit_button_style"}}),e._v(" "),t("div",{attrs:{id:"ff_asterisk_styles"}}),e._v(" "),t("div",{attrs:{id:"ff_inline_error_msg_style"}}),e._v(" "),t("div",{attrs:{id:"ff_success_msg_styles"}}),e._v(" "),t("div",{attrs:{id:"ff_error_msg_styles"}}),e._v(" "),t("div",{attrs:{id:"ff_next_button_style"}}),e._v(" "),t("div",{attrs:{id:"ff_prev_button_style"}}),e._v(" "),t("div",{attrs:{id:"ff_step_header_style"}}),e._v(" "),t("div",{attrs:{id:"ff_range_slider_style"}}),e._v(" "),t("div",{attrs:{id:"ff_net_promoter_score"}}),e._v(" "),t("div",{attrs:{id:"ff_payment_summary"}}),e._v(" "),t("div",{attrs:{id:"ff_payment_coupon"}}),e._v(" "),t("div",{attrs:{id:"image_or_file_button_style"}})],1)}),[],!1,null,null,null).exports;function Te(e){return Array.isArray?Array.isArray(e):"[object Array]"===De(e)}const Ee=1/0;function je(e){return null==e?"":function(e){if("string"==typeof e)return e;let t=e+"";return"0"==t&&1/e==-Ee?"-0":t}(e)}function Ie(e){return"string"==typeof e}function Pe(e){return"number"==typeof e}function Me(e){return!0===e||!1===e||function(e){return Ae(e)&&null!==e}(e)&&"[object Boolean]"==De(e)}function Ae(e){return"object"==typeof e}function Ne(e){return null!=e}function Le(e){return!e.trim().length}function De(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":Object.prototype.toString.call(e)}const Re=e=>`Missing ${e} property in key`,ze=e=>`Property 'weight' in key '${e}' must be a positive integer`,Fe=Object.prototype.hasOwnProperty;class Ve{constructor(e){this._keys=[],this._keyMap={};let t=0;e.forEach((e=>{let n=Be(e);t+=n.weight,this._keys.push(n),this._keyMap[n.id]=n,t+=n.weight})),this._keys.forEach((e=>{e.weight/=t}))}get(e){return this._keyMap[e]}keys(){return this._keys}toJSON(){return JSON.stringify(this._keys)}}function Be(e){let t=null,n=null,i=null,r=1,o=null;if(Ie(e)||Te(e))i=e,t=He(e),n=Ue(e);else{if(!Fe.call(e,"name"))throw new Error(Re("name"));const s=e.name;if(i=s,Fe.call(e,"weight")&&(r=e.weight,r<=0))throw new Error(ze(s));t=He(s),n=Ue(s),o=e.getFn}return{path:t,id:n,weight:r,src:i,getFn:o}}function He(e){return Te(e)?e:e.split(".")}function Ue(e){return Te(e)?e.join("."):e}var qe={isCaseSensitive:!1,includeScore:!1,keys:[],shouldSort:!0,sortFn:(e,t)=>e.score===t.score?e.idx{if(Ne(e))if(t[o]){const s=e[t[o]];if(!Ne(s))return;if(o===t.length-1&&(Ie(s)||Pe(s)||Me(s)))n.push(je(s));else if(Te(s)){i=!0;for(let e=0,n=s.length;e{this._keysMap[e.id]=t}))}create(){!this.isCreated&&this.docs.length&&(this.isCreated=!0,Ie(this.docs[0])?this.docs.forEach(((e,t)=>{this._addString(e,t)})):this.docs.forEach(((e,t)=>{this._addObject(e,t)})),this.norm.clear())}add(e){const t=this.size();Ie(e)?this._addString(e,t):this._addObject(e,t)}removeAt(e){this.records.splice(e,1);for(let t=e,n=this.size();t{let r=t.getFn?t.getFn(e):this.getFn(e,t.path);if(Ne(r))if(Te(r)){let e=[];const t=[{nestedArrIndex:-1,value:r}];for(;t.length;){const{nestedArrIndex:n,value:i}=t.pop();if(Ne(i))if(Ie(i)&&!Le(i)){let t={v:i,i:n,n:this.norm.get(i)};e.push(t)}else Te(i)&&i.forEach(((e,n)=>{t.push({nestedArrIndex:n,value:e})}))}n.$[i]=e}else if(Ie(r)&&!Le(r)){let e={v:r,n:this.norm.get(r)};n.$[i]=e}})),this.records.push(n)}toJSON(){return{keys:this.keys,records:this.records}}}function Xe(e,t,{getFn:n=qe.getFn,fieldNormWeight:i=qe.fieldNormWeight}={}){const r=new Ge({getFn:n,fieldNormWeight:i});return r.setKeys(e.map(Be)),r.setSources(t),r.create(),r}function Ze(e,{errors:t=0,currentLocation:n=0,expectedLocation:i=0,distance:r=qe.distance,ignoreLocation:o=qe.ignoreLocation}={}){const s=t/e.length;if(o)return s;const a=Math.abs(i-n);return r?s+a/r:a?1:s}const Ke=32;function Je(e,t,n,{location:i=qe.location,distance:r=qe.distance,threshold:o=qe.threshold,findAllMatches:s=qe.findAllMatches,minMatchCharLength:a=qe.minMatchCharLength,includeMatches:l=qe.includeMatches,ignoreLocation:c=qe.ignoreLocation}={}){if(t.length>Ke)throw new Error(`Pattern length exceeds max of ${Ke}.`);const u=t.length,d=e.length,f=Math.max(0,Math.min(i,d));let p=o,h=f;const v=a>1||l,m=v?Array(d):[];let _;for(;(_=e.indexOf(t,h))>-1;){let e=Ze(t,{currentLocation:_,expectedLocation:f,distance:r,ignoreLocation:c});if(p=Math.min(e,p),h=_+u,v){let e=0;for(;e=l;o-=1){let s=o-1,a=n[e.charAt(s)];if(v&&(m[s]=+!!a),w[o]=(w[o+1]<<1|1)&a,i&&(w[o]|=(g[o+1]|g[o])<<1|1|g[o+1]),w[o]&x&&(b=Ze(t,{errors:i,currentLocation:s,expectedLocation:f,distance:r,ignoreLocation:c}),b<=p)){if(p=b,h=s,h<=f)break;l=Math.max(1,2*f-h)}}if(Ze(t,{errors:i+1,currentLocation:f,expectedLocation:f,distance:r,ignoreLocation:c})>p)break;g=w}const w={isMatch:h>=0,score:Math.max(.001,b)};if(v){const e=function(e=[],t=qe.minMatchCharLength){let n=[],i=-1,r=-1,o=0;for(let s=e.length;o=t&&n.push([i,r]),i=-1)}return e[o-1]&&o-i>=t&&n.push([i,o-1]),n}(m,a);e.length?l&&(w.indices=e):w.isMatch=!1}return w}function Ye(e){let t={};for(let n=0,i=e.length;n{this.chunks.push({pattern:e,alphabet:Ye(e),startIndex:t})},u=this.pattern.length;if(u>Ke){let e=0;const t=u%Ke,n=u-t;for(;e{const{isMatch:h,score:v,indices:m}=Je(e,t,f,{location:i+p,distance:r,threshold:o,findAllMatches:s,minMatchCharLength:a,includeMatches:n,ignoreLocation:l});h&&(d=!0),u+=v,h&&m&&(c=[...c,...m])}));let f={isMatch:d,score:d?u/this.chunks.length:1};return d&&n&&(f.indices=c),f}}class et{constructor(e){this.pattern=e}static isMultiMatch(e){return tt(e,this.multiRegex)}static isSingleMatch(e){return tt(e,this.singleRegex)}search(){}}function tt(e,t){const n=e.match(t);return n?n[1]:null}class nt extends et{constructor(e,{location:t=qe.location,threshold:n=qe.threshold,distance:i=qe.distance,includeMatches:r=qe.includeMatches,findAllMatches:o=qe.findAllMatches,minMatchCharLength:s=qe.minMatchCharLength,isCaseSensitive:a=qe.isCaseSensitive,ignoreLocation:l=qe.ignoreLocation}={}){super(e),this._bitapSearch=new Qe(e,{location:t,threshold:n,distance:i,includeMatches:r,findAllMatches:o,minMatchCharLength:s,isCaseSensitive:a,ignoreLocation:l})}static get type(){return"fuzzy"}static get multiRegex(){return/^"(.*)"$/}static get singleRegex(){return/^(.*)$/}search(e){return this._bitapSearch.searchIn(e)}}class it extends et{constructor(e){super(e)}static get type(){return"include"}static get multiRegex(){return/^'"(.*)"$/}static get singleRegex(){return/^'(.*)$/}search(e){let t,n=0;const i=[],r=this.pattern.length;for(;(t=e.indexOf(this.pattern,n))>-1;)n=t+r,i.push([t,n-1]);const o=!!i.length;return{isMatch:o,score:o?0:1,indices:i}}}const rt=[class extends et{constructor(e){super(e)}static get type(){return"exact"}static get multiRegex(){return/^="(.*)"$/}static get singleRegex(){return/^=(.*)$/}search(e){const t=e===this.pattern;return{isMatch:t,score:t?0:1,indices:[0,this.pattern.length-1]}}},it,class extends et{constructor(e){super(e)}static get type(){return"prefix-exact"}static get multiRegex(){return/^\^"(.*)"$/}static get singleRegex(){return/^\^(.*)$/}search(e){const t=e.startsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,this.pattern.length-1]}}},class extends et{constructor(e){super(e)}static get type(){return"inverse-prefix-exact"}static get multiRegex(){return/^!\^"(.*)"$/}static get singleRegex(){return/^!\^(.*)$/}search(e){const t=!e.startsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}},class extends et{constructor(e){super(e)}static get type(){return"inverse-suffix-exact"}static get multiRegex(){return/^!"(.*)"\$$/}static get singleRegex(){return/^!(.*)\$$/}search(e){const t=!e.endsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}},class extends et{constructor(e){super(e)}static get type(){return"suffix-exact"}static get multiRegex(){return/^"(.*)"\$$/}static get singleRegex(){return/^(.*)\$$/}search(e){const t=e.endsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[e.length-this.pattern.length,e.length-1]}}},class extends et{constructor(e){super(e)}static get type(){return"inverse-exact"}static get multiRegex(){return/^!"(.*)"$/}static get singleRegex(){return/^!(.*)$/}search(e){const t=-1===e.indexOf(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}},nt],ot=rt.length,st=/ +(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/;const at=new Set([nt.type,it.type]);class lt{constructor(e,{isCaseSensitive:t=qe.isCaseSensitive,includeMatches:n=qe.includeMatches,minMatchCharLength:i=qe.minMatchCharLength,ignoreLocation:r=qe.ignoreLocation,findAllMatches:o=qe.findAllMatches,location:s=qe.location,threshold:a=qe.threshold,distance:l=qe.distance}={}){this.query=null,this.options={isCaseSensitive:t,includeMatches:n,minMatchCharLength:i,findAllMatches:o,ignoreLocation:r,location:s,threshold:a,distance:l},this.pattern=t?e:e.toLowerCase(),this.query=function(e,t={}){return e.split("|").map((e=>{let n=e.trim().split(st).filter((e=>e&&!!e.trim())),i=[];for(let e=0,r=n.length;e!(!e[dt]&&!e[ft]),mt=e=>({[dt]:Object.keys(e).map((t=>({[t]:e[t]})))});function _t(e,t,{auto:n=!0}={}){const i=e=>{let r=Object.keys(e);const o=(e=>!!e[pt])(e);if(!o&&r.length>1&&!vt(e))return i(mt(e));if((e=>!Te(e)&&Ae(e)&&!vt(e))(e)){const i=o?e[pt]:r[0],s=o?e[ht]:e[i];if(!Ie(s))throw new Error((e=>`Invalid value for key ${e}`)(i));const a={keyId:Ue(i),pattern:s};return n&&(a.searcher=ut(s,t)),a}let s={children:[],operator:r[0]};return r.forEach((t=>{const n=e[t];Te(n)&&n.forEach((e=>{s.children.push(i(e))}))})),s};return vt(e)||(e=mt(e)),i(e)}function gt(e,t){const n=e.matches;t.matches=[],Ne(n)&&n.forEach((e=>{if(!Ne(e.indices)||!e.indices.length)return;const{indices:n,value:i}=e;let r={indices:n,value:i};e.key&&(r.key=e.key.src),e.idx>-1&&(r.refIndex=e.idx),t.matches.push(r)}))}function bt(e,t){t.score=e.score}class yt{constructor(e,t={},n){this.options={...qe,...t},this.options.useExtendedSearch,this._keyStore=new Ve(this.options.keys),this.setCollection(e,n)}setCollection(e,t){if(this._docs=e,t&&!(t instanceof Ge))throw new Error("Incorrect 'index' type");this._myIndex=t||Xe(this.options.keys,this._docs,{getFn:this.options.getFn,fieldNormWeight:this.options.fieldNormWeight})}add(e){Ne(e)&&(this._docs.push(e),this._myIndex.add(e))}remove(e=(()=>!1)){const t=[];for(let n=0,i=this._docs.length;n{let n=1;e.matches.forEach((({key:e,norm:i,score:r})=>{const o=e?e.weight:null;n*=Math.pow(0===r&&o?Number.EPSILON:r,(o||1)*(t?1:i))})),e.score=n}))}(a,{ignoreFieldNorm:s}),r&&a.sort(o),Pe(t)&&t>-1&&(a=a.slice(0,t)),function(e,t,{includeMatches:n=qe.includeMatches,includeScore:i=qe.includeScore}={}){const r=[];return n&&r.push(gt),i&&r.push(bt),e.map((e=>{const{idx:n}=e,i={item:t[n],refIndex:n};return r.length&&r.forEach((t=>{t(e,i)})),i}))}(a,this._docs,{includeMatches:n,includeScore:i})}_searchStringList(e){const t=ut(e,this.options),{records:n}=this._myIndex,i=[];return n.forEach((({v:e,i:n,n:r})=>{if(!Ne(e))return;const{isMatch:o,score:s,indices:a}=t.searchIn(e);o&&i.push({item:e,idx:n,matches:[{score:s,value:e,norm:r,indices:a}]})})),i}_searchLogical(e){const t=_t(e,this.options),n=(e,t,i)=>{if(!e.children){const{keyId:n,searcher:r}=e,o=this._findMatches({key:this._keyStore.get(n),value:this._myIndex.getValueForItemAtKeyId(t,n),searcher:r});return o&&o.length?[{idx:i,item:t,matches:o}]:[]}const r=[];for(let o=0,s=e.children.length;o{if(Ne(e)){let s=n(t,e,i);s.length&&(r[i]||(r[i]={idx:i,item:e,matches:[]},o.push(r[i])),s.forEach((({matches:e})=>{r[i].matches.push(...e)})))}})),o}_searchObjectList(e){const t=ut(e,this.options),{keys:n,records:i}=this._myIndex,r=[];return i.forEach((({$:e,i})=>{if(!Ne(e))return;let o=[];n.forEach(((n,i)=>{o.push(...this._findMatches({key:n,value:e[i],searcher:t}))})),o.length&&r.push({idx:i,item:e,matches:o})})),r}_findMatches({key:e,value:t,searcher:n}){if(!Ne(t))return[];let i=[];if(Te(t))t.forEach((({v:t,i:r,n:o})=>{if(!Ne(t))return;const{isMatch:s,score:a,indices:l}=n.searchIn(t);s&&i.push({score:a,key:e,value:t,idx:r,norm:o,indices:l})}));else{const{v:r,n:o}=t,{isMatch:s,score:a,indices:l}=n.searchIn(r);s&&i.push({score:a,key:e,value:r,norm:o,indices:l})}return i}}yt.version="6.6.2",yt.createIndex=Xe,yt.parseIndex=function(e,{getFn:t=qe.getFn,fieldNormWeight:n=qe.fieldNormWeight}={}){const{keys:i,records:r}=e,o=new Ge({getFn:t,fieldNormWeight:n});return o.setKeys(i),o.setIndexRecords(r),o},yt.config=qe,yt.parseQuery=_t,function(...e){ct.push(...e)}(lt);const xt=ne({name:"global-search",data:function(){return{showSearch:!1,placeholder:"Search anything",links:[],filteredLinks:[],adminUrl:"",siteUrl:"",linkFocusIndex:0,loading:!0,fuse:{}}},methods:{getSearchData:function(){var e=this,t=FluentFormsGlobal.$rest.route("globalSearch");FluentFormsGlobal.$rest.get(t).then((function(t){e.adminUrl=t.admin_url,e.siteUrl=t.site_url,e.links=t.links,e.fuse=new yt(e.links,{minMatchCharLength:2,threshold:.4,keys:["title","tags"]}),e.filteredLinks=e.links.slice(0,7)})).catch((function(e){console.log(e)})).finally((function(){e.loading=!1}))},search:function(e){var t,n;this.linkFocusIndex=0,this.filteredLinks=e&&(null===(t=(n=this.fuse).search)||void 0===t?void 0:t.call(n,e,{limit:50}))||this.links.slice(0,7)},reset:function(){this.showSearch&&(this.showSearch=!1),this.linkFocusIndex=0},goToSlug:function(e,t){var n=new URL(window.location);t.type&&"preview"===t.type?window.location.href=this.siteUrl+"/"+t.path:(window.location.href=this.adminUrl+t.path,this.shouldReload(t,n)&&window.location.reload())},shouldReload:function(e,t){var n=new URL(e.path,this.adminUrl),i=t.searchParams.get("page"),r=n.searchParams.get("page"),o=t.searchParams.get("component"),s=n.searchParams.get("component"),a=t.searchParams.get("form_id"),l=n.searchParams.get("form_id"),c=t.searchParams.get("route"),u=n.searchParams.get("route"),d=t.hash,f=n.hash;return r===i&&((!a&&!l||a===l)&&(!(!c&&!u||c!==u)||(!(!o&&!s||o!==s)||!(o||s||!d&&!f||d===f))))},listener:function(e){var t,n=this;if(((null===(t=window)||void 0===t||null===(t=t.navigator.userAgent)||void 0===t?void 0:t.toUpperCase().includes("MAC"))?e.metaKey:e.ctrlKey)&&75===e.keyCode){if(e.preventDefault&&e.preventDefault(),this.showSearch)return void this.reset();this.showSearch=!0,setTimeout((function(){var e;null===(e=n.$refs.searchInput)||void 0===e||e.focus()}),500),this.links.length||this.getSearchData()}if(this.showSearch)if(27===e.keyCode)e.preventDefault(),this.reset();else if(38===e.keyCode||40===e.keyCode)e.preventDefault(),this.handleUpDownArrow(e);else if(9===e.keyCode){var i;e.preventDefault(),null===(i=this.$refs.searchInput)||void 0===i||i.focus(),this.linkFocusIndex=0}else if(13===e.keyCode&&this.filteredLinks.length){var r=this.filteredLinks[this.linkFocusIndex];r&&this.goToSlug(void 0,r.item||r)}},handleUpDownArrow:function(e){if(this.$refs.links&&Array.isArray(this.$refs.links)){var t,n,i;if(38===e.keyCode?this.linkFocusIndex-=1:this.linkFocusIndex+=1,this.linkFocusIndex>=this.filteredLinks.length||this.linkFocusIndex<=0)return null===(t=this.$refs.searchInput)||void 0===t||t.focus(),null===(n=this.$refs.searchBody)||void 0===n||null===(i=n.scroll)||void 0===i||i.call(n,{top:0}),void(this.linkFocusIndex=0);var r=this.$refs.links[this.linkFocusIndex-1];r&&this.$nextTick((function(){r.focus()}))}}},created:function(){var e,t=this;"yes"===(null===(e=window.fluent_forms_global_var)||void 0===e?void 0:e.global_search_active)&&(document.addEventListener("keydown",this.listener),document.addEventListener("global-search-menu-button-click",(function(e){t.listener({ctrlKey:!0,metaKey:!0,keyCode:75})})))},beforeDestroy:function(){document.removeEventListener("keydown",this.listener)}},(function(){var e=this,t=e._self._c;return e.showSearch?t("div",{staticClass:"global-search-wrapper",on:{click:e.reset}},[t("div",{directives:[{name:"loading",rawName:"v-loading",value:e.loading,expression:"loading"}],staticClass:"global-search-container",on:{click:function(e){e.stopPropagation()}}},[t("div",{ref:"searchBody",staticClass:"global-search-body"},[t("div",{staticClass:"el-input el-input--prefix"},[t("input",{ref:"searchInput",attrs:{"prefix-icon":"el-icon-search",type:"text",name:"search",placeholder:e.$t(e.placeholder),autocomplete:"off"},on:{input:function(t){return e.search(t.target.value)}}}),e._v(" "),e._m(0)]),e._v(" "),t("ul",{staticClass:"search-result"},[this.filteredLinks.length?e._l(e.filteredLinks,(function(n,i){var r;return t("li",{key:"link_"+i,ref:"links",refInFor:!0,class:{"active-search-link":e.linkFocusIndex===i},attrs:{tabindex:"1"},on:{click:function(t){return e.goToSlug(t,n.item||n)}}},[t("span",[e._v(e._s((null===(r=n.item)||void 0===r?void 0:r.title)||n.title))])])})):t("li",[t("span",[e._v(e._s(e.$t("Search not match. Try a different query.")))])])],2)]),e._v(" "),t("div",[t("ul",{staticClass:"search-commands"},[t("li",[e._v(e._s(e.$t("Esc to close")))]),e._v(" "),t("li",[e._v("\n "+e._s(e.$t("Navigate"))+"\n "),t("i",{staticClass:"el-icon-bottom"}),e._v(" "),t("i",{staticClass:"el-icon-top"})]),e._v(" "),t("li",[e._v(e._s(e.$t("Tab to focus search")))]),e._v(" "),t("li",[e._v(e._s(e.$t("Enter to Select")))])])])])]):e._e()}),[function(){var e=this._self._c;return e("span",{staticClass:"el-input__prefix"},[e("i",{staticClass:"el-input__icon el-icon-search"})])}],!1,null,null,null).exports;Z.default.use(X().directive),Z.default.prototype.$loading=X().service,Z.default.prototype.$message=W(),Z.default.prototype.$notify=U(),Z.default.use(B()),Z.default.use(F()),Z.default.use(R()),Z.default.use(L()),Z.default.use(A()),Z.default.use(P()),Z.default.use(j()),Z.default.use(T()),Z.default.use($()),Z.default.use(S()),Z.default.use(w()),Z.default.use(y()),Z.default.use(g()),Z.default.use(m()),Z.default.use(h()),Z.default.use(f()),Z.default.use(u()),Z.default.use(l()),Z.default.use(s()),Z.default.use(r()),K.default.use(J.Z),Z.default.mixin({methods:{$t:function(e){var t=window.fluent_styler_vars.styler_str[e];return t||e}}}),new Z.default({el:"#ff_form_styler",components:{"ff-styler-app":Oe,globalSearch:xt},data:{form_vars:window.fluent_styler_vars}})},47065:(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";function _typeof(e){return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},_typeof(e)}function ownKeys(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function _objectSpread(e){for(var t=1;tresetWithDefault,GH:()=>TabPart,Il:()=>Color,OC:()=>Border,Xd:()=>BackgroundImage,ZT:()=>Typography,Zh:()=>Padding,Zt:()=>Margin,Zw:()=>UnitValue,i6:()=>Boxshadow,lP:()=>BackgroundColor,wU:()=>AroundItem});var AroundItem=_createClass((function e(){_classCallCheck(this,e),this.type="px",this.top="",this.left="",this.right="",this.bottom="",this.linked="yes"})),TypeValue=_createClass((function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"px";_classCallCheck(this,e),this.type=n,this.value=t})),Color=_createClass((function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"color",n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"Color",i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";_classCallCheck(this,e),this.label=n,this.key=t,this.element="ff_color",this.value=i})),UnitValue=_createClass((function e(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};_classCallCheck(this,e),this.key=t,this.label=n,this.element="ff_unit_value",i.units&&(this.units=i.units),i.config&&(this.config=i.config),this.value=new TypeValue(i.value||"",i.type||"px")})),BackgroundColor=_createClass((function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"backgroundColor",n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"Background Color",i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";_classCallCheck(this,e),this.label=n,this.key=t,this.element="ff_color",this.value=i})),BackgroundImage=_createClass((function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"backgroundImage",n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"Background Image";_classCallCheck(this,e),this.label=n,this.key=t,this.element="ff_background_image",this.value={type:"classic",image:{url:"",position:{value:"",valueX:new TypeValue,valueY:new TypeValue},size:{value:"",valueX:new TypeValue,valueY:new TypeValue},attachment:"",repeat:""},gradient:{type:"radial",position:"center center",angle:new TypeValue(0,"deg"),primary:{color:"",location:new TypeValue(50,"%")},secondary:{color:"",location:new TypeValue(50,"%")}}}})),Padding=_createClass((function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"padding",n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"Padding";_classCallCheck(this,e),this.label=n,this.element="ff_around_item",this.key=t,this.value=new AroundItem,this.type="px"})),Margin=_createClass((function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"margin",n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"Margin";_classCallCheck(this,e),this.label=n,this.element="ff_around_item",this.key=t,this.value=new AroundItem,this.type="px"})),Border=_createClass((function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"border",n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"Border",i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"Custom Border",r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};_classCallCheck(this,e),this.label=n,this.key=t,this.status_label=i,this.element="ff_border_config",this.value=_objectSpread({border_radius:new AroundItem,border_width:new AroundItem,border_type:"solid",border_color:"",status:""},r),this.type="px"})),Typography=_createClass((function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"typography",n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"Typography";_classCallCheck(this,e),this.label=n,this.key=t,this.element="ff_typography",this.value={fontSize:{type:"px",value:""},fontWeight:"",transform:"",fontStyle:"",textDecoration:"",lineHeight:{type:"px",value:""},letterSpacing:{type:"px",value:""},wordSpacing:{type:"px",value:""}}})),Boxshadow=_createClass((function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"boxshadow",n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"Box Shadow",i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};_classCallCheck(this,e),this.key=t,this.element="ff_boxshadow_config",this.label=n,this.value=_objectSpread({horizontal:{type:"px",value:"0"},vertical:{type:"px",value:"0"},blur:{type:"px",value:"0"},spread:{type:"px",value:"0"},color:"",position:""},i)})),TabPart=_createClass((function TabPart(key,label){var _this=this,newValue=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},replaceExisting=arguments.length>3&&void 0!==arguments[3]&&arguments[3];_classCallCheck(this,TabPart),this.key=key,this.label=label,Array.isArray(newValue)?(this.value={},newValue.forEach((function(prop){var className=prop.charAt(0).toUpperCase()+prop.slice(1);try{_this.value[prop]=eval("new ".concat(className,"()"))}catch(e){}}))):this.value=_objectSpread(_objectSpread({color:new Color,backgroundColor:new BackgroundColor},newValue),{},{typography:new Typography,boxshadow:new Boxshadow,border:new Border}),replaceExisting&&(this.value=_objectSpread(_objectSpread({},this.value),replaceExisting))}));function resetWithDefault(e,t){for(var n in t){var i=t[n];if("object"!==_typeof(i)&&void 0!==e[n])e[n]=i;else if(void 0!==e[n])for(var r in i)"object"!==_typeof(r)&&void 0!==e[n][r]&&(e[n][r]=i[r])}}},9996:e=>{"use strict";var t=function(e){return function(e){return!!e&&"object"==typeof e}(e)&&!function(e){var t=Object.prototype.toString.call(e);return"[object RegExp]"===t||"[object Date]"===t||function(e){return e.$$typeof===n}(e)}(e)};var n="function"==typeof Symbol&&Symbol.for?Symbol.for("react.element"):60103;function i(e,n){var i;return n&&!0===n.clone&&t(e)?o((i=e,Array.isArray(i)?[]:{}),e,n):e}function r(e,n,r){var s=e.slice();return n.forEach((function(n,a){void 0===s[a]?s[a]=i(n,r):t(n)?s[a]=o(e[a],n,r):-1===e.indexOf(n)&&s.push(i(n,r))})),s}function o(e,n,s){var a=Array.isArray(n);return a===Array.isArray(e)?a?((s||{arrayMerge:r}).arrayMerge||r)(e,n,s):function(e,n,r){var s={};return t(e)&&Object.keys(e).forEach((function(t){s[t]=i(e[t],r)})),Object.keys(n).forEach((function(a){t(n[a])&&e[a]?s[a]=o(e[a],n[a],r):s[a]=i(n[a],r)})),s}(e,n,s):i(n,s)}o.all=function(e,t){if(!Array.isArray(e)||e.length<2)throw new Error("first argument should be an array with at least two elements");return e.reduce((function(e,n){return o(e,n,t)}))};var s=o;e.exports=s},87563:e=>{e.exports=function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist/",n(n.s=97)}({0:function(e,t,n){"use strict";function i(e,t,n,i,r,o,s,a){var l,c="function"==typeof e?e.options:e;if(t&&(c.render=t,c.staticRenderFns=n,c._compiled=!0),i&&(c.functional=!0),o&&(c._scopeId="data-v-"+o),s?(l=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),r&&r.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(s)},c._ssrRegister=l):r&&(l=a?function(){r.call(this,this.$root.$options.shadowRoot)}:r),l)if(c.functional){c._injectStyles=l;var u=c.render;c.render=function(e,t){return l.call(t),u(e,t)}}else{var d=c.beforeCreate;c.beforeCreate=d?[].concat(d,l):[l]}return{exports:e,options:c}}n.d(t,"a",(function(){return i}))},97:function(e,t,n){"use strict";n.r(t);var i=function(){var e=this,t=e.$createElement;return(e._self._c||t)("div",{staticClass:"el-button-group"},[e._t("default")],2)};i._withStripped=!0;var r={name:"ElButtonGroup"},o=n(0),s=Object(o.a)(r,i,[],!1,null,null,null);s.options.__file="packages/button/src/button-group.vue";var a=s.exports;a.install=function(e){e.component(a.name,a)};t.default=a}})},26426:e=>{e.exports=function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist/",n(n.s=96)}({0:function(e,t,n){"use strict";function i(e,t,n,i,r,o,s,a){var l,c="function"==typeof e?e.options:e;if(t&&(c.render=t,c.staticRenderFns=n,c._compiled=!0),i&&(c.functional=!0),o&&(c._scopeId="data-v-"+o),s?(l=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),r&&r.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(s)},c._ssrRegister=l):r&&(l=a?function(){r.call(this,this.$root.$options.shadowRoot)}:r),l)if(c.functional){c._injectStyles=l;var u=c.render;c.render=function(e,t){return l.call(t),u(e,t)}}else{var d=c.beforeCreate;c.beforeCreate=d?[].concat(d,l):[l]}return{exports:e,options:c}}n.d(t,"a",(function(){return i}))},96:function(e,t,n){"use strict";n.r(t);var i=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("button",{staticClass:"el-button",class:[e.type?"el-button--"+e.type:"",e.buttonSize?"el-button--"+e.buttonSize:"",{"is-disabled":e.buttonDisabled,"is-loading":e.loading,"is-plain":e.plain,"is-round":e.round,"is-circle":e.circle}],attrs:{disabled:e.buttonDisabled||e.loading,autofocus:e.autofocus,type:e.nativeType},on:{click:e.handleClick}},[e.loading?n("i",{staticClass:"el-icon-loading"}):e._e(),e.icon&&!e.loading?n("i",{class:e.icon}):e._e(),e.$slots.default?n("span",[e._t("default")],2):e._e()])};i._withStripped=!0;var r={name:"ElButton",inject:{elForm:{default:""},elFormItem:{default:""}},props:{type:{type:String,default:"default"},size:String,icon:{type:String,default:""},nativeType:{type:String,default:"button"},loading:Boolean,disabled:Boolean,plain:Boolean,autofocus:Boolean,round:Boolean,circle:Boolean},computed:{_elFormItemSize:function(){return(this.elFormItem||{}).elFormItemSize},buttonSize:function(){return this.size||this._elFormItemSize||(this.$ELEMENT||{}).size},buttonDisabled:function(){return this.$options.propsData.hasOwnProperty("disabled")?this.disabled:(this.elForm||{}).disabled}},methods:{handleClick:function(e){this.$emit("click",e)}}},o=n(0),s=Object(o.a)(r,i,[],!1,null,null,null);s.options.__file="packages/button/src/button.vue";var a=s.exports;a.install=function(e){e.component(a.name,a)};t.default=a}})},82626:(e,t,n)=>{e.exports=function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist/",n(n.s=91)}({0:function(e,t,n){"use strict";function i(e,t,n,i,r,o,s,a){var l,c="function"==typeof e?e.options:e;if(t&&(c.render=t,c.staticRenderFns=n,c._compiled=!0),i&&(c.functional=!0),o&&(c._scopeId="data-v-"+o),s?(l=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),r&&r.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(s)},c._ssrRegister=l):r&&(l=a?function(){r.call(this,this.$root.$options.shadowRoot)}:r),l)if(c.functional){c._injectStyles=l;var u=c.render;c.render=function(e,t){return l.call(t),u(e,t)}}else{var d=c.beforeCreate;c.beforeCreate=d?[].concat(d,l):[l]}return{exports:e,options:c}}n.d(t,"a",(function(){return i}))},4:function(e,t){e.exports=n(52477)},91:function(e,t,n){"use strict";n.r(t);var i=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("label",{staticClass:"el-checkbox",class:[e.border&&e.checkboxSize?"el-checkbox--"+e.checkboxSize:"",{"is-disabled":e.isDisabled},{"is-bordered":e.border},{"is-checked":e.isChecked}],attrs:{id:e.id}},[n("span",{staticClass:"el-checkbox__input",class:{"is-disabled":e.isDisabled,"is-checked":e.isChecked,"is-indeterminate":e.indeterminate,"is-focus":e.focus},attrs:{tabindex:!!e.indeterminate&&0,role:!!e.indeterminate&&"checkbox","aria-checked":!!e.indeterminate&&"mixed"}},[n("span",{staticClass:"el-checkbox__inner"}),e.trueLabel||e.falseLabel?n("input",{directives:[{name:"model",rawName:"v-model",value:e.model,expression:"model"}],staticClass:"el-checkbox__original",attrs:{type:"checkbox","aria-hidden":e.indeterminate?"true":"false",name:e.name,disabled:e.isDisabled,"true-value":e.trueLabel,"false-value":e.falseLabel},domProps:{checked:Array.isArray(e.model)?e._i(e.model,null)>-1:e._q(e.model,e.trueLabel)},on:{change:[function(t){var n=e.model,i=t.target,r=i.checked?e.trueLabel:e.falseLabel;if(Array.isArray(n)){var o=e._i(n,null);i.checked?o<0&&(e.model=n.concat([null])):o>-1&&(e.model=n.slice(0,o).concat(n.slice(o+1)))}else e.model=r},e.handleChange],focus:function(t){e.focus=!0},blur:function(t){e.focus=!1}}}):n("input",{directives:[{name:"model",rawName:"v-model",value:e.model,expression:"model"}],staticClass:"el-checkbox__original",attrs:{type:"checkbox","aria-hidden":e.indeterminate?"true":"false",disabled:e.isDisabled,name:e.name},domProps:{value:e.label,checked:Array.isArray(e.model)?e._i(e.model,e.label)>-1:e.model},on:{change:[function(t){var n=e.model,i=t.target,r=!!i.checked;if(Array.isArray(n)){var o=e.label,s=e._i(n,o);i.checked?s<0&&(e.model=n.concat([o])):s>-1&&(e.model=n.slice(0,s).concat(n.slice(s+1)))}else e.model=r},e.handleChange],focus:function(t){e.focus=!0},blur:function(t){e.focus=!1}}})]),e.$slots.default||e.label?n("span",{staticClass:"el-checkbox__label"},[e._t("default"),e.$slots.default?e._e():[e._v(e._s(e.label))]],2):e._e()])};i._withStripped=!0;var r=n(4),o={name:"ElCheckbox",mixins:[n.n(r).a],inject:{elForm:{default:""},elFormItem:{default:""}},componentName:"ElCheckbox",data:function(){return{selfModel:!1,focus:!1,isLimitExceeded:!1}},computed:{model:{get:function(){return this.isGroup?this.store:void 0!==this.value?this.value:this.selfModel},set:function(e){this.isGroup?(this.isLimitExceeded=!1,void 0!==this._checkboxGroup.min&&e.lengththis._checkboxGroup.max&&(this.isLimitExceeded=!0),!1===this.isLimitExceeded&&this.dispatch("ElCheckboxGroup","input",[e])):(this.$emit("input",e),this.selfModel=e)}},isChecked:function(){return"[object Boolean]"==={}.toString.call(this.model)?this.model:Array.isArray(this.model)?this.model.indexOf(this.label)>-1:null!==this.model&&void 0!==this.model?this.model===this.trueLabel:void 0},isGroup:function(){for(var e=this.$parent;e;){if("ElCheckboxGroup"===e.$options.componentName)return this._checkboxGroup=e,!0;e=e.$parent}return!1},store:function(){return this._checkboxGroup?this._checkboxGroup.value:this.value},isLimitDisabled:function(){var e=this._checkboxGroup,t=e.max,n=e.min;return!(!t&&!n)&&this.model.length>=t&&!this.isChecked||this.model.length<=n&&this.isChecked},isDisabled:function(){return this.isGroup?this._checkboxGroup.disabled||this.disabled||(this.elForm||{}).disabled||this.isLimitDisabled:this.disabled||(this.elForm||{}).disabled},_elFormItemSize:function(){return(this.elFormItem||{}).elFormItemSize},checkboxSize:function(){var e=this.size||this._elFormItemSize||(this.$ELEMENT||{}).size;return this.isGroup&&this._checkboxGroup.checkboxGroupSize||e}},props:{value:{},label:{},indeterminate:Boolean,disabled:Boolean,checked:Boolean,name:String,trueLabel:[String,Number],falseLabel:[String,Number],id:String,controls:String,border:Boolean,size:String},methods:{addToStore:function(){Array.isArray(this.model)&&-1===this.model.indexOf(this.label)?this.model.push(this.label):this.model=this.trueLabel||!0},handleChange:function(e){var t=this;if(!this.isLimitExceeded){var n=void 0;n=e.target.checked?void 0===this.trueLabel||this.trueLabel:void 0!==this.falseLabel&&this.falseLabel,this.$emit("change",n,e),this.$nextTick((function(){t.isGroup&&t.dispatch("ElCheckboxGroup","change",[t._checkboxGroup.value])}))}}},created:function(){this.checked&&this.addToStore()},mounted:function(){this.indeterminate&&this.$el.setAttribute("aria-controls",this.controls)},watch:{value:function(e){this.dispatch("ElFormItem","el.form.change",e)}}},s=n(0),a=Object(s.a)(o,i,[],!1,null,null,null);a.options.__file="packages/checkbox/src/checkbox.vue";var l=a.exports;l.install=function(e){e.component(l.name,l)};t.default=l}})},71937:(e,t,n)=>{e.exports=function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist/",n(n.s=114)}({0:function(e,t,n){"use strict";function i(e,t,n,i,r,o,s,a){var l,c="function"==typeof e?e.options:e;if(t&&(c.render=t,c.staticRenderFns=n,c._compiled=!0),i&&(c.functional=!0),o&&(c._scopeId="data-v-"+o),s?(l=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),r&&r.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(s)},c._ssrRegister=l):r&&(l=a?function(){r.call(this,this.$root.$options.shadowRoot)}:r),l)if(c.functional){c._injectStyles=l;var u=c.render;c.render=function(e,t){return l.call(t),u(e,t)}}else{var d=c.beforeCreate;c.beforeCreate=d?[].concat(d,l):[l]}return{exports:e,options:c}}n.d(t,"a",(function(){return i}))},114:function(e,t,n){"use strict";n.r(t);var i=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"el-collapse-item",class:{"is-active":e.isActive,"is-disabled":e.disabled}},[n("div",{attrs:{role:"tab","aria-expanded":e.isActive,"aria-controls":"el-collapse-content-"+e.id,"aria-describedby":"el-collapse-content-"+e.id}},[n("div",{staticClass:"el-collapse-item__header",class:{focusing:e.focusing,"is-active":e.isActive},attrs:{role:"button",id:"el-collapse-head-"+e.id,tabindex:e.disabled?void 0:0},on:{click:e.handleHeaderClick,keyup:function(t){return!("button"in t)&&e._k(t.keyCode,"space",32,t.key,[" ","Spacebar"])&&e._k(t.keyCode,"enter",13,t.key,"Enter")?null:(t.stopPropagation(),e.handleEnterClick(t))},focus:e.handleFocus,blur:function(t){e.focusing=!1}}},[e._t("title",[e._v(e._s(e.title))]),n("i",{staticClass:"el-collapse-item__arrow el-icon-arrow-right",class:{"is-active":e.isActive}})],2)]),n("el-collapse-transition",[n("div",{directives:[{name:"show",rawName:"v-show",value:e.isActive,expression:"isActive"}],staticClass:"el-collapse-item__wrap",attrs:{role:"tabpanel","aria-hidden":!e.isActive,"aria-labelledby":"el-collapse-head-"+e.id,id:"el-collapse-content-"+e.id}},[n("div",{staticClass:"el-collapse-item__content"},[e._t("default")],2)])])],1)};i._withStripped=!0;var r=n(28),o=n.n(r),s=n(4),a=n.n(s),l=n(3),c={name:"ElCollapseItem",componentName:"ElCollapseItem",mixins:[a.a],components:{ElCollapseTransition:o.a},data:function(){return{contentWrapStyle:{height:"auto",display:"block"},contentHeight:0,focusing:!1,isClick:!1,id:Object(l.generateId)()}},inject:["collapse"],props:{title:String,name:{type:[String,Number],default:function(){return this._uid}},disabled:Boolean},computed:{isActive:function(){return this.collapse.activeNames.indexOf(this.name)>-1}},methods:{handleFocus:function(){var e=this;setTimeout((function(){e.isClick?e.isClick=!1:e.focusing=!0}),50)},handleHeaderClick:function(){this.disabled||(this.dispatch("ElCollapse","item-click",this),this.focusing=!1,this.isClick=!0)},handleEnterClick:function(){this.dispatch("ElCollapse","item-click",this)}}},u=n(0),d=Object(u.a)(c,i,[],!1,null,null,null);d.options.__file="packages/collapse/src/collapse-item.vue";var f=d.exports;f.install=function(e){e.component(f.name,f)};t.default=f},28:function(e,t){e.exports=n(32743)},3:function(e,t){e.exports=n(93104)},4:function(e,t){e.exports=n(52477)}})},22428:e=>{e.exports=function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist/",n(n.s=113)}({0:function(e,t,n){"use strict";function i(e,t,n,i,r,o,s,a){var l,c="function"==typeof e?e.options:e;if(t&&(c.render=t,c.staticRenderFns=n,c._compiled=!0),i&&(c.functional=!0),o&&(c._scopeId="data-v-"+o),s?(l=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),r&&r.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(s)},c._ssrRegister=l):r&&(l=a?function(){r.call(this,this.$root.$options.shadowRoot)}:r),l)if(c.functional){c._injectStyles=l;var u=c.render;c.render=function(e,t){return l.call(t),u(e,t)}}else{var d=c.beforeCreate;c.beforeCreate=d?[].concat(d,l):[l]}return{exports:e,options:c}}n.d(t,"a",(function(){return i}))},113:function(e,t,n){"use strict";n.r(t);var i=function(){var e=this,t=e.$createElement;return(e._self._c||t)("div",{staticClass:"el-collapse",attrs:{role:"tablist","aria-multiselectable":"true"}},[e._t("default")],2)};i._withStripped=!0;var r={name:"ElCollapse",componentName:"ElCollapse",props:{accordion:Boolean,value:{type:[Array,String,Number],default:function(){return[]}}},data:function(){return{activeNames:[].concat(this.value)}},provide:function(){return{collapse:this}},watch:{value:function(e){this.activeNames=[].concat(e)}},methods:{setActiveNames:function(e){e=[].concat(e);var t=this.accordion?e[0]:e;this.activeNames=e,this.$emit("input",t),this.$emit("change",t)},handleItemClick:function(e){if(this.accordion)this.setActiveNames(!this.activeNames[0]&&0!==this.activeNames[0]||this.activeNames[0]!==e.name?e.name:"");else{var t=this.activeNames.slice(0),n=t.indexOf(e.name);n>-1?t.splice(n,1):t.push(e.name),this.setActiveNames(t)}}},created:function(){this.$on("item-click",this.handleItemClick)}},o=n(0),s=Object(o.a)(r,i,[],!1,null,null,null);s.options.__file="packages/collapse/src/collapse.vue";var a=s.exports;a.install=function(e){e.component(a.name,a)};t.default=a}})},62618:(e,t,n)=>{e.exports=function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist/",n(n.s=55)}({0:function(e,t,n){"use strict";function i(e,t,n,i,r,o,s,a){var l,c="function"==typeof e?e.options:e;if(t&&(c.render=t,c.staticRenderFns=n,c._compiled=!0),i&&(c.functional=!0),o&&(c._scopeId="data-v-"+o),s?(l=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),r&&r.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(s)},c._ssrRegister=l):r&&(l=a?function(){r.call(this,this.$root.$options.shadowRoot)}:r),l)if(c.functional){c._injectStyles=l;var u=c.render;c.render=function(e,t){return l.call(t),u(e,t)}}else{var d=c.beforeCreate;c.beforeCreate=d?[].concat(d,l):[l]}return{exports:e,options:c}}n.d(t,"a",(function(){return i}))},10:function(e,t){e.exports=n(7626)},12:function(e,t){e.exports=n(1080)},14:function(e,t){e.exports=n(26426)},4:function(e,t){e.exports=n(52477)},5:function(e,t){e.exports=n(70499)},55:function(e,t,n){"use strict";n.r(t);var i=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{directives:[{name:"clickoutside",rawName:"v-clickoutside",value:e.hide,expression:"hide"}],class:["el-color-picker",e.colorDisabled?"is-disabled":"",e.colorSize?"el-color-picker--"+e.colorSize:""]},[e.colorDisabled?n("div",{staticClass:"el-color-picker__mask"}):e._e(),n("div",{staticClass:"el-color-picker__trigger",on:{click:e.handleTrigger}},[n("span",{staticClass:"el-color-picker__color",class:{"is-alpha":e.showAlpha}},[n("span",{staticClass:"el-color-picker__color-inner",style:{backgroundColor:e.displayedColor}}),e.value||e.showPanelColor?e._e():n("span",{staticClass:"el-color-picker__empty el-icon-close"})]),n("span",{directives:[{name:"show",rawName:"v-show",value:e.value||e.showPanelColor,expression:"value || showPanelColor"}],staticClass:"el-color-picker__icon el-icon-arrow-down"})]),n("picker-dropdown",{ref:"dropdown",class:["el-color-picker__panel",e.popperClass||""],attrs:{color:e.color,"show-alpha":e.showAlpha,predefine:e.predefine},on:{pick:e.confirmValue,clear:e.clearValue},model:{value:e.showPicker,callback:function(t){e.showPicker=t},expression:"showPicker"}})],1)};i._withStripped=!0;var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};var o=function(e,t,n){return[e,t*n/((e=(2-t)*n)<1?e:2-e)||0,e/2]},s=function(e,t){var n;"string"==typeof(n=e)&&-1!==n.indexOf(".")&&1===parseFloat(n)&&(e="100%");var i=function(e){return"string"==typeof e&&-1!==e.indexOf("%")}(e);return e=Math.min(t,Math.max(0,parseFloat(e))),i&&(e=parseInt(e*t,10)/100),Math.abs(e-t)<1e-6?1:e%t/parseFloat(t)},a={10:"A",11:"B",12:"C",13:"D",14:"E",15:"F"},l={A:10,B:11,C:12,D:13,E:14,F:15},c=function(e){return 2===e.length?16*(l[e[0].toUpperCase()]||+e[0])+(l[e[1].toUpperCase()]||+e[1]):l[e[1].toUpperCase()]||+e[1]},u=function(e,t,n){e=s(e,255),t=s(t,255),n=s(n,255);var i,r=Math.max(e,t,n),o=Math.min(e,t,n),a=void 0,l=r,c=r-o;if(i=0===r?0:c/r,r===o)a=0;else{switch(r){case e:a=(t-n)/c+(t2?parseFloat(e):parseInt(e,10)}));if(4===i.length?this._alpha=Math.floor(100*parseFloat(i[3])):3===i.length&&(this._alpha=100),i.length>=3){var r=function(e,t,n){n/=100;var i=t/=100,r=Math.max(n,.01);return t*=(n*=2)<=1?n:2-n,i*=r<=1?r:2-r,{h:e,s:100*(0===n?2*i/(r+i):2*t/(n+t)),v:(n+t)/2*100}}(i[0],i[1],i[2]);n(r.h,r.s,r.v)}}else if(-1!==e.indexOf("hsv")){var o=e.replace(/hsva|hsv|\(|\)/gm,"").split(/\s|,/g).filter((function(e){return""!==e})).map((function(e,t){return t>2?parseFloat(e):parseInt(e,10)}));4===o.length?this._alpha=Math.floor(100*parseFloat(o[3])):3===o.length&&(this._alpha=100),o.length>=3&&n(o[0],o[1],o[2])}else if(-1!==e.indexOf("rgb")){var s=e.replace(/rgba|rgb|\(|\)/gm,"").split(/\s|,/g).filter((function(e){return""!==e})).map((function(e,t){return t>2?parseFloat(e):parseInt(e,10)}));if(4===s.length?this._alpha=Math.floor(100*parseFloat(s[3])):3===s.length&&(this._alpha=100),s.length>=3){var a=u(s[0],s[1],s[2]);n(a.h,a.s,a.v)}}else if(-1!==e.indexOf("#")){var l=e.replace("#","").trim();if(!/^(?:[0-9a-fA-F]{3}){1,2}|[0-9a-fA-F]{8}$/.test(l))return;var d=void 0,f=void 0,p=void 0;3===l.length?(d=c(l[0]+l[0]),f=c(l[1]+l[1]),p=c(l[2]+l[2])):6!==l.length&&8!==l.length||(d=c(l.substring(0,2)),f=c(l.substring(2,4)),p=c(l.substring(4,6))),8===l.length?this._alpha=Math.floor(c(l.substring(6))/255*100):3!==l.length&&6!==l.length||(this._alpha=100);var h=u(d,f,p);n(h.h,h.s,h.v)}},e.prototype.compare=function(e){return Math.abs(e._hue-this._hue)<2&&Math.abs(e._saturation-this._saturation)<1&&Math.abs(e._value-this._value)<1&&Math.abs(e._alpha-this._alpha)<1},e.prototype.doOnChange=function(){var e=this._hue,t=this._saturation,n=this._value,i=this._alpha,r=this.format;if(this.enableAlpha)switch(r){case"hsl":var s=o(e,t/100,n/100);this.value="hsla("+e+", "+Math.round(100*s[1])+"%, "+Math.round(100*s[2])+"%, "+i/100+")";break;case"hsv":this.value="hsva("+e+", "+Math.round(t)+"%, "+Math.round(n)+"%, "+i/100+")";break;default:var l=d(e,t,n),c=l.r,u=l.g,f=l.b;this.value="rgba("+c+", "+u+", "+f+", "+i/100+")"}else switch(r){case"hsl":var p=o(e,t/100,n/100);this.value="hsl("+e+", "+Math.round(100*p[1])+"%, "+Math.round(100*p[2])+"%)";break;case"hsv":this.value="hsv("+e+", "+Math.round(t)+"%, "+Math.round(n)+"%)";break;case"rgb":var h=d(e,t,n),v=h.r,m=h.g,_=h.b;this.value="rgb("+v+", "+m+", "+_+")";break;default:this.value=function(e){var t=e.r,n=e.g,i=e.b,r=function(e){e=Math.min(Math.round(e),255);var t=Math.floor(e/16),n=e%16;return""+(a[t]||t)+(a[n]||n)};return isNaN(t)||isNaN(n)||isNaN(i)?"":"#"+r(t)+r(n)+r(i)}(d(e,t,n))}},e}(),p=f,h=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("transition",{attrs:{name:"el-zoom-in-top"},on:{"after-leave":e.doDestroy}},[n("div",{directives:[{name:"show",rawName:"v-show",value:e.showPopper,expression:"showPopper"}],staticClass:"el-color-dropdown"},[n("div",{staticClass:"el-color-dropdown__main-wrapper"},[n("hue-slider",{ref:"hue",staticStyle:{float:"right"},attrs:{color:e.color,vertical:""}}),n("sv-panel",{ref:"sl",attrs:{color:e.color}})],1),e.showAlpha?n("alpha-slider",{ref:"alpha",attrs:{color:e.color}}):e._e(),e.predefine?n("predefine",{attrs:{color:e.color,colors:e.predefine}}):e._e(),n("div",{staticClass:"el-color-dropdown__btns"},[n("span",{staticClass:"el-color-dropdown__value"},[n("el-input",{attrs:{"validate-event":!1,size:"mini"},on:{blur:e.handleConfirm},nativeOn:{keyup:function(t){return!("button"in t)&&e._k(t.keyCode,"enter",13,t.key,"Enter")?null:e.handleConfirm(t)}},model:{value:e.customInput,callback:function(t){e.customInput=t},expression:"customInput"}})],1),n("el-button",{staticClass:"el-color-dropdown__link-btn",attrs:{size:"mini",type:"text"},on:{click:function(t){e.$emit("clear")}}},[e._v("\n "+e._s(e.t("el.colorpicker.clear"))+"\n ")]),n("el-button",{staticClass:"el-color-dropdown__btn",attrs:{plain:"",size:"mini"},on:{click:e.confirmValue}},[e._v("\n "+e._s(e.t("el.colorpicker.confirm"))+"\n ")])],1)],1)])};h._withStripped=!0;var v=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"el-color-svpanel",style:{backgroundColor:e.background}},[n("div",{staticClass:"el-color-svpanel__white"}),n("div",{staticClass:"el-color-svpanel__black"}),n("div",{staticClass:"el-color-svpanel__cursor",style:{top:e.cursorTop+"px",left:e.cursorLeft+"px"}},[n("div")])])};v._withStripped=!0;var m=n(7),_=n.n(m),g=!1,b=function(e,t){if(!_.a.prototype.$isServer){var n=function(e){t.drag&&t.drag(e)},i=function e(i){document.removeEventListener("mousemove",n),document.removeEventListener("mouseup",e),document.onselectstart=null,document.ondragstart=null,g=!1,t.end&&t.end(i)};e.addEventListener("mousedown",(function(e){g||(document.onselectstart=function(){return!1},document.ondragstart=function(){return!1},document.addEventListener("mousemove",n),document.addEventListener("mouseup",i),g=!0,t.start&&t.start(e))}))}},y={name:"el-sl-panel",props:{color:{required:!0}},computed:{colorValue:function(){return{hue:this.color.get("hue"),value:this.color.get("value")}}},watch:{colorValue:function(){this.update()}},methods:{update:function(){var e=this.color.get("saturation"),t=this.color.get("value"),n=this.$el,i=n.clientWidth,r=n.clientHeight;this.cursorLeft=e*i/100,this.cursorTop=(100-t)*r/100,this.background="hsl("+this.color.get("hue")+", 100%, 50%)"},handleDrag:function(e){var t=this.$el.getBoundingClientRect(),n=e.clientX-t.left,i=e.clientY-t.top;n=Math.max(0,n),n=Math.min(n,t.width),i=Math.max(0,i),i=Math.min(i,t.height),this.cursorLeft=n,this.cursorTop=i,this.color.set({saturation:n/t.width*100,value:100-i/t.height*100})}},mounted:function(){var e=this;b(this.$el,{drag:function(t){e.handleDrag(t)},end:function(t){e.handleDrag(t)}}),this.update()},data:function(){return{cursorTop:0,cursorLeft:0,background:"hsl(0, 100%, 50%)"}}},x=n(0),w=Object(x.a)(y,v,[],!1,null,null,null);w.options.__file="packages/color-picker/src/components/sv-panel.vue";var C=w.exports,S=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"el-color-hue-slider",class:{"is-vertical":e.vertical}},[n("div",{ref:"bar",staticClass:"el-color-hue-slider__bar",on:{click:e.handleClick}}),n("div",{ref:"thumb",staticClass:"el-color-hue-slider__thumb",style:{left:e.thumbLeft+"px",top:e.thumbTop+"px"}})])};S._withStripped=!0;var k={name:"el-color-hue-slider",props:{color:{required:!0},vertical:Boolean},data:function(){return{thumbLeft:0,thumbTop:0}},computed:{hueValue:function(){return this.color.get("hue")}},watch:{hueValue:function(){this.update()}},methods:{handleClick:function(e){var t=this.$refs.thumb;e.target!==t&&this.handleDrag(e)},handleDrag:function(e){var t=this.$el.getBoundingClientRect(),n=this.$refs.thumb,i=void 0;if(this.vertical){var r=e.clientY-t.top;r=Math.min(r,t.height-n.offsetHeight/2),r=Math.max(n.offsetHeight/2,r),i=Math.round((r-n.offsetHeight/2)/(t.height-n.offsetHeight)*360)}else{var o=e.clientX-t.left;o=Math.min(o,t.width-n.offsetWidth/2),o=Math.max(n.offsetWidth/2,o),i=Math.round((o-n.offsetWidth/2)/(t.width-n.offsetWidth)*360)}this.color.set("hue",i)},getThumbLeft:function(){if(this.vertical)return 0;var e=this.$el,t=this.color.get("hue");if(!e)return 0;var n=this.$refs.thumb;return Math.round(t*(e.offsetWidth-n.offsetWidth/2)/360)},getThumbTop:function(){if(!this.vertical)return 0;var e=this.$el,t=this.color.get("hue");if(!e)return 0;var n=this.$refs.thumb;return Math.round(t*(e.offsetHeight-n.offsetHeight/2)/360)},update:function(){this.thumbLeft=this.getThumbLeft(),this.thumbTop=this.getThumbTop()}},mounted:function(){var e=this,t=this.$refs,n=t.bar,i=t.thumb,r={drag:function(t){e.handleDrag(t)},end:function(t){e.handleDrag(t)}};b(n,r),b(i,r),this.update()}},$=Object(x.a)(k,S,[],!1,null,null,null);$.options.__file="packages/color-picker/src/components/hue-slider.vue";var O=$.exports,T=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"el-color-alpha-slider",class:{"is-vertical":e.vertical}},[n("div",{ref:"bar",staticClass:"el-color-alpha-slider__bar",style:{background:e.background},on:{click:e.handleClick}}),n("div",{ref:"thumb",staticClass:"el-color-alpha-slider__thumb",style:{left:e.thumbLeft+"px",top:e.thumbTop+"px"}})])};T._withStripped=!0;var E={name:"el-color-alpha-slider",props:{color:{required:!0},vertical:Boolean},watch:{"color._alpha":function(){this.update()},"color.value":function(){this.update()}},methods:{handleClick:function(e){var t=this.$refs.thumb;e.target!==t&&this.handleDrag(e)},handleDrag:function(e){var t=this.$el.getBoundingClientRect(),n=this.$refs.thumb;if(this.vertical){var i=e.clientY-t.top;i=Math.max(n.offsetHeight/2,i),i=Math.min(i,t.height-n.offsetHeight/2),this.color.set("alpha",Math.round((i-n.offsetHeight/2)/(t.height-n.offsetHeight)*100))}else{var r=e.clientX-t.left;r=Math.max(n.offsetWidth/2,r),r=Math.min(r,t.width-n.offsetWidth/2),this.color.set("alpha",Math.round((r-n.offsetWidth/2)/(t.width-n.offsetWidth)*100))}},getThumbLeft:function(){if(this.vertical)return 0;var e=this.$el,t=this.color._alpha;if(!e)return 0;var n=this.$refs.thumb;return Math.round(t*(e.offsetWidth-n.offsetWidth/2)/100)},getThumbTop:function(){if(!this.vertical)return 0;var e=this.$el,t=this.color._alpha;if(!e)return 0;var n=this.$refs.thumb;return Math.round(t*(e.offsetHeight-n.offsetHeight/2)/100)},getBackground:function(){if(this.color&&this.color.value){var e=this.color.toRgb(),t=e.r,n=e.g,i=e.b;return"linear-gradient(to right, rgba("+t+", "+n+", "+i+", 0) 0%, rgba("+t+", "+n+", "+i+", 1) 100%)"}return null},update:function(){this.thumbLeft=this.getThumbLeft(),this.thumbTop=this.getThumbTop(),this.background=this.getBackground()}},data:function(){return{thumbLeft:0,thumbTop:0,background:null}},mounted:function(){var e=this,t=this.$refs,n=t.bar,i=t.thumb,r={drag:function(t){e.handleDrag(t)},end:function(t){e.handleDrag(t)}};b(n,r),b(i,r),this.update()}},j=Object(x.a)(E,T,[],!1,null,null,null);j.options.__file="packages/color-picker/src/components/alpha-slider.vue";var I=j.exports,P=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"el-color-predefine"},[n("div",{staticClass:"el-color-predefine__colors"},e._l(e.rgbaColors,(function(t,i){return n("div",{key:e.colors[i],staticClass:"el-color-predefine__color-selector",class:{selected:t.selected,"is-alpha":t._alpha<100},on:{click:function(t){e.handleSelect(i)}}},[n("div",{style:{"background-color":t.value}})])})),0)])};P._withStripped=!0;var M={props:{colors:{type:Array,required:!0},color:{required:!0}},data:function(){return{rgbaColors:this.parseColors(this.colors,this.color)}},methods:{handleSelect:function(e){this.color.fromString(this.colors[e])},parseColors:function(e,t){return e.map((function(e){var n=new p;return n.enableAlpha=!0,n.format="rgba",n.fromString(e),n.selected=n.value===t.value,n}))}},watch:{"$parent.currentColor":function(e){var t=new p;t.fromString(e),this.rgbaColors.forEach((function(e){e.selected=t.compare(e)}))},colors:function(e){this.rgbaColors=this.parseColors(e,this.color)},color:function(e){this.rgbaColors=this.parseColors(this.colors,e)}}},A=Object(x.a)(M,P,[],!1,null,null,null);A.options.__file="packages/color-picker/src/components/predefine.vue";var N=A.exports,L=n(5),D=n.n(L),R=n(6),z=n.n(R),F=n(10),V=n.n(F),B=n(14),H=n.n(B),U={name:"el-color-picker-dropdown",mixins:[D.a,z.a],components:{SvPanel:C,HueSlider:O,AlphaSlider:I,ElInput:V.a,ElButton:H.a,Predefine:N},props:{color:{required:!0},showAlpha:Boolean,predefine:Array},data:function(){return{customInput:""}},computed:{currentColor:function(){var e=this.$parent;return e.value||e.showPanelColor?e.color.value:""}},methods:{confirmValue:function(){this.$emit("pick")},handleConfirm:function(){this.color.fromString(this.customInput)}},mounted:function(){this.$parent.popperElm=this.popperElm=this.$el,this.referenceElm=this.$parent.$el},watch:{showPopper:function(e){var t=this;!0===e&&this.$nextTick((function(){var e=t.$refs,n=e.sl,i=e.hue,r=e.alpha;n&&n.update(),i&&i.update(),r&&r.update()}))},currentColor:{immediate:!0,handler:function(e){this.customInput=e}}}},q=Object(x.a)(U,h,[],!1,null,null,null);q.options.__file="packages/color-picker/src/components/picker-dropdown.vue";var W=q.exports,G=n(12),X=n.n(G),Z=n(4),K={name:"ElColorPicker",mixins:[n.n(Z).a],props:{value:String,showAlpha:Boolean,colorFormat:String,disabled:Boolean,size:String,popperClass:String,predefine:Array},inject:{elForm:{default:""},elFormItem:{default:""}},directives:{Clickoutside:X.a},computed:{displayedColor:function(){return this.value||this.showPanelColor?this.displayedRgb(this.color,this.showAlpha):"transparent"},_elFormItemSize:function(){return(this.elFormItem||{}).elFormItemSize},colorSize:function(){return this.size||this._elFormItemSize||(this.$ELEMENT||{}).size},colorDisabled:function(){return this.disabled||(this.elForm||{}).disabled}},watch:{value:function(e){e?e&&e!==this.color.value&&this.color.fromString(e):this.showPanelColor=!1},color:{deep:!0,handler:function(){this.showPanelColor=!0}},displayedColor:function(e){if(this.showPicker){var t=new p({enableAlpha:this.showAlpha,format:this.colorFormat});t.fromString(this.value),e!==this.displayedRgb(t,this.showAlpha)&&this.$emit("active-change",e)}}},methods:{handleTrigger:function(){this.colorDisabled||(this.showPicker=!this.showPicker)},confirmValue:function(){var e=this.color.value;this.$emit("input",e),this.$emit("change",e),this.dispatch("ElFormItem","el.form.change",e),this.showPicker=!1},clearValue:function(){this.$emit("input",null),this.$emit("change",null),null!==this.value&&this.dispatch("ElFormItem","el.form.change",null),this.showPanelColor=!1,this.showPicker=!1,this.resetColor()},hide:function(){this.showPicker=!1,this.resetColor()},resetColor:function(){var e=this;this.$nextTick((function(t){e.value?e.color.fromString(e.value):e.showPanelColor=!1}))},displayedRgb:function(e,t){if(!(e instanceof p))throw Error("color should be instance of Color Class");var n=e.toRgb(),i=n.r,r=n.g,o=n.b;return t?"rgba("+i+", "+r+", "+o+", "+e.get("alpha")/100+")":"rgb("+i+", "+r+", "+o+")"}},mounted:function(){var e=this.value;e&&this.color.fromString(e),this.popperElm=this.$refs.dropdown.$el},data:function(){return{color:new p({enableAlpha:this.showAlpha,format:this.colorFormat}),showPicker:!1,showPanelColor:!1}},components:{PickerDropdown:W}},J=Object(x.a)(K,i,[],!1,null,null,null);J.options.__file="packages/color-picker/src/main.vue";var Y=J.exports;Y.install=function(e){e.component(Y.name,Y)};t.default=Y},6:function(e,t){e.exports=n(52084)},7:function(e,t){e.exports=n(70538)}})},42173:(e,t,n)=>{e.exports=function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist/",n(n.s=84)}({0:function(e,t,n){"use strict";function i(e,t,n,i,r,o,s,a){var l,c="function"==typeof e?e.options:e;if(t&&(c.render=t,c.staticRenderFns=n,c._compiled=!0),i&&(c.functional=!0),o&&(c._scopeId="data-v-"+o),s?(l=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),r&&r.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(s)},c._ssrRegister=l):r&&(l=a?function(){r.call(this,this.$root.$options.shadowRoot)}:r),l)if(c.functional){c._injectStyles=l;var u=c.render;c.render=function(e,t){return l.call(t),u(e,t)}}else{var d=c.beforeCreate;c.beforeCreate=d?[].concat(d,l):[l]}return{exports:e,options:c}}n.d(t,"a",(function(){return i}))},4:function(e,t){e.exports=n(52477)},84:function(e,t,n){"use strict";n.r(t);var i=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("li",{staticClass:"el-dropdown-menu__item",class:{"is-disabled":e.disabled,"el-dropdown-menu__item--divided":e.divided},attrs:{"aria-disabled":e.disabled,tabindex:e.disabled?null:-1},on:{click:e.handleClick}},[e.icon?n("i",{class:e.icon}):e._e(),e._t("default")],2)};i._withStripped=!0;var r=n(4),o={name:"ElDropdownItem",mixins:[n.n(r).a],props:{command:{},disabled:Boolean,divided:Boolean,icon:String},methods:{handleClick:function(e){this.dispatch("ElDropdown","menu-item-click",[this.command,this])}}},s=n(0),a=Object(s.a)(o,i,[],!1,null,null,null);a.options.__file="packages/dropdown/src/dropdown-item.vue";var l=a.exports;l.install=function(e){e.component(l.name,l)};t.default=l}})},43229:(e,t,n)=>{e.exports=function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist/",n(n.s=83)}({0:function(e,t,n){"use strict";function i(e,t,n,i,r,o,s,a){var l,c="function"==typeof e?e.options:e;if(t&&(c.render=t,c.staticRenderFns=n,c._compiled=!0),i&&(c.functional=!0),o&&(c._scopeId="data-v-"+o),s?(l=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),r&&r.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(s)},c._ssrRegister=l):r&&(l=a?function(){r.call(this,this.$root.$options.shadowRoot)}:r),l)if(c.functional){c._injectStyles=l;var u=c.render;c.render=function(e,t){return l.call(t),u(e,t)}}else{var d=c.beforeCreate;c.beforeCreate=d?[].concat(d,l):[l]}return{exports:e,options:c}}n.d(t,"a",(function(){return i}))},5:function(e,t){e.exports=n(70499)},83:function(e,t,n){"use strict";n.r(t);var i=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("transition",{attrs:{name:"el-zoom-in-top"},on:{"after-leave":e.doDestroy}},[n("ul",{directives:[{name:"show",rawName:"v-show",value:e.showPopper,expression:"showPopper"}],staticClass:"el-dropdown-menu el-popper",class:[e.size&&"el-dropdown-menu--"+e.size]},[e._t("default")],2)])};i._withStripped=!0;var r=n(5),o={name:"ElDropdownMenu",componentName:"ElDropdownMenu",mixins:[n.n(r).a],props:{visibleArrow:{type:Boolean,default:!0},arrowOffset:{type:Number,default:0}},data:function(){return{size:this.dropdown.dropdownSize}},inject:["dropdown"],created:function(){var e=this;this.$on("updatePopper",(function(){e.showPopper&&e.updatePopper()})),this.$on("visible",(function(t){e.showPopper=t}))},mounted:function(){this.dropdown.popperElm=this.popperElm=this.$el,this.referenceElm=this.dropdown.$el,this.dropdown.initDomOperation()},watch:{"dropdown.placement":{immediate:!0,handler:function(e){this.currentPlacement=e}}}},s=n(0),a=Object(s.a)(o,i,[],!1,null,null,null);a.options.__file="packages/dropdown/src/dropdown-menu.vue";var l=a.exports;l.install=function(e){e.component(l.name,l)};t.default=l}})},57099:(e,t,n)=>{e.exports=function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist/",n(n.s=130)}({0:function(e,t,n){"use strict";function i(e,t,n,i,r,o,s,a){var l,c="function"==typeof e?e.options:e;if(t&&(c.render=t,c.staticRenderFns=n,c._compiled=!0),i&&(c.functional=!0),o&&(c._scopeId="data-v-"+o),s?(l=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),r&&r.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(s)},c._ssrRegister=l):r&&(l=a?function(){r.call(this,this.$root.$options.shadowRoot)}:r),l)if(c.functional){c._injectStyles=l;var u=c.render;c.render=function(e,t){return l.call(t),u(e,t)}}else{var d=c.beforeCreate;c.beforeCreate=d?[].concat(d,l):[l]}return{exports:e,options:c}}n.d(t,"a",(function(){return i}))},11:function(e,t){e.exports=n(84222)},12:function(e,t){e.exports=n(1080)},130:function(e,t,n){"use strict";n.r(t);var i=n(12),r=n.n(i),o=n(4),s=n.n(o),a=n(11),l=n.n(a),c=n(14),u=n.n(c),d=n(36),f=n.n(d),p=n(3),h={name:"ElDropdown",componentName:"ElDropdown",mixins:[s.a,l.a],directives:{Clickoutside:r.a},components:{ElButton:u.a,ElButtonGroup:f.a},provide:function(){return{dropdown:this}},props:{trigger:{type:String,default:"hover"},type:String,size:{type:String,default:""},splitButton:Boolean,hideOnClick:{type:Boolean,default:!0},placement:{type:String,default:"bottom-end"},visibleArrow:{default:!0},showTimeout:{type:Number,default:250},hideTimeout:{type:Number,default:150},tabindex:{type:Number,default:0},disabled:{type:Boolean,default:!1}},data:function(){return{timeout:null,visible:!1,triggerElm:null,menuItems:null,menuItemsArray:null,dropdownElm:null,focusing:!1,listId:"dropdown-menu-"+Object(p.generateId)()}},computed:{dropdownSize:function(){return this.size||(this.$ELEMENT||{}).size}},mounted:function(){this.$on("menu-item-click",this.handleMenuItemClick)},watch:{visible:function(e){this.broadcast("ElDropdownMenu","visible",e),this.$emit("visible-change",e)},focusing:function(e){var t=this.$el.querySelector(".el-dropdown-selfdefine");t&&(e?t.className+=" focusing":t.className=t.className.replace("focusing",""))}},methods:{getMigratingConfig:function(){return{props:{"menu-align":"menu-align is renamed to placement."}}},show:function(){var e=this;this.disabled||(clearTimeout(this.timeout),this.timeout=setTimeout((function(){e.visible=!0}),"click"===this.trigger?0:this.showTimeout))},hide:function(){var e=this;this.disabled||(this.removeTabindex(),this.tabindex>=0&&this.resetTabindex(this.triggerElm),clearTimeout(this.timeout),this.timeout=setTimeout((function(){e.visible=!1}),"click"===this.trigger?0:this.hideTimeout))},handleClick:function(){this.disabled||(this.visible?this.hide():this.show())},handleTriggerKeyDown:function(e){var t=e.keyCode;[38,40].indexOf(t)>-1?(this.removeTabindex(),this.resetTabindex(this.menuItems[0]),this.menuItems[0].focus(),e.preventDefault(),e.stopPropagation()):13===t?this.handleClick():[9,27].indexOf(t)>-1&&this.hide()},handleItemKeyDown:function(e){var t=e.keyCode,n=e.target,i=this.menuItemsArray.indexOf(n),r=this.menuItemsArray.length-1,o=void 0;[38,40].indexOf(t)>-1?(o=38===t?0!==i?i-1:0:i-1&&(this.hide(),this.triggerElmFocus())},resetTabindex:function(e){this.removeTabindex(),e.setAttribute("tabindex","0")},removeTabindex:function(){this.triggerElm.setAttribute("tabindex","-1"),this.menuItemsArray.forEach((function(e){e.setAttribute("tabindex","-1")}))},initAria:function(){this.dropdownElm.setAttribute("id",this.listId),this.triggerElm.setAttribute("aria-haspopup","list"),this.triggerElm.setAttribute("aria-controls",this.listId),this.splitButton||(this.triggerElm.setAttribute("role","button"),this.triggerElm.setAttribute("tabindex",this.tabindex),this.triggerElm.setAttribute("class",(this.triggerElm.getAttribute("class")||"")+" el-dropdown-selfdefine"))},initEvent:function(){var e=this,t=this.trigger,n=this.show,i=this.hide,r=this.handleClick,o=this.splitButton,s=this.handleTriggerKeyDown,a=this.handleItemKeyDown;this.triggerElm=o?this.$refs.trigger.$el:this.$slots.default[0].elm;var l=this.dropdownElm;this.triggerElm.addEventListener("keydown",s),l.addEventListener("keydown",a,!0),o||(this.triggerElm.addEventListener("focus",(function(){e.focusing=!0})),this.triggerElm.addEventListener("blur",(function(){e.focusing=!1})),this.triggerElm.addEventListener("click",(function(){e.focusing=!1}))),"hover"===t?(this.triggerElm.addEventListener("mouseenter",n),this.triggerElm.addEventListener("mouseleave",i),l.addEventListener("mouseenter",n),l.addEventListener("mouseleave",i)):"click"===t&&this.triggerElm.addEventListener("click",r)},handleMenuItemClick:function(e,t){this.hideOnClick&&(this.visible=!1),this.$emit("command",e,t)},triggerElmFocus:function(){this.triggerElm.focus&&this.triggerElm.focus()},initDomOperation:function(){this.dropdownElm=this.popperElm,this.menuItems=this.dropdownElm.querySelectorAll("[tabindex='-1']"),this.menuItemsArray=[].slice.call(this.menuItems),this.initEvent(),this.initAria()}},render:function(e){var t=this,n=this.hide,i=this.splitButton,r=this.type,o=this.dropdownSize,s=this.disabled,a=null;if(i)a=e("el-button-group",[e("el-button",{attrs:{type:r,size:o,disabled:s},nativeOn:{click:function(e){t.$emit("click",e),n()}}},[this.$slots.default]),e("el-button",{ref:"trigger",attrs:{type:r,size:o,disabled:s},class:"el-dropdown__caret-button"},[e("i",{class:"el-dropdown__icon el-icon-arrow-down"})])]);else{var l=(a=this.$slots.default)[0].data||{},c=l.attrs,u=void 0===c?{}:c;s&&!u.disabled&&(u.disabled=!0,l.attrs=u)}var d=s?null:this.$slots.dropdown;return e("div",{class:"el-dropdown",directives:[{name:"clickoutside",value:n}],attrs:{"aria-disabled":s}},[a,d])}},v=n(0),m=Object(v.a)(h,undefined,undefined,!1,null,null,null);m.options.__file="packages/dropdown/src/dropdown.vue";var _=m.exports;_.install=function(e){e.component(_.name,_)};t.default=_},14:function(e,t){e.exports=n(26426)},3:function(e,t){e.exports=n(93104)},36:function(e,t){e.exports=n(87563)},4:function(e,t){e.exports=n(52477)}})},7987:(e,t,n)=>{e.exports=function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist/",n(n.s=87)}({0:function(e,t,n){"use strict";function i(e,t,n,i,r,o,s,a){var l,c="function"==typeof e?e.options:e;if(t&&(c.render=t,c.staticRenderFns=n,c._compiled=!0),i&&(c.functional=!0),o&&(c._scopeId="data-v-"+o),s?(l=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),r&&r.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(s)},c._ssrRegister=l):r&&(l=a?function(){r.call(this,this.$root.$options.shadowRoot)}:r),l)if(c.functional){c._injectStyles=l;var u=c.render;c.render=function(e,t){return l.call(t),u(e,t)}}else{var d=c.beforeCreate;c.beforeCreate=d?[].concat(d,l):[l]}return{exports:e,options:c}}n.d(t,"a",(function(){return i}))},10:function(e,t){e.exports=n(7626)},2:function(e,t){e.exports=n(34594)},22:function(e,t){e.exports=n(98618)},3:function(e,t){e.exports=n(93104)},30:function(e,t,n){"use strict";var i=n(2),r=n(3);t.a={bind:function(e,t,n){var o=null,s=void 0,a=Object(r.isMac)()?100:200,l=function(){return n.context[t.expression].apply()},c=function(){Date.now()-s=0&&e===parseInt(e,10)}}},data:function(){return{currentValue:0,userInput:null}},watch:{value:{immediate:!0,handler:function(e){var t=void 0===e?e:Number(e);if(void 0!==t){if(isNaN(t))return;if(this.stepStrictly){var n=this.getPrecision(this.step),i=Math.pow(10,n);t=Math.round(t/this.step)*i*this.step/i}void 0!==this.precision&&(t=this.toPrecision(t,this.precision))}t>=this.max&&(t=this.max),t<=this.min&&(t=this.min),this.currentValue=t,this.userInput=null,this.$emit("input",t)}}},computed:{minDisabled:function(){return this._decrease(this.value,this.step)this.max},numPrecision:function(){var e=this.value,t=this.step,n=this.getPrecision,i=this.precision,r=n(t);return void 0!==i?(r>i&&console.warn("[Element Warn][InputNumber]precision should not be less than the decimal places of step"),i):Math.max(n(e),r)},controlsAtRight:function(){return this.controls&&"right"===this.controlsPosition},_elFormItemSize:function(){return(this.elFormItem||{}).elFormItemSize},inputNumberSize:function(){return this.size||this._elFormItemSize||(this.$ELEMENT||{}).size},inputNumberDisabled:function(){return this.disabled||!!(this.elForm||{}).disabled},displayValue:function(){if(null!==this.userInput)return this.userInput;var e=this.currentValue;if("number"==typeof e){if(this.stepStrictly){var t=this.getPrecision(this.step),n=Math.pow(10,t);e=Math.round(e/this.step)*n*this.step/n}void 0!==this.precision&&(e=e.toFixed(this.precision))}return e}},methods:{toPrecision:function(e,t){return void 0===t&&(t=this.numPrecision),parseFloat(Math.round(e*Math.pow(10,t))/Math.pow(10,t))},getPrecision:function(e){if(void 0===e)return 0;var t=e.toString(),n=t.indexOf("."),i=0;return-1!==n&&(i=t.length-n-1),i},_increase:function(e,t){if("number"!=typeof e&&void 0!==e)return this.currentValue;var n=Math.pow(10,this.numPrecision);return this.toPrecision((n*e+n*t)/n)},_decrease:function(e,t){if("number"!=typeof e&&void 0!==e)return this.currentValue;var n=Math.pow(10,this.numPrecision);return this.toPrecision((n*e-n*t)/n)},increase:function(){if(!this.inputNumberDisabled&&!this.maxDisabled){var e=this.value||0,t=this._increase(e,this.step);this.setCurrentValue(t)}},decrease:function(){if(!this.inputNumberDisabled&&!this.minDisabled){var e=this.value||0,t=this._decrease(e,this.step);this.setCurrentValue(t)}},handleBlur:function(e){this.$emit("blur",e)},handleFocus:function(e){this.$emit("focus",e)},setCurrentValue:function(e){var t=this.currentValue;"number"==typeof e&&void 0!==this.precision&&(e=this.toPrecision(e,this.precision)),e>=this.max&&(e=this.max),e<=this.min&&(e=this.min),t!==e&&(this.userInput=null,this.$emit("input",e),this.$emit("change",e,t),this.currentValue=e)},handleInput:function(e){this.userInput=e},handleInputChange:function(e){var t=""===e?void 0:Number(e);isNaN(t)&&""!==e||this.setCurrentValue(t),this.userInput=null},select:function(){this.$refs.input.select()}},mounted:function(){var e=this.$refs.input.$refs.input;e.setAttribute("role","spinbutton"),e.setAttribute("aria-valuemax",this.max),e.setAttribute("aria-valuemin",this.min),e.setAttribute("aria-valuenow",this.currentValue),e.setAttribute("aria-disabled",this.inputNumberDisabled)},updated:function(){this.$refs&&this.$refs.input&&this.$refs.input.$refs.input.setAttribute("aria-valuenow",this.currentValue)}},u=n(0),d=Object(u.a)(c,i,[],!1,null,null,null);d.options.__file="packages/input-number/src/input-number.vue";var f=d.exports;f.install=function(e){e.component(f.name,f)};t.default=f}})},7626:(e,t,n)=>{e.exports=function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist/",n(n.s=75)}({0:function(e,t,n){"use strict";function i(e,t,n,i,r,o,s,a){var l,c="function"==typeof e?e.options:e;if(t&&(c.render=t,c.staticRenderFns=n,c._compiled=!0),i&&(c.functional=!0),o&&(c._scopeId="data-v-"+o),s?(l=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),r&&r.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(s)},c._ssrRegister=l):r&&(l=a?function(){r.call(this,this.$root.$options.shadowRoot)}:r),l)if(c.functional){c._injectStyles=l;var u=c.render;c.render=function(e,t){return l.call(t),u(e,t)}}else{var d=c.beforeCreate;c.beforeCreate=d?[].concat(d,l):[l]}return{exports:e,options:c}}n.d(t,"a",(function(){return i}))},11:function(e,t){e.exports=n(84222)},21:function(e,t){e.exports=n(50167)},4:function(e,t){e.exports=n(52477)},75:function(e,t,n){"use strict";n.r(t);var i=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{class:["textarea"===e.type?"el-textarea":"el-input",e.inputSize?"el-input--"+e.inputSize:"",{"is-disabled":e.inputDisabled,"is-exceed":e.inputExceed,"el-input-group":e.$slots.prepend||e.$slots.append,"el-input-group--append":e.$slots.append,"el-input-group--prepend":e.$slots.prepend,"el-input--prefix":e.$slots.prefix||e.prefixIcon,"el-input--suffix":e.$slots.suffix||e.suffixIcon||e.clearable||e.showPassword}],on:{mouseenter:function(t){e.hovering=!0},mouseleave:function(t){e.hovering=!1}}},["textarea"!==e.type?[e.$slots.prepend?n("div",{staticClass:"el-input-group__prepend"},[e._t("prepend")],2):e._e(),"textarea"!==e.type?n("input",e._b({ref:"input",staticClass:"el-input__inner",attrs:{tabindex:e.tabindex,type:e.showPassword?e.passwordVisible?"text":"password":e.type,disabled:e.inputDisabled,readonly:e.readonly,autocomplete:e.autoComplete||e.autocomplete,"aria-label":e.label},on:{compositionstart:e.handleCompositionStart,compositionupdate:e.handleCompositionUpdate,compositionend:e.handleCompositionEnd,input:e.handleInput,focus:e.handleFocus,blur:e.handleBlur,change:e.handleChange}},"input",e.$attrs,!1)):e._e(),e.$slots.prefix||e.prefixIcon?n("span",{staticClass:"el-input__prefix"},[e._t("prefix"),e.prefixIcon?n("i",{staticClass:"el-input__icon",class:e.prefixIcon}):e._e()],2):e._e(),e.getSuffixVisible()?n("span",{staticClass:"el-input__suffix"},[n("span",{staticClass:"el-input__suffix-inner"},[e.showClear&&e.showPwdVisible&&e.isWordLimitVisible?e._e():[e._t("suffix"),e.suffixIcon?n("i",{staticClass:"el-input__icon",class:e.suffixIcon}):e._e()],e.showClear?n("i",{staticClass:"el-input__icon el-icon-circle-close el-input__clear",on:{mousedown:function(e){e.preventDefault()},click:e.clear}}):e._e(),e.showPwdVisible?n("i",{staticClass:"el-input__icon el-icon-view el-input__clear",on:{click:e.handlePasswordVisible}}):e._e(),e.isWordLimitVisible?n("span",{staticClass:"el-input__count"},[n("span",{staticClass:"el-input__count-inner"},[e._v("\n "+e._s(e.textLength)+"/"+e._s(e.upperLimit)+"\n ")])]):e._e()],2),e.validateState?n("i",{staticClass:"el-input__icon",class:["el-input__validateIcon",e.validateIcon]}):e._e()]):e._e(),e.$slots.append?n("div",{staticClass:"el-input-group__append"},[e._t("append")],2):e._e()]:n("textarea",e._b({ref:"textarea",staticClass:"el-textarea__inner",style:e.textareaStyle,attrs:{tabindex:e.tabindex,disabled:e.inputDisabled,readonly:e.readonly,autocomplete:e.autoComplete||e.autocomplete,"aria-label":e.label},on:{compositionstart:e.handleCompositionStart,compositionupdate:e.handleCompositionUpdate,compositionend:e.handleCompositionEnd,input:e.handleInput,focus:e.handleFocus,blur:e.handleBlur,change:e.handleChange}},"textarea",e.$attrs,!1)),e.isWordLimitVisible&&"textarea"===e.type?n("span",{staticClass:"el-input__count"},[e._v(e._s(e.textLength)+"/"+e._s(e.upperLimit))]):e._e()],2)};i._withStripped=!0;var r=n(4),o=n.n(r),s=n(11),a=n.n(s),l=void 0,c=["letter-spacing","line-height","padding-top","padding-bottom","font-family","font-weight","font-size","text-rendering","text-transform","width","text-indent","padding-left","padding-right","border-width","box-sizing"];function u(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;l||(l=document.createElement("textarea"),document.body.appendChild(l));var i=function(e){var t=window.getComputedStyle(e),n=t.getPropertyValue("box-sizing"),i=parseFloat(t.getPropertyValue("padding-bottom"))+parseFloat(t.getPropertyValue("padding-top")),r=parseFloat(t.getPropertyValue("border-bottom-width"))+parseFloat(t.getPropertyValue("border-top-width"));return{contextStyle:c.map((function(e){return e+":"+t.getPropertyValue(e)})).join(";"),paddingSize:i,borderSize:r,boxSizing:n}}(e),r=i.paddingSize,o=i.borderSize,s=i.boxSizing,a=i.contextStyle;l.setAttribute("style",a+";\n height:0 !important;\n visibility:hidden !important;\n overflow:hidden !important;\n position:absolute !important;\n z-index:-1000 !important;\n top:0 !important;\n right:0 !important\n"),l.value=e.value||e.placeholder||"";var u=l.scrollHeight,d={};"border-box"===s?u+=o:"content-box"===s&&(u-=r),l.value="";var f=l.scrollHeight-r;if(null!==t){var p=f*t;"border-box"===s&&(p=p+r+o),u=Math.max(p,u),d.minHeight=p+"px"}if(null!==n){var h=f*n;"border-box"===s&&(h=h+r+o),u=Math.min(h,u)}return d.height=u+"px",l.parentNode&&l.parentNode.removeChild(l),l=null,d}var d=n(9),f=n.n(d),p=n(21),h={name:"ElInput",componentName:"ElInput",mixins:[o.a,a.a],inheritAttrs:!1,inject:{elForm:{default:""},elFormItem:{default:""}},data:function(){return{textareaCalcStyle:{},hovering:!1,focused:!1,isComposing:!1,passwordVisible:!1}},props:{value:[String,Number],size:String,resize:String,form:String,disabled:Boolean,readonly:Boolean,type:{type:String,default:"text"},autosize:{type:[Boolean,Object],default:!1},autocomplete:{type:String,default:"off"},autoComplete:{type:String,validator:function(e){return!0}},validateEvent:{type:Boolean,default:!0},suffixIcon:String,prefixIcon:String,label:String,clearable:{type:Boolean,default:!1},showPassword:{type:Boolean,default:!1},showWordLimit:{type:Boolean,default:!1},tabindex:String},computed:{_elFormItemSize:function(){return(this.elFormItem||{}).elFormItemSize},validateState:function(){return this.elFormItem?this.elFormItem.validateState:""},needStatusIcon:function(){return!!this.elForm&&this.elForm.statusIcon},validateIcon:function(){return{validating:"el-icon-loading",success:"el-icon-circle-check",error:"el-icon-circle-close"}[this.validateState]},textareaStyle:function(){return f()({},this.textareaCalcStyle,{resize:this.resize})},inputSize:function(){return this.size||this._elFormItemSize||(this.$ELEMENT||{}).size},inputDisabled:function(){return this.disabled||(this.elForm||{}).disabled},nativeInputValue:function(){return null===this.value||void 0===this.value?"":String(this.value)},showClear:function(){return this.clearable&&!this.inputDisabled&&!this.readonly&&this.nativeInputValue&&(this.focused||this.hovering)},showPwdVisible:function(){return this.showPassword&&!this.inputDisabled&&!this.readonly&&(!!this.nativeInputValue||this.focused)},isWordLimitVisible:function(){return this.showWordLimit&&this.$attrs.maxlength&&("text"===this.type||"textarea"===this.type)&&!this.inputDisabled&&!this.readonly&&!this.showPassword},upperLimit:function(){return this.$attrs.maxlength},textLength:function(){return"number"==typeof this.value?String(this.value).length:(this.value||"").length},inputExceed:function(){return this.isWordLimitVisible&&this.textLength>this.upperLimit}},watch:{value:function(e){this.$nextTick(this.resizeTextarea),this.validateEvent&&this.dispatch("ElFormItem","el.form.change",[e])},nativeInputValue:function(){this.setNativeInputValue()},type:function(){var e=this;this.$nextTick((function(){e.setNativeInputValue(),e.resizeTextarea(),e.updateIconOffset()}))}},methods:{focus:function(){this.getInput().focus()},blur:function(){this.getInput().blur()},getMigratingConfig:function(){return{props:{icon:"icon is removed, use suffix-icon / prefix-icon instead.","on-icon-click":"on-icon-click is removed."},events:{click:"click is removed."}}},handleBlur:function(e){this.focused=!1,this.$emit("blur",e),this.validateEvent&&this.dispatch("ElFormItem","el.form.blur",[this.value])},select:function(){this.getInput().select()},resizeTextarea:function(){if(!this.$isServer){var e=this.autosize;if("textarea"===this.type)if(e){var t=e.minRows,n=e.maxRows;this.textareaCalcStyle=u(this.$refs.textarea,t,n)}else this.textareaCalcStyle={minHeight:u(this.$refs.textarea).minHeight}}},setNativeInputValue:function(){var e=this.getInput();e&&e.value!==this.nativeInputValue&&(e.value=this.nativeInputValue)},handleFocus:function(e){this.focused=!0,this.$emit("focus",e)},handleCompositionStart:function(e){this.$emit("compositionstart",e),this.isComposing=!0},handleCompositionUpdate:function(e){this.$emit("compositionupdate",e);var t=e.target.value,n=t[t.length-1]||"";this.isComposing=!Object(p.isKorean)(n)},handleCompositionEnd:function(e){this.$emit("compositionend",e),this.isComposing&&(this.isComposing=!1,this.handleInput(e))},handleInput:function(e){this.isComposing||e.target.value!==this.nativeInputValue&&(this.$emit("input",e.target.value),this.$nextTick(this.setNativeInputValue))},handleChange:function(e){this.$emit("change",e.target.value)},calcIconOffset:function(e){var t=[].slice.call(this.$el.querySelectorAll(".el-input__"+e)||[]);if(t.length){for(var n=null,i=0;i{e.exports=function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist/",n(n.s=73)}({0:function(e,t,n){"use strict";function i(e,t,n,i,r,o,s,a){var l,c="function"==typeof e?e.options:e;if(t&&(c.render=t,c.staticRenderFns=n,c._compiled=!0),i&&(c.functional=!0),o&&(c._scopeId="data-v-"+o),s?(l=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),r&&r.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(s)},c._ssrRegister=l):r&&(l=a?function(){r.call(this,this.$root.$options.shadowRoot)}:r),l)if(c.functional){c._injectStyles=l;var u=c.render;c.render=function(e,t){return l.call(t),u(e,t)}}else{var d=c.beforeCreate;c.beforeCreate=d?[].concat(d,l):[l]}return{exports:e,options:c}}n.d(t,"a",(function(){return i}))},13:function(e,t){e.exports=n(2680)},2:function(e,t){e.exports=n(34594)},42:function(e,t){e.exports=n(79634)},7:function(e,t){e.exports=n(70538)},73:function(e,t,n){"use strict";n.r(t);var i=n(7),r=n.n(i),o=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("transition",{attrs:{name:"el-loading-fade"},on:{"after-leave":e.handleAfterLeave}},[n("div",{directives:[{name:"show",rawName:"v-show",value:e.visible,expression:"visible"}],staticClass:"el-loading-mask",class:[e.customClass,{"is-fullscreen":e.fullscreen}],style:{backgroundColor:e.background||""}},[n("div",{staticClass:"el-loading-spinner"},[e.spinner?n("i",{class:e.spinner}):n("svg",{staticClass:"circular",attrs:{viewBox:"25 25 50 50"}},[n("circle",{staticClass:"path",attrs:{cx:"50",cy:"50",r:"20",fill:"none"}})]),e.text?n("p",{staticClass:"el-loading-text"},[e._v(e._s(e.text))]):e._e()])])])};o._withStripped=!0;var s={data:function(){return{text:null,spinner:null,background:null,fullscreen:!0,visible:!1,customClass:""}},methods:{handleAfterLeave:function(){this.$emit("after-leave")},setText:function(e){this.text=e}}},a=n(0),l=Object(a.a)(s,o,[],!1,null,null,null);l.options.__file="packages/loading/src/loading.vue";var c=l.exports,u=n(2),d=n(13),f=n(42),p=n.n(f),h=r.a.extend(c),v={install:function(e){if(!e.prototype.$isServer){var t=function(t,i){i.value?e.nextTick((function(){i.modifiers.fullscreen?(t.originalPosition=Object(u.getStyle)(document.body,"position"),t.originalOverflow=Object(u.getStyle)(document.body,"overflow"),t.maskStyle.zIndex=d.PopupManager.nextZIndex(),Object(u.addClass)(t.mask,"is-fullscreen"),n(document.body,t,i)):(Object(u.removeClass)(t.mask,"is-fullscreen"),i.modifiers.body?(t.originalPosition=Object(u.getStyle)(document.body,"position"),["top","left"].forEach((function(e){var n="top"===e?"scrollTop":"scrollLeft";t.maskStyle[e]=t.getBoundingClientRect()[e]+document.body[n]+document.documentElement[n]-parseInt(Object(u.getStyle)(document.body,"margin-"+e),10)+"px"})),["height","width"].forEach((function(e){t.maskStyle[e]=t.getBoundingClientRect()[e]+"px"})),n(document.body,t,i)):(t.originalPosition=Object(u.getStyle)(t,"position"),n(t,t,i)))})):(p()(t.instance,(function(e){if(t.instance.hiding){t.domVisible=!1;var n=i.modifiers.fullscreen||i.modifiers.body?document.body:t;Object(u.removeClass)(n,"el-loading-parent--relative"),Object(u.removeClass)(n,"el-loading-parent--hidden"),t.instance.hiding=!1}}),300,!0),t.instance.visible=!1,t.instance.hiding=!0)},n=function(t,n,i){n.domVisible||"none"===Object(u.getStyle)(n,"display")||"hidden"===Object(u.getStyle)(n,"visibility")?n.domVisible&&!0===n.instance.hiding&&(n.instance.visible=!0,n.instance.hiding=!1):(Object.keys(n.maskStyle).forEach((function(e){n.mask.style[e]=n.maskStyle[e]})),"absolute"!==n.originalPosition&&"fixed"!==n.originalPosition&&"sticky"!==n.originalPosition&&Object(u.addClass)(t,"el-loading-parent--relative"),i.modifiers.fullscreen&&i.modifiers.lock&&Object(u.addClass)(t,"el-loading-parent--hidden"),n.domVisible=!0,t.appendChild(n.mask),e.nextTick((function(){n.instance.hiding?n.instance.$emit("after-leave"):n.instance.visible=!0})),n.domInserted=!0)};e.directive("loading",{bind:function(e,n,i){var r=e.getAttribute("element-loading-text"),o=e.getAttribute("element-loading-spinner"),s=e.getAttribute("element-loading-background"),a=e.getAttribute("element-loading-custom-class"),l=i.context,c=new h({el:document.createElement("div"),data:{text:l&&l[r]||r,spinner:l&&l[o]||o,background:l&&l[s]||s,customClass:l&&l[a]||a,fullscreen:!!n.modifiers.fullscreen}});e.instance=c,e.mask=c.$el,e.maskStyle={},n.value&&t(e,n)},update:function(e,n){e.instance.setText(e.getAttribute("element-loading-text")),n.oldValue!==n.value&&t(e,n)},unbind:function(e,n){e.domInserted&&(e.mask&&e.mask.parentNode&&e.mask.parentNode.removeChild(e.mask),t(e,{value:!1,modifiers:n.modifiers})),e.instance&&e.instance.$destroy()}})}}},m=v,_=n(9),g=n.n(_),b=r.a.extend(c),y={text:null,fullscreen:!0,body:!1,lock:!1,customClass:""},x=void 0;b.prototype.originalPosition="",b.prototype.originalOverflow="",b.prototype.close=function(){var e=this;this.fullscreen&&(x=void 0),p()(this,(function(t){var n=e.fullscreen||e.body?document.body:e.target;Object(u.removeClass)(n,"el-loading-parent--relative"),Object(u.removeClass)(n,"el-loading-parent--hidden"),e.$el&&e.$el.parentNode&&e.$el.parentNode.removeChild(e.$el),e.$destroy()}),300),this.visible=!1};var w=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if(!r.a.prototype.$isServer){if("string"==typeof(e=g()({},y,e)).target&&(e.target=document.querySelector(e.target)),e.target=e.target||document.body,e.target!==document.body?e.fullscreen=!1:e.body=!0,e.fullscreen&&x)return x;var t=e.body?document.body:e.target,n=new b({el:document.createElement("div"),data:e});return function(e,t,n){var i={};e.fullscreen?(n.originalPosition=Object(u.getStyle)(document.body,"position"),n.originalOverflow=Object(u.getStyle)(document.body,"overflow"),i.zIndex=d.PopupManager.nextZIndex()):e.body?(n.originalPosition=Object(u.getStyle)(document.body,"position"),["top","left"].forEach((function(t){var n="top"===t?"scrollTop":"scrollLeft";i[t]=e.target.getBoundingClientRect()[t]+document.body[n]+document.documentElement[n]+"px"})),["height","width"].forEach((function(t){i[t]=e.target.getBoundingClientRect()[t]+"px"}))):n.originalPosition=Object(u.getStyle)(t,"position"),Object.keys(i).forEach((function(e){n.$el.style[e]=i[e]}))}(e,t,n),"absolute"!==n.originalPosition&&"fixed"!==n.originalPosition&&"sticky"!==n.originalPosition&&Object(u.addClass)(t,"el-loading-parent--relative"),e.fullscreen&&e.lock&&Object(u.addClass)(t,"el-loading-parent--hidden"),t.appendChild(n.$el),r.a.nextTick((function(){n.visible=!0})),e.fullscreen&&(x=n),n}};t.default={install:function(e){e.use(m),e.prototype.$loading=w},directive:m,service:w}},9:function(e,t){e.exports=n(21615)}})},96445:(e,t,n)=>{"use strict";t.__esModule=!0;var i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};t.default=function(e){return function(e){for(var t=arguments.length,n=Array(t>1?t-1:0),s=1;s{"use strict";t.__esModule=!0,t.i18n=t.use=t.t=void 0;var i=s(n(21877)),r=s(n(70538)),o=s(n(9996));function s(e){return e&&e.__esModule?e:{default:e}}var a=(0,s(n(96445)).default)(r.default),l=i.default,c=!1,u=function(){var e=Object.getPrototypeOf(this||r.default).$t;if("function"==typeof e&&r.default.locale)return c||(c=!0,r.default.locale(r.default.config.lang,(0,o.default)(l,r.default.locale(r.default.config.lang)||{},{clone:!0}))),e.apply(this,arguments)},d=t.t=function(e,t){var n=u.apply(this,arguments);if(null!=n)return n;for(var i=e.split("."),r=l,o=0,s=i.length;o{"use strict";t.Z={el:{colorpicker:{confirm:"OK",clear:"Clear"},datepicker:{now:"Now",today:"Today",cancel:"Cancel",clear:"Clear",confirm:"OK",selectDate:"Select date",selectTime:"Select time",startDate:"Start Date",startTime:"Start Time",endDate:"End Date",endTime:"End Time",prevYear:"Previous Year",nextYear:"Next Year",prevMonth:"Previous Month",nextMonth:"Next Month",year:"",month1:"January",month2:"February",month3:"March",month4:"April",month5:"May",month6:"June",month7:"July",month8:"August",month9:"September",month10:"October",month11:"November",month12:"December",week:"week",weeks:{sun:"Sun",mon:"Mon",tue:"Tue",wed:"Wed",thu:"Thu",fri:"Fri",sat:"Sat"},months:{jan:"Jan",feb:"Feb",mar:"Mar",apr:"Apr",may:"May",jun:"Jun",jul:"Jul",aug:"Aug",sep:"Sep",oct:"Oct",nov:"Nov",dec:"Dec"}},select:{loading:"Loading",noMatch:"No matching data",noData:"No data",placeholder:"Select"},cascader:{noMatch:"No matching data",loading:"Loading",placeholder:"Select",noData:"No data"},pagination:{goto:"Go to",pagesize:"/page",total:"Total {total}",pageClassifier:""},messagebox:{title:"Message",confirm:"OK",cancel:"Cancel",error:"Illegal input"},upload:{deleteTip:"press delete to remove",delete:"Delete",preview:"Preview",continue:"Continue"},table:{emptyText:"No Data",confirmFilter:"Confirm",resetFilter:"Reset",clearFilter:"All",sumText:"Sum"},tree:{emptyText:"No Data"},transfer:{noMatch:"No matching data",noData:"No data",titles:["List 1","List 2"],filterPlaceholder:"Enter keyword",noCheckedFormat:"{total} items",hasCheckedFormat:"{checked}/{total} checked"},image:{error:"FAILED"},pageHeader:{title:"Back"},popconfirm:{confirmButtonText:"Yes",cancelButtonText:"No"},empty:{description:"No Data"}}}},21877:(e,t)=>{"use strict";t.__esModule=!0,t.default={el:{colorpicker:{confirm:"确定",clear:"清空"},datepicker:{now:"此刻",today:"今天",cancel:"取消",clear:"清空",confirm:"确定",selectDate:"选择日期",selectTime:"选择时间",startDate:"开始日期",startTime:"开始时间",endDate:"结束日期",endTime:"结束时间",prevYear:"前一年",nextYear:"后一年",prevMonth:"上个月",nextMonth:"下个月",year:"年",month1:"1 月",month2:"2 月",month3:"3 月",month4:"4 月",month5:"5 月",month6:"6 月",month7:"7 月",month8:"8 月",month9:"9 月",month10:"10 月",month11:"11 月",month12:"12 月",weeks:{sun:"日",mon:"一",tue:"二",wed:"三",thu:"四",fri:"五",sat:"六"},months:{jan:"一月",feb:"二月",mar:"三月",apr:"四月",may:"五月",jun:"六月",jul:"七月",aug:"八月",sep:"九月",oct:"十月",nov:"十一月",dec:"十二月"}},select:{loading:"加载中",noMatch:"无匹配数据",noData:"无数据",placeholder:"请选择"},cascader:{noMatch:"无匹配数据",loading:"加载中",placeholder:"请选择",noData:"暂无数据"},pagination:{goto:"前往",pagesize:"条/页",total:"共 {total} 条",pageClassifier:"页"},messagebox:{title:"提示",confirm:"确定",cancel:"取消",error:"输入的数据不合法!"},upload:{deleteTip:"按 delete 键可删除",delete:"删除",preview:"查看图片",continue:"继续上传"},table:{emptyText:"暂无数据",confirmFilter:"筛选",resetFilter:"重置",clearFilter:"全部",sumText:"合计"},tree:{emptyText:"暂无数据"},transfer:{noMatch:"无匹配数据",noData:"无数据",titles:["列表 1","列表 2"],filterPlaceholder:"请输入搜索内容",noCheckedFormat:"共 {total} 项",hasCheckedFormat:"已选 {checked}/{total} 项"},image:{error:"加载失败"},pageHeader:{title:"返回"},popconfirm:{confirmButtonText:"确定",cancelButtonText:"取消"},empty:{description:"暂无数据"}}}},16473:(e,t,n)=>{e.exports=function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist/",n(n.s=81)}({0:function(e,t,n){"use strict";function i(e,t,n,i,r,o,s,a){var l,c="function"==typeof e?e.options:e;if(t&&(c.render=t,c.staticRenderFns=n,c._compiled=!0),i&&(c.functional=!0),o&&(c._scopeId="data-v-"+o),s?(l=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),r&&r.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(s)},c._ssrRegister=l):r&&(l=a?function(){r.call(this,this.$root.$options.shadowRoot)}:r),l)if(c.functional){c._injectStyles=l;var u=c.render;c.render=function(e,t){return l.call(t),u(e,t)}}else{var d=c.beforeCreate;c.beforeCreate=d?[].concat(d,l):[l]}return{exports:e,options:c}}n.d(t,"a",(function(){return i}))},13:function(e,t){e.exports=n(2680)},17:function(e,t){e.exports=n(5389)},23:function(e,t){e.exports=n(54823)},7:function(e,t){e.exports=n(70538)},81:function(e,t,n){"use strict";n.r(t);var i=n(7),r=n.n(i),o=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("transition",{attrs:{name:"el-message-fade"},on:{"after-leave":e.handleAfterLeave}},[n("div",{directives:[{name:"show",rawName:"v-show",value:e.visible,expression:"visible"}],class:["el-message",e.type&&!e.iconClass?"el-message--"+e.type:"",e.center?"is-center":"",e.showClose?"is-closable":"",e.customClass],style:e.positionStyle,attrs:{role:"alert"},on:{mouseenter:e.clearTimer,mouseleave:e.startTimer}},[e.iconClass?n("i",{class:e.iconClass}):n("i",{class:e.typeClass}),e._t("default",[e.dangerouslyUseHTMLString?n("p",{staticClass:"el-message__content",domProps:{innerHTML:e._s(e.message)}}):n("p",{staticClass:"el-message__content"},[e._v(e._s(e.message))])]),e.showClose?n("i",{staticClass:"el-message__closeBtn el-icon-close",on:{click:e.close}}):e._e()],2)])};o._withStripped=!0;var s={success:"success",info:"info",warning:"warning",error:"error"},a={data:function(){return{visible:!1,message:"",duration:3e3,type:"info",iconClass:"",customClass:"",onClose:null,showClose:!1,closed:!1,verticalOffset:20,timer:null,dangerouslyUseHTMLString:!1,center:!1}},computed:{typeClass:function(){return this.type&&!this.iconClass?"el-message__icon el-icon-"+s[this.type]:""},positionStyle:function(){return{top:this.verticalOffset+"px"}}},watch:{closed:function(e){e&&(this.visible=!1)}},methods:{handleAfterLeave:function(){this.$destroy(!0),this.$el.parentNode.removeChild(this.$el)},close:function(){this.closed=!0,"function"==typeof this.onClose&&this.onClose(this)},clearTimer:function(){clearTimeout(this.timer)},startTimer:function(){var e=this;this.duration>0&&(this.timer=setTimeout((function(){e.closed||e.close()}),this.duration))},keydown:function(e){27===e.keyCode&&(this.closed||this.close())}},mounted:function(){this.startTimer(),document.addEventListener("keydown",this.keydown)},beforeDestroy:function(){document.removeEventListener("keydown",this.keydown)}},l=n(0),c=Object(l.a)(a,o,[],!1,null,null,null);c.options.__file="packages/message/src/main.vue";var u=c.exports,d=n(13),f=n(23),p=n(17),h=Object.assign||function(e){for(var t=1;t_.length-1))for(var s=i;s=0;e--)_[e].close()};var y=b;t.default=y}})},52477:(e,t)=>{"use strict";function n(e,t,i){this.$children.forEach((function(r){r.$options.componentName===e?r.$emit.apply(r,[t].concat(i)):n.apply(r,[e,t].concat([i]))}))}t.__esModule=!0,t.default={methods:{dispatch:function(e,t,n){for(var i=this.$parent||this.$root,r=i.$options.componentName;i&&(!r||r!==e);)(i=i.$parent)&&(r=i.$options.componentName);i&&i.$emit.apply(i,[t].concat(n))},broadcast:function(e,t,i){n.call(this,e,t,i)}}}},98618:(e,t)=>{"use strict";t.__esModule=!0,t.default=function(e){return{methods:{focus:function(){this.$refs[e].focus()}}}}},52084:(e,t,n)=>{"use strict";t.__esModule=!0;var i=n(1802);t.default={methods:{t:function(){for(var e=arguments.length,t=Array(e),n=0;n{"use strict";t.__esModule=!0;n(93104);t.default={mounted:function(){},methods:{getMigratingConfig:function(){return{props:{},events:{}}}}}},30272:(e,t,n)=>{e.exports=function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist/",n(n.s=80)}({0:function(e,t,n){"use strict";function i(e,t,n,i,r,o,s,a){var l,c="function"==typeof e?e.options:e;if(t&&(c.render=t,c.staticRenderFns=n,c._compiled=!0),i&&(c.functional=!0),o&&(c._scopeId="data-v-"+o),s?(l=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),r&&r.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(s)},c._ssrRegister=l):r&&(l=a?function(){r.call(this,this.$root.$options.shadowRoot)}:r),l)if(c.functional){c._injectStyles=l;var u=c.render;c.render=function(e,t){return l.call(t),u(e,t)}}else{var d=c.beforeCreate;c.beforeCreate=d?[].concat(d,l):[l]}return{exports:e,options:c}}n.d(t,"a",(function(){return i}))},13:function(e,t){e.exports=n(2680)},23:function(e,t){e.exports=n(54823)},7:function(e,t){e.exports=n(70538)},80:function(e,t,n){"use strict";n.r(t);var i=n(7),r=n.n(i),o=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("transition",{attrs:{name:"el-notification-fade"}},[n("div",{directives:[{name:"show",rawName:"v-show",value:e.visible,expression:"visible"}],class:["el-notification",e.customClass,e.horizontalClass],style:e.positionStyle,attrs:{role:"alert"},on:{mouseenter:function(t){e.clearTimer()},mouseleave:function(t){e.startTimer()},click:e.click}},[e.type||e.iconClass?n("i",{staticClass:"el-notification__icon",class:[e.typeClass,e.iconClass]}):e._e(),n("div",{staticClass:"el-notification__group",class:{"is-with-icon":e.typeClass||e.iconClass}},[n("h2",{staticClass:"el-notification__title",domProps:{textContent:e._s(e.title)}}),n("div",{directives:[{name:"show",rawName:"v-show",value:e.message,expression:"message"}],staticClass:"el-notification__content"},[e._t("default",[e.dangerouslyUseHTMLString?n("p",{domProps:{innerHTML:e._s(e.message)}}):n("p",[e._v(e._s(e.message))])])],2),e.showClose?n("div",{staticClass:"el-notification__closeBtn el-icon-close",on:{click:function(t){return t.stopPropagation(),e.close(t)}}}):e._e()])])])};o._withStripped=!0;var s={success:"success",info:"info",warning:"warning",error:"error"},a={data:function(){return{visible:!1,title:"",message:"",duration:4500,type:"",showClose:!0,customClass:"",iconClass:"",onClose:null,onClick:null,closed:!1,verticalOffset:0,timer:null,dangerouslyUseHTMLString:!1,position:"top-right"}},computed:{typeClass:function(){return this.type&&s[this.type]?"el-icon-"+s[this.type]:""},horizontalClass:function(){return this.position.indexOf("right")>-1?"right":"left"},verticalProperty:function(){return/^top-/.test(this.position)?"top":"bottom"},positionStyle:function(){var e;return(e={})[this.verticalProperty]=this.verticalOffset+"px",e}},watch:{closed:function(e){e&&(this.visible=!1,this.$el.addEventListener("transitionend",this.destroyElement))}},methods:{destroyElement:function(){this.$el.removeEventListener("transitionend",this.destroyElement),this.$destroy(!0),this.$el.parentNode.removeChild(this.$el)},click:function(){"function"==typeof this.onClick&&this.onClick()},close:function(){this.closed=!0,"function"==typeof this.onClose&&this.onClose()},clearTimer:function(){clearTimeout(this.timer)},startTimer:function(){var e=this;this.duration>0&&(this.timer=setTimeout((function(){e.closed||e.close()}),this.duration))},keydown:function(e){46===e.keyCode||8===e.keyCode?this.clearTimer():27===e.keyCode?this.closed||this.close():this.startTimer()}},mounted:function(){var e=this;this.duration>0&&(this.timer=setTimeout((function(){e.closed||e.close()}),this.duration)),document.addEventListener("keydown",this.keydown)},beforeDestroy:function(){document.removeEventListener("keydown",this.keydown)}},l=n(0),c=Object(l.a)(a,o,[],!1,null,null,null);c.options.__file="packages/notification/src/main.vue";var u=c.exports,d=n(9),f=n.n(d),p=n(13),h=n(23),v=r.a.extend(u),m=void 0,_=[],g=1,b=function e(t){if(!r.a.prototype.$isServer){var n=(t=f()({},t)).onClose,i="notification_"+g++,o=t.position||"top-right";t.onClose=function(){e.close(i,n)},m=new v({data:t}),Object(h.isVNode)(t.message)&&(m.$slots.default=[t.message],t.message="REPLACED_BY_VNODE"),m.id=i,m.$mount(),document.body.appendChild(m.$el),m.visible=!0,m.dom=m.$el,m.dom.style.zIndex=p.PopupManager.nextZIndex();var s=t.offset||0;return _.filter((function(e){return e.position===o})).forEach((function(e){s+=e.$el.offsetHeight+16})),s+=16,m.verticalOffset=s,_.push(m),m}};["success","warning","info","error"].forEach((function(e){b[e]=function(t){return("string"==typeof t||Object(h.isVNode)(t))&&(t={message:t}),t.type=e,b(t)}})),b.close=function(e,t){var n=-1,i=_.length,r=_.filter((function(t,i){return t.id===e&&(n=i,!0)}))[0];if(r&&("function"==typeof t&&t(r),_.splice(n,1),!(i<=1)))for(var o=r.position,s=r.dom.offsetHeight,a=n;a=0;e--)_[e].close()};var y=b;t.default=y},9:function(e,t){e.exports=n(21615)}})},34354:(e,t,n)=>{e.exports=function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist/",n(n.s=95)}({0:function(e,t,n){"use strict";function i(e,t,n,i,r,o,s,a){var l,c="function"==typeof e?e.options:e;if(t&&(c.render=t,c.staticRenderFns=n,c._compiled=!0),i&&(c.functional=!0),o&&(c._scopeId="data-v-"+o),s?(l=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),r&&r.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(s)},c._ssrRegister=l):r&&(l=a?function(){r.call(this,this.$root.$options.shadowRoot)}:r),l)if(c.functional){c._injectStyles=l;var u=c.render;c.render=function(e,t){return l.call(t),u(e,t)}}else{var d=c.beforeCreate;c.beforeCreate=d?[].concat(d,l):[l]}return{exports:e,options:c}}n.d(t,"a",(function(){return i}))},4:function(e,t){e.exports=n(52477)},95:function(e,t,n){"use strict";n.r(t);var i=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("ul",{directives:[{name:"show",rawName:"v-show",value:e.visible,expression:"visible"}],staticClass:"el-select-group__wrap"},[n("li",{staticClass:"el-select-group__title"},[e._v(e._s(e.label))]),n("li",[n("ul",{staticClass:"el-select-group"},[e._t("default")],2)])])};i._withStripped=!0;var r=n(4),o={mixins:[n.n(r).a],name:"ElOptionGroup",componentName:"ElOptionGroup",props:{label:String,disabled:{type:Boolean,default:!1}},data:function(){return{visible:!0}},watch:{disabled:function(e){this.broadcast("ElOption","handleGroupDisabled",e)}},methods:{queryChange:function(){this.visible=this.$children&&Array.isArray(this.$children)&&this.$children.some((function(e){return!0===e.visible}))}},created:function(){this.$on("queryChange",this.queryChange)},mounted:function(){this.disabled&&this.broadcast("ElOption","handleGroupDisabled",this.disabled)}},s=n(0),a=Object(s.a)(o,i,[],!1,null,null,null);a.options.__file="packages/select/src/option-group.vue";var l=a.exports;l.install=function(e){e.component(l.name,l)};t.default=l}})},45614:(e,t,n)=>{e.exports=function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist/",n(n.s=54)}({0:function(e,t,n){"use strict";function i(e,t,n,i,r,o,s,a){var l,c="function"==typeof e?e.options:e;if(t&&(c.render=t,c.staticRenderFns=n,c._compiled=!0),i&&(c.functional=!0),o&&(c._scopeId="data-v-"+o),s?(l=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),r&&r.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(s)},c._ssrRegister=l):r&&(l=a?function(){r.call(this,this.$root.$options.shadowRoot)}:r),l)if(c.functional){c._injectStyles=l;var u=c.render;c.render=function(e,t){return l.call(t),u(e,t)}}else{var d=c.beforeCreate;c.beforeCreate=d?[].concat(d,l):[l]}return{exports:e,options:c}}n.d(t,"a",(function(){return i}))},3:function(e,t){e.exports=n(93104)},33:function(e,t,n){"use strict";var i=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("li",{directives:[{name:"show",rawName:"v-show",value:e.visible,expression:"visible"}],staticClass:"el-select-dropdown__item",class:{selected:e.itemSelected,"is-disabled":e.disabled||e.groupDisabled||e.limitReached,hover:e.hover},on:{mouseenter:e.hoverItem,click:function(t){return t.stopPropagation(),e.selectOptionClick(t)}}},[e._t("default",[n("span",[e._v(e._s(e.currentLabel))])])],2)};i._withStripped=!0;var r=n(4),o=n.n(r),s=n(3),a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},l={mixins:[o.a],name:"ElOption",componentName:"ElOption",inject:["select"],props:{value:{required:!0},label:[String,Number],created:Boolean,disabled:{type:Boolean,default:!1}},data:function(){return{index:-1,groupDisabled:!1,visible:!0,hitState:!1,hover:!1}},computed:{isObject:function(){return"[object object]"===Object.prototype.toString.call(this.value).toLowerCase()},currentLabel:function(){return this.label||(this.isObject?"":this.value)},currentValue:function(){return this.value||this.label||""},itemSelected:function(){return this.select.multiple?this.contains(this.select.value,this.value):this.isEqual(this.value,this.select.value)},limitReached:function(){return!!this.select.multiple&&(!this.itemSelected&&(this.select.value||[]).length>=this.select.multipleLimit&&this.select.multipleLimit>0)}},watch:{currentLabel:function(){this.created||this.select.remote||this.dispatch("ElSelect","setSelected")},value:function(e,t){var n=this.select,i=n.remote,r=n.valueKey;if(!this.created&&!i){if(r&&"object"===(void 0===e?"undefined":a(e))&&"object"===(void 0===t?"undefined":a(t))&&e[r]===t[r])return;this.dispatch("ElSelect","setSelected")}}},methods:{isEqual:function(e,t){if(this.isObject){var n=this.select.valueKey;return Object(s.getValueByPath)(e,n)===Object(s.getValueByPath)(t,n)}return e===t},contains:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t=arguments[1];if(this.isObject){var n=this.select.valueKey;return e&&e.some((function(e){return Object(s.getValueByPath)(e,n)===Object(s.getValueByPath)(t,n)}))}return e&&e.indexOf(t)>-1},handleGroupDisabled:function(e){this.groupDisabled=e},hoverItem:function(){this.disabled||this.groupDisabled||(this.select.hoverIndex=this.select.options.indexOf(this))},selectOptionClick:function(){!0!==this.disabled&&!0!==this.groupDisabled&&this.dispatch("ElSelect","handleOptionClick",[this,!0])},queryChange:function(e){this.visible=new RegExp(Object(s.escapeRegexpString)(e),"i").test(this.currentLabel)||this.created,this.visible||this.select.filteredOptionsCount--}},created:function(){this.select.options.push(this),this.select.cachedOptions.push(this),this.select.optionsCount++,this.select.filteredOptionsCount++,this.$on("queryChange",this.queryChange),this.$on("handleGroupDisabled",this.handleGroupDisabled)},beforeDestroy:function(){var e=this.select,t=e.selected,n=e.multiple?t:[t],i=this.select.cachedOptions.indexOf(this),r=n.indexOf(this);i>-1&&r<0&&this.select.cachedOptions.splice(i,1),this.select.onOptionDestroy(this.select.options.indexOf(this))}},c=l,u=n(0),d=Object(u.a)(c,i,[],!1,null,null,null);d.options.__file="packages/select/src/option.vue";t.a=d.exports},4:function(e,t){e.exports=n(52477)},54:function(e,t,n){"use strict";n.r(t);var i=n(33);i.a.install=function(e){e.component(i.a.name,i.a)},t.default=i.a}})},24650:(e,t,n)=>{e.exports=function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist/",n(n.s=78)}({0:function(e,t,n){"use strict";function i(e,t,n,i,r,o,s,a){var l,c="function"==typeof e?e.options:e;if(t&&(c.render=t,c.staticRenderFns=n,c._compiled=!0),i&&(c.functional=!0),o&&(c._scopeId="data-v-"+o),s?(l=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),r&&r.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(s)},c._ssrRegister=l):r&&(l=a?function(){r.call(this,this.$root.$options.shadowRoot)}:r),l)if(c.functional){c._injectStyles=l;var u=c.render;c.render=function(e,t){return l.call(t),u(e,t)}}else{var d=c.beforeCreate;c.beforeCreate=d?[].concat(d,l):[l]}return{exports:e,options:c}}n.d(t,"a",(function(){return i}))},2:function(e,t){e.exports=n(34594)},3:function(e,t){e.exports=n(93104)},5:function(e,t){e.exports=n(70499)},7:function(e,t){e.exports=n(70538)},78:function(e,t,n){"use strict";n.r(t);var i=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("span",[n("transition",{attrs:{name:e.transition},on:{"after-enter":e.handleAfterEnter,"after-leave":e.handleAfterLeave}},[n("div",{directives:[{name:"show",rawName:"v-show",value:!e.disabled&&e.showPopper,expression:"!disabled && showPopper"}],ref:"popper",staticClass:"el-popover el-popper",class:[e.popperClass,e.content&&"el-popover--plain"],style:{width:e.width+"px"},attrs:{role:"tooltip",id:e.tooltipId,"aria-hidden":e.disabled||!e.showPopper?"true":"false"}},[e.title?n("div",{staticClass:"el-popover__title",domProps:{textContent:e._s(e.title)}}):e._e(),e._t("default",[e._v(e._s(e.content))])],2)]),n("span",{ref:"wrapper",staticClass:"el-popover__reference-wrapper"},[e._t("reference")],2)],1)};i._withStripped=!0;var r=n(5),o=n.n(r),s=n(2),a=n(3),l={name:"ElPopover",mixins:[o.a],props:{trigger:{type:String,default:"click",validator:function(e){return["click","focus","hover","manual"].indexOf(e)>-1}},openDelay:{type:Number,default:0},closeDelay:{type:Number,default:200},title:String,disabled:Boolean,content:String,reference:{},popperClass:String,width:{},visibleArrow:{default:!0},arrowOffset:{type:Number,default:0},transition:{type:String,default:"fade-in-linear"},tabindex:{type:Number,default:0}},computed:{tooltipId:function(){return"el-popover-"+Object(a.generateId)()}},watch:{showPopper:function(e){this.disabled||(e?this.$emit("show"):this.$emit("hide"))}},mounted:function(){var e=this,t=this.referenceElm=this.reference||this.$refs.reference,n=this.popper||this.$refs.popper;!t&&this.$refs.wrapper.children&&(t=this.referenceElm=this.$refs.wrapper.children[0]),t&&(Object(s.addClass)(t,"el-popover__reference"),t.setAttribute("aria-describedby",this.tooltipId),t.setAttribute("tabindex",this.tabindex),n.setAttribute("tabindex",0),"click"!==this.trigger&&(Object(s.on)(t,"focusin",(function(){e.handleFocus();var n=t.__vue__;n&&"function"==typeof n.focus&&n.focus()})),Object(s.on)(n,"focusin",this.handleFocus),Object(s.on)(t,"focusout",this.handleBlur),Object(s.on)(n,"focusout",this.handleBlur)),Object(s.on)(t,"keydown",this.handleKeydown),Object(s.on)(t,"click",this.handleClick)),"click"===this.trigger?(Object(s.on)(t,"click",this.doToggle),Object(s.on)(document,"click",this.handleDocumentClick)):"hover"===this.trigger?(Object(s.on)(t,"mouseenter",this.handleMouseEnter),Object(s.on)(n,"mouseenter",this.handleMouseEnter),Object(s.on)(t,"mouseleave",this.handleMouseLeave),Object(s.on)(n,"mouseleave",this.handleMouseLeave)):"focus"===this.trigger&&(this.tabindex<0&&console.warn("[Element Warn][Popover]a negative taindex means that the element cannot be focused by tab key"),t.querySelector("input, textarea")?(Object(s.on)(t,"focusin",this.doShow),Object(s.on)(t,"focusout",this.doClose)):(Object(s.on)(t,"mousedown",this.doShow),Object(s.on)(t,"mouseup",this.doClose)))},beforeDestroy:function(){this.cleanup()},deactivated:function(){this.cleanup()},methods:{doToggle:function(){this.showPopper=!this.showPopper},doShow:function(){this.showPopper=!0},doClose:function(){this.showPopper=!1},handleFocus:function(){Object(s.addClass)(this.referenceElm,"focusing"),"click"!==this.trigger&&"focus"!==this.trigger||(this.showPopper=!0)},handleClick:function(){Object(s.removeClass)(this.referenceElm,"focusing")},handleBlur:function(){Object(s.removeClass)(this.referenceElm,"focusing"),"click"!==this.trigger&&"focus"!==this.trigger||(this.showPopper=!1)},handleMouseEnter:function(){var e=this;clearTimeout(this._timer),this.openDelay?this._timer=setTimeout((function(){e.showPopper=!0}),this.openDelay):this.showPopper=!0},handleKeydown:function(e){27===e.keyCode&&"manual"!==this.trigger&&this.doClose()},handleMouseLeave:function(){var e=this;clearTimeout(this._timer),this.closeDelay?this._timer=setTimeout((function(){e.showPopper=!1}),this.closeDelay):this.showPopper=!1},handleDocumentClick:function(e){var t=this.reference||this.$refs.reference,n=this.popper||this.$refs.popper;!t&&this.$refs.wrapper.children&&(t=this.referenceElm=this.$refs.wrapper.children[0]),this.$el&&t&&!this.$el.contains(e.target)&&!t.contains(e.target)&&n&&!n.contains(e.target)&&(this.showPopper=!1)},handleAfterEnter:function(){this.$emit("after-enter")},handleAfterLeave:function(){this.$emit("after-leave"),this.doDestroy()},cleanup:function(){(this.openDelay||this.closeDelay)&&clearTimeout(this._timer)}},destroyed:function(){var e=this.reference;Object(s.off)(e,"click",this.doToggle),Object(s.off)(e,"mouseup",this.doClose),Object(s.off)(e,"mousedown",this.doShow),Object(s.off)(e,"focusin",this.doShow),Object(s.off)(e,"focusout",this.doClose),Object(s.off)(e,"mousedown",this.doShow),Object(s.off)(e,"mouseup",this.doClose),Object(s.off)(e,"mouseleave",this.handleMouseLeave),Object(s.off)(e,"mouseenter",this.handleMouseEnter),Object(s.off)(document,"click",this.handleDocumentClick)}},c=n(0),u=Object(c.a)(l,i,[],!1,null,null,null);u.options.__file="packages/popover/src/main.vue";var d=u.exports,f=function(e,t,n){var i=t.expression?t.value:t.arg,r=n.context.$refs[i];r&&(Array.isArray(r)?r[0].$refs.reference=e:r.$refs.reference=e)},p={bind:function(e,t,n){f(e,t,n)},inserted:function(e,t,n){f(e,t,n)}},h=n(7);n.n(h).a.directive("popover",p),d.install=function(e){e.directive("popover",p),e.component(d.name,d)},d.directive=p;t.default=d}})},81337:(e,t,n)=>{e.exports=function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist/",n(n.s=89)}({0:function(e,t,n){"use strict";function i(e,t,n,i,r,o,s,a){var l,c="function"==typeof e?e.options:e;if(t&&(c.render=t,c.staticRenderFns=n,c._compiled=!0),i&&(c.functional=!0),o&&(c._scopeId="data-v-"+o),s?(l=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),r&&r.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(s)},c._ssrRegister=l):r&&(l=a?function(){r.call(this,this.$root.$options.shadowRoot)}:r),l)if(c.functional){c._injectStyles=l;var u=c.render;c.render=function(e,t){return l.call(t),u(e,t)}}else{var d=c.beforeCreate;c.beforeCreate=d?[].concat(d,l):[l]}return{exports:e,options:c}}n.d(t,"a",(function(){return i}))},4:function(e,t){e.exports=n(52477)},89:function(e,t,n){"use strict";n.r(t);var i=function(){var e=this,t=e.$createElement;return(e._self._c||t)(e._elTag,{tag:"component",staticClass:"el-radio-group",attrs:{role:"radiogroup"},on:{keydown:e.handleKeydown}},[e._t("default")],2)};i._withStripped=!0;var r=n(4),o=n.n(r),s=Object.freeze({LEFT:37,UP:38,RIGHT:39,DOWN:40}),a={name:"ElRadioGroup",componentName:"ElRadioGroup",inject:{elFormItem:{default:""}},mixins:[o.a],props:{value:{},size:String,fill:String,textColor:String,disabled:Boolean},computed:{_elFormItemSize:function(){return(this.elFormItem||{}).elFormItemSize},_elTag:function(){var e=(this.$vnode.data||{}).tag;return e&&"component"!==e||(e="div"),e},radioGroupSize:function(){return this.size||this._elFormItemSize||(this.$ELEMENT||{}).size}},created:function(){var e=this;this.$on("handleChange",(function(t){e.$emit("change",t)}))},mounted:function(){var e=this.$el.querySelectorAll("[type=radio]"),t=this.$el.querySelectorAll("[role=radio]")[0];![].some.call(e,(function(e){return e.checked}))&&t&&(t.tabIndex=0)},methods:{handleKeydown:function(e){var t=e.target,n="INPUT"===t.nodeName?"[type=radio]":"[role=radio]",i=this.$el.querySelectorAll(n),r=i.length,o=[].indexOf.call(i,t),a=this.$el.querySelectorAll("[role=radio]");switch(e.keyCode){case s.LEFT:case s.UP:e.stopPropagation(),e.preventDefault(),0===o?(a[r-1].click(),a[r-1].focus()):(a[o-1].click(),a[o-1].focus());break;case s.RIGHT:case s.DOWN:o===r-1?(e.stopPropagation(),e.preventDefault(),a[0].click(),a[0].focus()):(a[o+1].click(),a[o+1].focus())}}},watch:{value:function(e){this.dispatch("ElFormItem","el.form.change",[this.value])}}},l=n(0),c=Object(l.a)(a,i,[],!1,null,null,null);c.options.__file="packages/radio/src/radio-group.vue";var u=c.exports;u.install=function(e){e.component(u.name,u)};t.default=u}})},41955:(e,t,n)=>{e.exports=function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist/",n(n.s=88)}({0:function(e,t,n){"use strict";function i(e,t,n,i,r,o,s,a){var l,c="function"==typeof e?e.options:e;if(t&&(c.render=t,c.staticRenderFns=n,c._compiled=!0),i&&(c.functional=!0),o&&(c._scopeId="data-v-"+o),s?(l=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),r&&r.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(s)},c._ssrRegister=l):r&&(l=a?function(){r.call(this,this.$root.$options.shadowRoot)}:r),l)if(c.functional){c._injectStyles=l;var u=c.render;c.render=function(e,t){return l.call(t),u(e,t)}}else{var d=c.beforeCreate;c.beforeCreate=d?[].concat(d,l):[l]}return{exports:e,options:c}}n.d(t,"a",(function(){return i}))},4:function(e,t){e.exports=n(52477)},88:function(e,t,n){"use strict";n.r(t);var i=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("label",{staticClass:"el-radio",class:[e.border&&e.radioSize?"el-radio--"+e.radioSize:"",{"is-disabled":e.isDisabled},{"is-focus":e.focus},{"is-bordered":e.border},{"is-checked":e.model===e.label}],attrs:{role:"radio","aria-checked":e.model===e.label,"aria-disabled":e.isDisabled,tabindex:e.tabIndex},on:{keydown:function(t){if(!("button"in t)&&e._k(t.keyCode,"space",32,t.key,[" ","Spacebar"]))return null;t.stopPropagation(),t.preventDefault(),e.model=e.isDisabled?e.model:e.label}}},[n("span",{staticClass:"el-radio__input",class:{"is-disabled":e.isDisabled,"is-checked":e.model===e.label}},[n("span",{staticClass:"el-radio__inner"}),n("input",{directives:[{name:"model",rawName:"v-model",value:e.model,expression:"model"}],ref:"radio",staticClass:"el-radio__original",attrs:{type:"radio","aria-hidden":"true",name:e.name,disabled:e.isDisabled,tabindex:"-1",autocomplete:"off"},domProps:{value:e.label,checked:e._q(e.model,e.label)},on:{focus:function(t){e.focus=!0},blur:function(t){e.focus=!1},change:[function(t){e.model=e.label},e.handleChange]}})]),n("span",{staticClass:"el-radio__label",on:{keydown:function(e){e.stopPropagation()}}},[e._t("default"),e.$slots.default?e._e():[e._v(e._s(e.label))]],2)])};i._withStripped=!0;var r=n(4),o={name:"ElRadio",mixins:[n.n(r).a],inject:{elForm:{default:""},elFormItem:{default:""}},componentName:"ElRadio",props:{value:{},label:{},disabled:Boolean,name:String,border:Boolean,size:String},data:function(){return{focus:!1}},computed:{isGroup:function(){for(var e=this.$parent;e;){if("ElRadioGroup"===e.$options.componentName)return this._radioGroup=e,!0;e=e.$parent}return!1},model:{get:function(){return this.isGroup?this._radioGroup.value:this.value},set:function(e){this.isGroup?this.dispatch("ElRadioGroup","input",[e]):this.$emit("input",e),this.$refs.radio&&(this.$refs.radio.checked=this.model===this.label)}},_elFormItemSize:function(){return(this.elFormItem||{}).elFormItemSize},radioSize:function(){var e=this.size||this._elFormItemSize||(this.$ELEMENT||{}).size;return this.isGroup&&this._radioGroup.radioGroupSize||e},isDisabled:function(){return this.isGroup?this._radioGroup.disabled||this.disabled||(this.elForm||{}).disabled:this.disabled||(this.elForm||{}).disabled},tabIndex:function(){return this.isDisabled||this.isGroup&&this.model!==this.label?-1:0}},methods:{handleChange:function(){var e=this;this.$nextTick((function(){e.$emit("change",e.model),e.isGroup&&e.dispatch("ElRadioGroup","handleChange",e.model)}))}}},s=n(0),a=Object(s.a)(o,i,[],!1,null,null,null);a.options.__file="packages/radio/src/radio.vue";var l=a.exports;l.install=function(e){e.component(l.name,l)};t.default=l}})},47122:(e,t,n)=>{e.exports=function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist/",n(n.s=133)}({133:function(e,t,n){"use strict";n.r(t);var i=n(16),r=n(39),o=n.n(r),s=n(3),a=n(2),l={vertical:{offset:"offsetHeight",scroll:"scrollTop",scrollSize:"scrollHeight",size:"height",key:"vertical",axis:"Y",client:"clientY",direction:"top"},horizontal:{offset:"offsetWidth",scroll:"scrollLeft",scrollSize:"scrollWidth",size:"width",key:"horizontal",axis:"X",client:"clientX",direction:"left"}};function c(e){var t=e.move,n=e.size,i=e.bar,r={},o="translate"+i.axis+"("+t+"%)";return r[i.size]=n,r.transform=o,r.msTransform=o,r.webkitTransform=o,r}var u={name:"Bar",props:{vertical:Boolean,size:String,move:Number},computed:{bar:function(){return l[this.vertical?"vertical":"horizontal"]},wrap:function(){return this.$parent.wrap}},render:function(e){var t=this.size,n=this.move,i=this.bar;return e("div",{class:["el-scrollbar__bar","is-"+i.key],on:{mousedown:this.clickTrackHandler}},[e("div",{ref:"thumb",class:"el-scrollbar__thumb",on:{mousedown:this.clickThumbHandler},style:c({size:t,move:n,bar:i})})])},methods:{clickThumbHandler:function(e){e.ctrlKey||2===e.button||(this.startDrag(e),this[this.bar.axis]=e.currentTarget[this.bar.offset]-(e[this.bar.client]-e.currentTarget.getBoundingClientRect()[this.bar.direction]))},clickTrackHandler:function(e){var t=100*(Math.abs(e.target.getBoundingClientRect()[this.bar.direction]-e[this.bar.client])-this.$refs.thumb[this.bar.offset]/2)/this.$el[this.bar.offset];this.wrap[this.bar.scroll]=t*this.wrap[this.bar.scrollSize]/100},startDrag:function(e){e.stopImmediatePropagation(),this.cursorDown=!0,Object(a.on)(document,"mousemove",this.mouseMoveDocumentHandler),Object(a.on)(document,"mouseup",this.mouseUpDocumentHandler),document.onselectstart=function(){return!1}},mouseMoveDocumentHandler:function(e){if(!1!==this.cursorDown){var t=this[this.bar.axis];if(t){var n=100*(-1*(this.$el.getBoundingClientRect()[this.bar.direction]-e[this.bar.client])-(this.$refs.thumb[this.bar.offset]-t))/this.$el[this.bar.offset];this.wrap[this.bar.scroll]=n*this.wrap[this.bar.scrollSize]/100}}},mouseUpDocumentHandler:function(e){this.cursorDown=!1,this[this.bar.axis]=0,Object(a.off)(document,"mousemove",this.mouseMoveDocumentHandler),document.onselectstart=null}},destroyed:function(){Object(a.off)(document,"mouseup",this.mouseUpDocumentHandler)}},d={name:"ElScrollbar",components:{Bar:u},props:{native:Boolean,wrapStyle:{},wrapClass:{},viewClass:{},viewStyle:{},noresize:Boolean,tag:{type:String,default:"div"}},data:function(){return{sizeWidth:"0",sizeHeight:"0",moveX:0,moveY:0}},computed:{wrap:function(){return this.$refs.wrap}},render:function(e){var t=o()(),n=this.wrapStyle;if(t){var i="-"+t+"px",r="margin-bottom: "+i+"; margin-right: "+i+";";Array.isArray(this.wrapStyle)?(n=Object(s.toObject)(this.wrapStyle)).marginRight=n.marginBottom=i:"string"==typeof this.wrapStyle?n+=r:n=r}var a=e(this.tag,{class:["el-scrollbar__view",this.viewClass],style:this.viewStyle,ref:"resize"},this.$slots.default),l=e("div",{ref:"wrap",style:n,on:{scroll:this.handleScroll},class:[this.wrapClass,"el-scrollbar__wrap",t?"":"el-scrollbar__wrap--hidden-default"]},[[a]]),c=void 0;return c=this.native?[e("div",{ref:"wrap",class:[this.wrapClass,"el-scrollbar__wrap"],style:n},[[a]])]:[l,e(u,{attrs:{move:this.moveX,size:this.sizeWidth}}),e(u,{attrs:{vertical:!0,move:this.moveY,size:this.sizeHeight}})],e("div",{class:"el-scrollbar"},c)},methods:{handleScroll:function(){var e=this.wrap;this.moveY=100*e.scrollTop/e.clientHeight,this.moveX=100*e.scrollLeft/e.clientWidth},update:function(){var e,t,n=this.wrap;n&&(e=100*n.clientHeight/n.scrollHeight,t=100*n.clientWidth/n.scrollWidth,this.sizeHeight=e<100?e+"%":"",this.sizeWidth=t<100?t+"%":"")}},mounted:function(){this.native||(this.$nextTick(this.update),!this.noresize&&Object(i.addResizeListener)(this.$refs.resize,this.update))},beforeDestroy:function(){this.native||!this.noresize&&Object(i.removeResizeListener)(this.$refs.resize,this.update)},install:function(e){e.component(d.name,d)}};t.default=d},16:function(e,t){e.exports=n(16567)},2:function(e,t){e.exports=n(34594)},3:function(e,t){e.exports=n(93104)},39:function(e,t){e.exports=n(81301)}})},67186:(e,t,n)=>{e.exports=function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist/",n(n.s=62)}({0:function(e,t,n){"use strict";function i(e,t,n,i,r,o,s,a){var l,c="function"==typeof e?e.options:e;if(t&&(c.render=t,c.staticRenderFns=n,c._compiled=!0),i&&(c.functional=!0),o&&(c._scopeId="data-v-"+o),s?(l=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),r&&r.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(s)},c._ssrRegister=l):r&&(l=a?function(){r.call(this,this.$root.$options.shadowRoot)}:r),l)if(c.functional){c._injectStyles=l;var u=c.render;c.render=function(e,t){return l.call(t),u(e,t)}}else{var d=c.beforeCreate;c.beforeCreate=d?[].concat(d,l):[l]}return{exports:e,options:c}}n.d(t,"a",(function(){return i}))},10:function(e,t){e.exports=n(7626)},12:function(e,t){e.exports=n(1080)},15:function(e,t){e.exports=n(47122)},16:function(e,t){e.exports=n(16567)},19:function(e,t){e.exports=n(42823)},21:function(e,t){e.exports=n(50167)},22:function(e,t){e.exports=n(98618)},3:function(e,t){e.exports=n(93104)},31:function(e,t){e.exports=n(78275)},33:function(e,t,n){"use strict";var i=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("li",{directives:[{name:"show",rawName:"v-show",value:e.visible,expression:"visible"}],staticClass:"el-select-dropdown__item",class:{selected:e.itemSelected,"is-disabled":e.disabled||e.groupDisabled||e.limitReached,hover:e.hover},on:{mouseenter:e.hoverItem,click:function(t){return t.stopPropagation(),e.selectOptionClick(t)}}},[e._t("default",[n("span",[e._v(e._s(e.currentLabel))])])],2)};i._withStripped=!0;var r=n(4),o=n.n(r),s=n(3),a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},l={mixins:[o.a],name:"ElOption",componentName:"ElOption",inject:["select"],props:{value:{required:!0},label:[String,Number],created:Boolean,disabled:{type:Boolean,default:!1}},data:function(){return{index:-1,groupDisabled:!1,visible:!0,hitState:!1,hover:!1}},computed:{isObject:function(){return"[object object]"===Object.prototype.toString.call(this.value).toLowerCase()},currentLabel:function(){return this.label||(this.isObject?"":this.value)},currentValue:function(){return this.value||this.label||""},itemSelected:function(){return this.select.multiple?this.contains(this.select.value,this.value):this.isEqual(this.value,this.select.value)},limitReached:function(){return!!this.select.multiple&&(!this.itemSelected&&(this.select.value||[]).length>=this.select.multipleLimit&&this.select.multipleLimit>0)}},watch:{currentLabel:function(){this.created||this.select.remote||this.dispatch("ElSelect","setSelected")},value:function(e,t){var n=this.select,i=n.remote,r=n.valueKey;if(!this.created&&!i){if(r&&"object"===(void 0===e?"undefined":a(e))&&"object"===(void 0===t?"undefined":a(t))&&e[r]===t[r])return;this.dispatch("ElSelect","setSelected")}}},methods:{isEqual:function(e,t){if(this.isObject){var n=this.select.valueKey;return Object(s.getValueByPath)(e,n)===Object(s.getValueByPath)(t,n)}return e===t},contains:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t=arguments[1];if(this.isObject){var n=this.select.valueKey;return e&&e.some((function(e){return Object(s.getValueByPath)(e,n)===Object(s.getValueByPath)(t,n)}))}return e&&e.indexOf(t)>-1},handleGroupDisabled:function(e){this.groupDisabled=e},hoverItem:function(){this.disabled||this.groupDisabled||(this.select.hoverIndex=this.select.options.indexOf(this))},selectOptionClick:function(){!0!==this.disabled&&!0!==this.groupDisabled&&this.dispatch("ElSelect","handleOptionClick",[this,!0])},queryChange:function(e){this.visible=new RegExp(Object(s.escapeRegexpString)(e),"i").test(this.currentLabel)||this.created,this.visible||this.select.filteredOptionsCount--}},created:function(){this.select.options.push(this),this.select.cachedOptions.push(this),this.select.optionsCount++,this.select.filteredOptionsCount++,this.$on("queryChange",this.queryChange),this.$on("handleGroupDisabled",this.handleGroupDisabled)},beforeDestroy:function(){var e=this.select,t=e.selected,n=e.multiple?t:[t],i=this.select.cachedOptions.indexOf(this),r=n.indexOf(this);i>-1&&r<0&&this.select.cachedOptions.splice(i,1),this.select.onOptionDestroy(this.select.options.indexOf(this))}},c=l,u=n(0),d=Object(u.a)(c,i,[],!1,null,null,null);d.options.__file="packages/select/src/option.vue";t.a=d.exports},38:function(e,t){e.exports=n(27698)},4:function(e,t){e.exports=n(52477)},5:function(e,t){e.exports=n(70499)},6:function(e,t){e.exports=n(52084)},62:function(e,t,n){"use strict";n.r(t);var i=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{directives:[{name:"clickoutside",rawName:"v-clickoutside",value:e.handleClose,expression:"handleClose"}],staticClass:"el-select",class:[e.selectSize?"el-select--"+e.selectSize:""],on:{click:function(t){return t.stopPropagation(),e.toggleMenu(t)}}},[e.multiple?n("div",{ref:"tags",staticClass:"el-select__tags",style:{"max-width":e.inputWidth-32+"px",width:"100%"}},[e.collapseTags&&e.selected.length?n("span",[n("el-tag",{attrs:{closable:!e.selectDisabled,size:e.collapseTagSize,hit:e.selected[0].hitState,type:"info","disable-transitions":""},on:{close:function(t){e.deleteTag(t,e.selected[0])}}},[n("span",{staticClass:"el-select__tags-text"},[e._v(e._s(e.selected[0].currentLabel))])]),e.selected.length>1?n("el-tag",{attrs:{closable:!1,size:e.collapseTagSize,type:"info","disable-transitions":""}},[n("span",{staticClass:"el-select__tags-text"},[e._v("+ "+e._s(e.selected.length-1))])]):e._e()],1):e._e(),e.collapseTags?e._e():n("transition-group",{on:{"after-leave":e.resetInputHeight}},e._l(e.selected,(function(t){return n("el-tag",{key:e.getValueKey(t),attrs:{closable:!e.selectDisabled,size:e.collapseTagSize,hit:t.hitState,type:"info","disable-transitions":""},on:{close:function(n){e.deleteTag(n,t)}}},[n("span",{staticClass:"el-select__tags-text"},[e._v(e._s(t.currentLabel))])])})),1),e.filterable?n("input",{directives:[{name:"model",rawName:"v-model",value:e.query,expression:"query"}],ref:"input",staticClass:"el-select__input",class:[e.selectSize?"is-"+e.selectSize:""],style:{"flex-grow":"1",width:e.inputLength/(e.inputWidth-32)+"%","max-width":e.inputWidth-42+"px"},attrs:{type:"text",disabled:e.selectDisabled,autocomplete:e.autoComplete||e.autocomplete},domProps:{value:e.query},on:{focus:e.handleFocus,blur:function(t){e.softFocus=!1},keyup:e.managePlaceholder,keydown:[e.resetInputState,function(t){if(!("button"in t)&&e._k(t.keyCode,"down",40,t.key,["Down","ArrowDown"]))return null;t.preventDefault(),e.handleNavigate("next")},function(t){if(!("button"in t)&&e._k(t.keyCode,"up",38,t.key,["Up","ArrowUp"]))return null;t.preventDefault(),e.handleNavigate("prev")},function(t){return!("button"in t)&&e._k(t.keyCode,"enter",13,t.key,"Enter")?null:(t.preventDefault(),e.selectOption(t))},function(t){if(!("button"in t)&&e._k(t.keyCode,"esc",27,t.key,["Esc","Escape"]))return null;t.stopPropagation(),t.preventDefault(),e.visible=!1},function(t){return!("button"in t)&&e._k(t.keyCode,"delete",[8,46],t.key,["Backspace","Delete","Del"])?null:e.deletePrevTag(t)},function(t){if(!("button"in t)&&e._k(t.keyCode,"tab",9,t.key,"Tab"))return null;e.visible=!1}],compositionstart:e.handleComposition,compositionupdate:e.handleComposition,compositionend:e.handleComposition,input:[function(t){t.target.composing||(e.query=t.target.value)},e.debouncedQueryChange]}}):e._e()],1):e._e(),n("el-input",{ref:"reference",class:{"is-focus":e.visible},attrs:{type:"text",placeholder:e.currentPlaceholder,name:e.name,id:e.id,autocomplete:e.autoComplete||e.autocomplete,size:e.selectSize,disabled:e.selectDisabled,readonly:e.readonly,"validate-event":!1,tabindex:e.multiple&&e.filterable?"-1":null},on:{focus:e.handleFocus,blur:e.handleBlur,input:e.debouncedOnInputChange,compositionstart:e.handleComposition,compositionupdate:e.handleComposition,compositionend:e.handleComposition},nativeOn:{keydown:[function(t){if(!("button"in t)&&e._k(t.keyCode,"down",40,t.key,["Down","ArrowDown"]))return null;t.stopPropagation(),t.preventDefault(),e.handleNavigate("next")},function(t){if(!("button"in t)&&e._k(t.keyCode,"up",38,t.key,["Up","ArrowUp"]))return null;t.stopPropagation(),t.preventDefault(),e.handleNavigate("prev")},function(t){return!("button"in t)&&e._k(t.keyCode,"enter",13,t.key,"Enter")?null:(t.preventDefault(),e.selectOption(t))},function(t){if(!("button"in t)&&e._k(t.keyCode,"esc",27,t.key,["Esc","Escape"]))return null;t.stopPropagation(),t.preventDefault(),e.visible=!1},function(t){if(!("button"in t)&&e._k(t.keyCode,"tab",9,t.key,"Tab"))return null;e.visible=!1}],mouseenter:function(t){e.inputHovering=!0},mouseleave:function(t){e.inputHovering=!1}},model:{value:e.selectedLabel,callback:function(t){e.selectedLabel=t},expression:"selectedLabel"}},[e.$slots.prefix?n("template",{slot:"prefix"},[e._t("prefix")],2):e._e(),n("template",{slot:"suffix"},[n("i",{directives:[{name:"show",rawName:"v-show",value:!e.showClose,expression:"!showClose"}],class:["el-select__caret","el-input__icon","el-icon-"+e.iconClass]}),e.showClose?n("i",{staticClass:"el-select__caret el-input__icon el-icon-circle-close",on:{click:e.handleClearClick}}):e._e()])],2),n("transition",{attrs:{name:"el-zoom-in-top"},on:{"before-enter":e.handleMenuEnter,"after-leave":e.doDestroy}},[n("el-select-menu",{directives:[{name:"show",rawName:"v-show",value:e.visible&&!1!==e.emptyText,expression:"visible && emptyText !== false"}],ref:"popper",attrs:{"append-to-body":e.popperAppendToBody}},[n("el-scrollbar",{directives:[{name:"show",rawName:"v-show",value:e.options.length>0&&!e.loading,expression:"options.length > 0 && !loading"}],ref:"scrollbar",class:{"is-empty":!e.allowCreate&&e.query&&0===e.filteredOptionsCount},attrs:{tag:"ul","wrap-class":"el-select-dropdown__wrap","view-class":"el-select-dropdown__list"}},[e.showNewOption?n("el-option",{attrs:{value:e.query,created:""}}):e._e(),e._t("default")],2),e.emptyText&&(!e.allowCreate||e.loading||e.allowCreate&&0===e.options.length)?[e.$slots.empty?e._t("empty"):n("p",{staticClass:"el-select-dropdown__empty"},[e._v("\n "+e._s(e.emptyText)+"\n ")])]:e._e()],2)],1)],1)};i._withStripped=!0;var r=n(4),o=n.n(r),s=n(22),a=n.n(s),l=n(6),c=n.n(l),u=n(10),d=n.n(u),f=function(){var e=this,t=e.$createElement;return(e._self._c||t)("div",{staticClass:"el-select-dropdown el-popper",class:[{"is-multiple":e.$parent.multiple},e.popperClass],style:{minWidth:e.minWidth}},[e._t("default")],2)};f._withStripped=!0;var p=n(5),h={name:"ElSelectDropdown",componentName:"ElSelectDropdown",mixins:[n.n(p).a],props:{placement:{default:"bottom-start"},boundariesPadding:{default:0},popperOptions:{default:function(){return{gpuAcceleration:!1}}},visibleArrow:{default:!0},appendToBody:{type:Boolean,default:!0}},data:function(){return{minWidth:""}},computed:{popperClass:function(){return this.$parent.popperClass}},watch:{"$parent.inputWidth":function(){this.minWidth=this.$parent.$el.getBoundingClientRect().width+"px"}},mounted:function(){var e=this;this.referenceElm=this.$parent.$refs.reference.$el,this.$parent.popperElm=this.popperElm=this.$el,this.$on("updatePopper",(function(){e.$parent.visible&&e.updatePopper()})),this.$on("destroyPopper",this.destroyPopper)}},v=n(0),m=Object(v.a)(h,f,[],!1,null,null,null);m.options.__file="packages/select/src/select-dropdown.vue";var _=m.exports,g=n(33),b=n(38),y=n.n(b),x=n(15),w=n.n(x),C=n(19),S=n.n(C),k=n(12),$=n.n(k),O=n(16),T=n(31),E=n.n(T),j=n(3),I=n(21),P={mixins:[o.a,c.a,a()("reference"),{data:function(){return{hoverOption:-1}},computed:{optionsAllDisabled:function(){return this.options.filter((function(e){return e.visible})).every((function(e){return e.disabled}))}},watch:{hoverIndex:function(e){var t=this;"number"==typeof e&&e>-1&&(this.hoverOption=this.options[e]||{}),this.options.forEach((function(e){e.hover=t.hoverOption===e}))}},methods:{navigateOptions:function(e){var t=this;if(this.visible){if(0!==this.options.length&&0!==this.filteredOptionsCount&&!this.optionsAllDisabled){"next"===e?(this.hoverIndex++,this.hoverIndex===this.options.length&&(this.hoverIndex=0)):"prev"===e&&(this.hoverIndex--,this.hoverIndex<0&&(this.hoverIndex=this.options.length-1));var n=this.options[this.hoverIndex];!0!==n.disabled&&!0!==n.groupDisabled&&n.visible||this.navigateOptions(e),this.$nextTick((function(){return t.scrollToOption(t.hoverOption)}))}}else this.visible=!0}}}],name:"ElSelect",componentName:"ElSelect",inject:{elForm:{default:""},elFormItem:{default:""}},provide:function(){return{select:this}},computed:{_elFormItemSize:function(){return(this.elFormItem||{}).elFormItemSize},readonly:function(){return!this.filterable||this.multiple||!Object(j.isIE)()&&!Object(j.isEdge)()&&!this.visible},showClose:function(){var e=this.multiple?Array.isArray(this.value)&&this.value.length>0:void 0!==this.value&&null!==this.value&&""!==this.value;return this.clearable&&!this.selectDisabled&&this.inputHovering&&e},iconClass:function(){return this.remote&&this.filterable?"":this.visible?"arrow-up is-reverse":"arrow-up"},debounce:function(){return this.remote?300:0},emptyText:function(){return this.loading?this.loadingText||this.t("el.select.loading"):(!this.remote||""!==this.query||0!==this.options.length)&&(this.filterable&&this.query&&this.options.length>0&&0===this.filteredOptionsCount?this.noMatchText||this.t("el.select.noMatch"):0===this.options.length?this.noDataText||this.t("el.select.noData"):null)},showNewOption:function(){var e=this,t=this.options.filter((function(e){return!e.created})).some((function(t){return t.currentLabel===e.query}));return this.filterable&&this.allowCreate&&""!==this.query&&!t},selectSize:function(){return this.size||this._elFormItemSize||(this.$ELEMENT||{}).size},selectDisabled:function(){return this.disabled||(this.elForm||{}).disabled},collapseTagSize:function(){return["small","mini"].indexOf(this.selectSize)>-1?"mini":"small"},propPlaceholder:function(){return void 0!==this.placeholder?this.placeholder:this.t("el.select.placeholder")}},components:{ElInput:d.a,ElSelectMenu:_,ElOption:g.a,ElTag:y.a,ElScrollbar:w.a},directives:{Clickoutside:$.a},props:{name:String,id:String,value:{required:!0},autocomplete:{type:String,default:"off"},autoComplete:{type:String,validator:function(e){return!0}},automaticDropdown:Boolean,size:String,disabled:Boolean,clearable:Boolean,filterable:Boolean,allowCreate:Boolean,loading:Boolean,popperClass:String,remote:Boolean,loadingText:String,noMatchText:String,noDataText:String,remoteMethod:Function,filterMethod:Function,multiple:Boolean,multipleLimit:{type:Number,default:0},placeholder:{type:String,required:!1},defaultFirstOption:Boolean,reserveKeyword:Boolean,valueKey:{type:String,default:"value"},collapseTags:Boolean,popperAppendToBody:{type:Boolean,default:!0}},data:function(){return{options:[],cachedOptions:[],createdLabel:null,createdSelected:!1,selected:this.multiple?[]:{},inputLength:20,inputWidth:0,initialInputHeight:0,cachedPlaceHolder:"",optionsCount:0,filteredOptionsCount:0,visible:!1,softFocus:!1,selectedLabel:"",hoverIndex:-1,query:"",previousQuery:null,inputHovering:!1,currentPlaceholder:"",menuVisibleOnFocus:!1,isOnComposition:!1,isSilentBlur:!1}},watch:{selectDisabled:function(){var e=this;this.$nextTick((function(){e.resetInputHeight()}))},propPlaceholder:function(e){this.cachedPlaceHolder=this.currentPlaceholder=e},value:function(e,t){this.multiple&&(this.resetInputHeight(),e&&e.length>0||this.$refs.input&&""!==this.query?this.currentPlaceholder="":this.currentPlaceholder=this.cachedPlaceHolder,this.filterable&&!this.reserveKeyword&&(this.query="",this.handleQueryChange(this.query))),this.setSelected(),this.filterable&&!this.multiple&&(this.inputLength=20),Object(j.valueEquals)(e,t)||this.dispatch("ElFormItem","el.form.change",e)},visible:function(e){var t=this;e?(this.broadcast("ElSelectDropdown","updatePopper"),this.filterable&&(this.query=this.remote?"":this.selectedLabel,this.handleQueryChange(this.query),this.multiple?this.$refs.input.focus():(this.remote||(this.broadcast("ElOption","queryChange",""),this.broadcast("ElOptionGroup","queryChange")),this.selectedLabel&&(this.currentPlaceholder=this.selectedLabel,this.selectedLabel="")))):(this.broadcast("ElSelectDropdown","destroyPopper"),this.$refs.input&&this.$refs.input.blur(),this.query="",this.previousQuery=null,this.selectedLabel="",this.inputLength=20,this.menuVisibleOnFocus=!1,this.resetHoverIndex(),this.$nextTick((function(){t.$refs.input&&""===t.$refs.input.value&&0===t.selected.length&&(t.currentPlaceholder=t.cachedPlaceHolder)})),this.multiple||(this.selected&&(this.filterable&&this.allowCreate&&this.createdSelected&&this.createdLabel?this.selectedLabel=this.createdLabel:this.selectedLabel=this.selected.currentLabel,this.filterable&&(this.query=this.selectedLabel)),this.filterable&&(this.currentPlaceholder=this.cachedPlaceHolder))),this.$emit("visible-change",e)},options:function(){var e=this;if(!this.$isServer){this.$nextTick((function(){e.broadcast("ElSelectDropdown","updatePopper")})),this.multiple&&this.resetInputHeight();var t=this.$el.querySelectorAll("input");-1===[].indexOf.call(t,document.activeElement)&&this.setSelected(),this.defaultFirstOption&&(this.filterable||this.remote)&&this.filteredOptionsCount&&this.checkDefaultFirstOption()}}},methods:{handleNavigate:function(e){this.isOnComposition||this.navigateOptions(e)},handleComposition:function(e){var t=this,n=e.target.value;if("compositionend"===e.type)this.isOnComposition=!1,this.$nextTick((function(e){return t.handleQueryChange(n)}));else{var i=n[n.length-1]||"";this.isOnComposition=!Object(I.isKorean)(i)}},handleQueryChange:function(e){var t=this;this.previousQuery===e||this.isOnComposition||(null!==this.previousQuery||"function"!=typeof this.filterMethod&&"function"!=typeof this.remoteMethod?(this.previousQuery=e,this.$nextTick((function(){t.visible&&t.broadcast("ElSelectDropdown","updatePopper")})),this.hoverIndex=-1,this.multiple&&this.filterable&&this.$nextTick((function(){var e=15*t.$refs.input.value.length+20;t.inputLength=t.collapseTags?Math.min(50,e):e,t.managePlaceholder(),t.resetInputHeight()})),this.remote&&"function"==typeof this.remoteMethod?(this.hoverIndex=-1,this.remoteMethod(e)):"function"==typeof this.filterMethod?(this.filterMethod(e),this.broadcast("ElOptionGroup","queryChange")):(this.filteredOptionsCount=this.optionsCount,this.broadcast("ElOption","queryChange",e),this.broadcast("ElOptionGroup","queryChange")),this.defaultFirstOption&&(this.filterable||this.remote)&&this.filteredOptionsCount&&this.checkDefaultFirstOption()):this.previousQuery=e)},scrollToOption:function(e){var t=Array.isArray(e)&&e[0]?e[0].$el:e.$el;if(this.$refs.popper&&t){var n=this.$refs.popper.$el.querySelector(".el-select-dropdown__wrap");E()(n,t)}this.$refs.scrollbar&&this.$refs.scrollbar.handleScroll()},handleMenuEnter:function(){var e=this;this.$nextTick((function(){return e.scrollToOption(e.selected)}))},emitChange:function(e){Object(j.valueEquals)(this.value,e)||this.$emit("change",e)},getOption:function(e){for(var t=void 0,n="[object object]"===Object.prototype.toString.call(e).toLowerCase(),i="[object null]"===Object.prototype.toString.call(e).toLowerCase(),r="[object undefined]"===Object.prototype.toString.call(e).toLowerCase(),o=this.cachedOptions.length-1;o>=0;o--){var s=this.cachedOptions[o];if(n?Object(j.getValueByPath)(s.value,this.valueKey)===Object(j.getValueByPath)(e,this.valueKey):s.value===e){t=s;break}}if(t)return t;var a={value:e,currentLabel:n||i||r?"":String(e)};return this.multiple&&(a.hitState=!1),a},setSelected:function(){var e=this;if(!this.multiple){var t=this.getOption(this.value);return t.created?(this.createdLabel=t.currentLabel,this.createdSelected=!0):this.createdSelected=!1,this.selectedLabel=t.currentLabel,this.selected=t,void(this.filterable&&(this.query=this.selectedLabel))}var n=[];Array.isArray(this.value)&&this.value.forEach((function(t){n.push(e.getOption(t))})),this.selected=n,this.$nextTick((function(){e.resetInputHeight()}))},handleFocus:function(e){this.softFocus?this.softFocus=!1:((this.automaticDropdown||this.filterable)&&(this.filterable&&!this.visible&&(this.menuVisibleOnFocus=!0),this.visible=!0),this.$emit("focus",e))},blur:function(){this.visible=!1,this.$refs.reference.blur()},handleBlur:function(e){var t=this;setTimeout((function(){t.isSilentBlur?t.isSilentBlur=!1:t.$emit("blur",e)}),50),this.softFocus=!1},handleClearClick:function(e){this.deleteSelected(e)},doDestroy:function(){this.$refs.popper&&this.$refs.popper.doDestroy()},handleClose:function(){this.visible=!1},toggleLastOptionHitState:function(e){if(Array.isArray(this.selected)){var t=this.selected[this.selected.length-1];if(t)return!0===e||!1===e?(t.hitState=e,e):(t.hitState=!t.hitState,t.hitState)}},deletePrevTag:function(e){if(e.target.value.length<=0&&!this.toggleLastOptionHitState()){var t=this.value.slice();t.pop(),this.$emit("input",t),this.emitChange(t)}},managePlaceholder:function(){""!==this.currentPlaceholder&&(this.currentPlaceholder=this.$refs.input.value?"":this.cachedPlaceHolder)},resetInputState:function(e){8!==e.keyCode&&this.toggleLastOptionHitState(!1),this.inputLength=15*this.$refs.input.value.length+20,this.resetInputHeight()},resetInputHeight:function(){var e=this;this.collapseTags&&!this.filterable||this.$nextTick((function(){if(e.$refs.reference){var t=e.$refs.reference.$el.childNodes,n=[].filter.call(t,(function(e){return"INPUT"===e.tagName}))[0],i=e.$refs.tags,r=i?Math.round(i.getBoundingClientRect().height):0,o=e.initialInputHeight||40;n.style.height=0===e.selected.length?o+"px":Math.max(i?r+(r>o?6:0):0,o)+"px",e.visible&&!1!==e.emptyText&&e.broadcast("ElSelectDropdown","updatePopper")}}))},resetHoverIndex:function(){var e=this;setTimeout((function(){e.multiple?e.selected.length>0?e.hoverIndex=Math.min.apply(null,e.selected.map((function(t){return e.options.indexOf(t)}))):e.hoverIndex=-1:e.hoverIndex=e.options.indexOf(e.selected)}),300)},handleOptionSelect:function(e,t){var n=this;if(this.multiple){var i=(this.value||[]).slice(),r=this.getValueIndex(i,e.value);r>-1?i.splice(r,1):(this.multipleLimit<=0||i.length0&&void 0!==arguments[0]?arguments[0]:[],t=arguments[1];if("[object object]"===Object.prototype.toString.call(t).toLowerCase()){var n=this.valueKey,i=-1;return e.some((function(e,r){return Object(j.getValueByPath)(e,n)===Object(j.getValueByPath)(t,n)&&(i=r,!0)})),i}return e.indexOf(t)},toggleMenu:function(){this.selectDisabled||(this.menuVisibleOnFocus?this.menuVisibleOnFocus=!1:this.visible=!this.visible,this.visible&&(this.$refs.input||this.$refs.reference).focus())},selectOption:function(){this.visible?this.options[this.hoverIndex]&&this.handleOptionSelect(this.options[this.hoverIndex]):this.toggleMenu()},deleteSelected:function(e){e.stopPropagation();var t=this.multiple?[]:"";this.$emit("input",t),this.emitChange(t),this.visible=!1,this.$emit("clear")},deleteTag:function(e,t){var n=this.selected.indexOf(t);if(n>-1&&!this.selectDisabled){var i=this.value.slice();i.splice(n,1),this.$emit("input",i),this.emitChange(i),this.$emit("remove-tag",t.value)}e.stopPropagation()},onInputChange:function(){this.filterable&&this.query!==this.selectedLabel&&(this.query=this.selectedLabel,this.handleQueryChange(this.query))},onOptionDestroy:function(e){e>-1&&(this.optionsCount--,this.filteredOptionsCount--,this.options.splice(e,1))},resetInputWidth:function(){this.inputWidth=this.$refs.reference.$el.getBoundingClientRect().width},handleResize:function(){this.resetInputWidth(),this.multiple&&this.resetInputHeight()},checkDefaultFirstOption:function(){this.hoverIndex=-1;for(var e=!1,t=this.options.length-1;t>=0;t--)if(this.options[t].created){e=!0,this.hoverIndex=t;break}if(!e)for(var n=0;n!==this.options.length;++n){var i=this.options[n];if(this.query){if(!i.disabled&&!i.groupDisabled&&i.visible){this.hoverIndex=n;break}}else if(i.itemSelected){this.hoverIndex=n;break}}},getValueKey:function(e){return"[object object]"!==Object.prototype.toString.call(e.value).toLowerCase()?e.value:Object(j.getValueByPath)(e.value,this.valueKey)}},created:function(){var e=this;this.cachedPlaceHolder=this.currentPlaceholder=this.propPlaceholder,this.multiple&&!Array.isArray(this.value)&&this.$emit("input",[]),!this.multiple&&Array.isArray(this.value)&&this.$emit("input",""),this.debouncedOnInputChange=S()(this.debounce,(function(){e.onInputChange()})),this.debouncedQueryChange=S()(this.debounce,(function(t){e.handleQueryChange(t.target.value)})),this.$on("handleOptionClick",this.handleOptionSelect),this.$on("setSelected",this.setSelected)},mounted:function(){var e=this;this.multiple&&Array.isArray(this.value)&&this.value.length>0&&(this.currentPlaceholder=""),Object(O.addResizeListener)(this.$el,this.handleResize);var t=this.$refs.reference;if(t&&t.$el){var n=t.$el.querySelector("input");this.initialInputHeight=n.getBoundingClientRect().height||{medium:36,small:32,mini:28}[this.selectSize]}this.remote&&this.multiple&&this.resetInputHeight(),this.$nextTick((function(){t&&t.$el&&(e.inputWidth=t.$el.getBoundingClientRect().width)})),this.setSelected()},beforeDestroy:function(){this.$el&&this.handleResize&&Object(O.removeResizeListener)(this.$el,this.handleResize)}},M=P,A=Object(v.a)(M,i,[],!1,null,null,null);A.options.__file="packages/select/src/select.vue";var N=A.exports;N.install=function(e){e.component(N.name,N)};t.default=N}})},75652:(e,t,n)=>{e.exports=function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist/",n(n.s=64)}({0:function(e,t,n){"use strict";function i(e,t,n,i,r,o,s,a){var l,c="function"==typeof e?e.options:e;if(t&&(c.render=t,c.staticRenderFns=n,c._compiled=!0),i&&(c.functional=!0),o&&(c._scopeId="data-v-"+o),s?(l=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),r&&r.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(s)},c._ssrRegister=l):r&&(l=a?function(){r.call(this,this.$root.$options.shadowRoot)}:r),l)if(c.functional){c._injectStyles=l;var u=c.render;c.render=function(e,t){return l.call(t),u(e,t)}}else{var d=c.beforeCreate;c.beforeCreate=d?[].concat(d,l):[l]}return{exports:e,options:c}}n.d(t,"a",(function(){return i}))},29:function(e,t){e.exports=n(14561)},4:function(e,t){e.exports=n(52477)},50:function(e,t){e.exports=n(7987)},64:function(e,t,n){"use strict";n.r(t);var i=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"el-slider",class:{"is-vertical":e.vertical,"el-slider--with-input":e.showInput},attrs:{role:"slider","aria-valuemin":e.min,"aria-valuemax":e.max,"aria-orientation":e.vertical?"vertical":"horizontal","aria-disabled":e.sliderDisabled}},[e.showInput&&!e.range?n("el-input-number",{ref:"input",staticClass:"el-slider__input",attrs:{step:e.step,disabled:e.sliderDisabled,controls:e.showInputControls,min:e.min,max:e.max,debounce:e.debounce,size:e.inputSize},on:{change:e.emitChange},model:{value:e.firstValue,callback:function(t){e.firstValue=t},expression:"firstValue"}}):e._e(),n("div",{ref:"slider",staticClass:"el-slider__runway",class:{"show-input":e.showInput,disabled:e.sliderDisabled},style:e.runwayStyle,on:{click:e.onSliderClick}},[n("div",{staticClass:"el-slider__bar",style:e.barStyle}),n("slider-button",{ref:"button1",attrs:{vertical:e.vertical,"tooltip-class":e.tooltipClass},model:{value:e.firstValue,callback:function(t){e.firstValue=t},expression:"firstValue"}}),e.range?n("slider-button",{ref:"button2",attrs:{vertical:e.vertical,"tooltip-class":e.tooltipClass},model:{value:e.secondValue,callback:function(t){e.secondValue=t},expression:"secondValue"}}):e._e(),e._l(e.stops,(function(t,i){return e.showStops?n("div",{key:i,staticClass:"el-slider__stop",style:e.getStopStyle(t)}):e._e()})),e.markList.length>0?[n("div",e._l(e.markList,(function(t,i){return n("div",{key:i,staticClass:"el-slider__stop el-slider__marks-stop",style:e.getStopStyle(t.position)})})),0),n("div",{staticClass:"el-slider__marks"},e._l(e.markList,(function(t,i){return n("slider-marker",{key:i,style:e.getStopStyle(t.position),attrs:{mark:t.mark}})})),1)]:e._e()],2)],1)};i._withStripped=!0;var r=n(50),o=n.n(r),s=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{ref:"button",staticClass:"el-slider__button-wrapper",class:{hover:e.hovering,dragging:e.dragging},style:e.wrapperStyle,attrs:{tabindex:"0"},on:{mouseenter:e.handleMouseEnter,mouseleave:e.handleMouseLeave,mousedown:e.onButtonDown,touchstart:e.onButtonDown,focus:e.handleMouseEnter,blur:e.handleMouseLeave,keydown:[function(t){return!("button"in t)&&e._k(t.keyCode,"left",37,t.key,["Left","ArrowLeft"])||"button"in t&&0!==t.button?null:e.onLeftKeyDown(t)},function(t){return!("button"in t)&&e._k(t.keyCode,"right",39,t.key,["Right","ArrowRight"])||"button"in t&&2!==t.button?null:e.onRightKeyDown(t)},function(t){return!("button"in t)&&e._k(t.keyCode,"down",40,t.key,["Down","ArrowDown"])?null:(t.preventDefault(),e.onLeftKeyDown(t))},function(t){return!("button"in t)&&e._k(t.keyCode,"up",38,t.key,["Up","ArrowUp"])?null:(t.preventDefault(),e.onRightKeyDown(t))}]}},[n("el-tooltip",{ref:"tooltip",attrs:{placement:"top","popper-class":e.tooltipClass,disabled:!e.showTooltip}},[n("span",{attrs:{slot:"content"},slot:"content"},[e._v(e._s(e.formatValue))]),n("div",{staticClass:"el-slider__button",class:{hover:e.hovering,dragging:e.dragging}})])],1)};s._withStripped=!0;var a=n(29),l={name:"ElSliderButton",components:{ElTooltip:n.n(a).a},props:{value:{type:Number,default:0},vertical:{type:Boolean,default:!1},tooltipClass:String},data:function(){return{hovering:!1,dragging:!1,isClick:!1,startX:0,currentX:0,startY:0,currentY:0,startPosition:0,newPosition:null,oldValue:this.value}},computed:{disabled:function(){return this.$parent.sliderDisabled},max:function(){return this.$parent.max},min:function(){return this.$parent.min},step:function(){return this.$parent.step},showTooltip:function(){return this.$parent.showTooltip},precision:function(){return this.$parent.precision},currentPosition:function(){return(this.value-this.min)/(this.max-this.min)*100+"%"},enableFormat:function(){return this.$parent.formatTooltip instanceof Function},formatValue:function(){return this.enableFormat&&this.$parent.formatTooltip(this.value)||this.value},wrapperStyle:function(){return this.vertical?{bottom:this.currentPosition}:{left:this.currentPosition}}},watch:{dragging:function(e){this.$parent.dragging=e}},methods:{displayTooltip:function(){this.$refs.tooltip&&(this.$refs.tooltip.showPopper=!0)},hideTooltip:function(){this.$refs.tooltip&&(this.$refs.tooltip.showPopper=!1)},handleMouseEnter:function(){this.hovering=!0,this.displayTooltip()},handleMouseLeave:function(){this.hovering=!1,this.hideTooltip()},onButtonDown:function(e){this.disabled||(e.preventDefault(),this.onDragStart(e),window.addEventListener("mousemove",this.onDragging),window.addEventListener("touchmove",this.onDragging),window.addEventListener("mouseup",this.onDragEnd),window.addEventListener("touchend",this.onDragEnd),window.addEventListener("contextmenu",this.onDragEnd))},onLeftKeyDown:function(){this.disabled||(this.newPosition=parseFloat(this.currentPosition)-this.step/(this.max-this.min)*100,this.setPosition(this.newPosition),this.$parent.emitChange())},onRightKeyDown:function(){this.disabled||(this.newPosition=parseFloat(this.currentPosition)+this.step/(this.max-this.min)*100,this.setPosition(this.newPosition),this.$parent.emitChange())},onDragStart:function(e){this.dragging=!0,this.isClick=!0,"touchstart"===e.type&&(e.clientY=e.touches[0].clientY,e.clientX=e.touches[0].clientX),this.vertical?this.startY=e.clientY:this.startX=e.clientX,this.startPosition=parseFloat(this.currentPosition),this.newPosition=this.startPosition},onDragging:function(e){if(this.dragging){this.isClick=!1,this.displayTooltip(),this.$parent.resetSize();var t=0;"touchmove"===e.type&&(e.clientY=e.touches[0].clientY,e.clientX=e.touches[0].clientX),this.vertical?(this.currentY=e.clientY,t=(this.startY-this.currentY)/this.$parent.sliderSize*100):(this.currentX=e.clientX,t=(this.currentX-this.startX)/this.$parent.sliderSize*100),this.newPosition=this.startPosition+t,this.setPosition(this.newPosition)}},onDragEnd:function(){var e=this;this.dragging&&(setTimeout((function(){e.dragging=!1,e.hideTooltip(),e.isClick||(e.setPosition(e.newPosition),e.$parent.emitChange())}),0),window.removeEventListener("mousemove",this.onDragging),window.removeEventListener("touchmove",this.onDragging),window.removeEventListener("mouseup",this.onDragEnd),window.removeEventListener("touchend",this.onDragEnd),window.removeEventListener("contextmenu",this.onDragEnd))},setPosition:function(e){var t=this;if(null!==e&&!isNaN(e)){e<0?e=0:e>100&&(e=100);var n=100/((this.max-this.min)/this.step),i=Math.round(e/n)*n*(this.max-this.min)*.01+this.min;i=parseFloat(i.toFixed(this.precision)),this.$emit("input",i),this.$nextTick((function(){t.displayTooltip(),t.$refs.tooltip&&t.$refs.tooltip.updatePopper()})),this.dragging||this.value===this.oldValue||(this.oldValue=this.value)}}}},c=n(0),u=Object(c.a)(l,s,[],!1,null,null,null);u.options.__file="packages/slider/src/button.vue";var d=u.exports,f={name:"ElMarker",props:{mark:{type:[String,Object]}},render:function(){var e=arguments[0],t="string"==typeof this.mark?this.mark:this.mark.label;return e("div",{class:"el-slider__marks-text",style:this.mark.style||{}},[t])}},p=n(4),h={name:"ElSlider",mixins:[n.n(p).a],inject:{elForm:{default:""}},props:{min:{type:Number,default:0},max:{type:Number,default:100},step:{type:Number,default:1},value:{type:[Number,Array],default:0},showInput:{type:Boolean,default:!1},showInputControls:{type:Boolean,default:!0},inputSize:{type:String,default:"small"},showStops:{type:Boolean,default:!1},showTooltip:{type:Boolean,default:!0},formatTooltip:Function,disabled:{type:Boolean,default:!1},range:{type:Boolean,default:!1},vertical:{type:Boolean,default:!1},height:{type:String},debounce:{type:Number,default:300},label:{type:String},tooltipClass:String,marks:Object},components:{ElInputNumber:o.a,SliderButton:d,SliderMarker:f},data:function(){return{firstValue:null,secondValue:null,oldValue:null,dragging:!1,sliderSize:1}},watch:{value:function(e,t){this.dragging||Array.isArray(e)&&Array.isArray(t)&&e.every((function(e,n){return e===t[n]}))||this.setValues()},dragging:function(e){e||this.setValues()},firstValue:function(e){this.range?this.$emit("input",[this.minValue,this.maxValue]):this.$emit("input",e)},secondValue:function(){this.range&&this.$emit("input",[this.minValue,this.maxValue])},min:function(){this.setValues()},max:function(){this.setValues()}},methods:{valueChanged:function(){var e=this;return this.range?![this.minValue,this.maxValue].every((function(t,n){return t===e.oldValue[n]})):this.value!==this.oldValue},setValues:function(){if(this.min>this.max)console.error("[Element Error][Slider]min should not be greater than max.");else{var e=this.value;this.range&&Array.isArray(e)?e[1]this.max?this.$emit("input",[this.max,this.max]):e[0]this.max?this.$emit("input",[e[0],this.max]):(this.firstValue=e[0],this.secondValue=e[1],this.valueChanged()&&(this.dispatch("ElFormItem","el.form.change",[this.minValue,this.maxValue]),this.oldValue=e.slice())):this.range||"number"!=typeof e||isNaN(e)||(ethis.max?this.$emit("input",this.max):(this.firstValue=e,this.valueChanged()&&(this.dispatch("ElFormItem","el.form.change",e),this.oldValue=e)))}},setPosition:function(e){var t=this.min+e*(this.max-this.min)/100;if(this.range){var n=void 0;n=Math.abs(this.minValue-t)this.secondValue?"button1":"button2",this.$refs[n].setPosition(e)}else this.$refs.button1.setPosition(e)},onSliderClick:function(e){if(!this.sliderDisabled&&!this.dragging){if(this.resetSize(),this.vertical){var t=this.$refs.slider.getBoundingClientRect().bottom;this.setPosition((t-e.clientY)/this.sliderSize*100)}else{var n=this.$refs.slider.getBoundingClientRect().left;this.setPosition((e.clientX-n)/this.sliderSize*100)}this.emitChange()}},resetSize:function(){this.$refs.slider&&(this.sliderSize=this.$refs.slider["client"+(this.vertical?"Height":"Width")])},emitChange:function(){var e=this;this.$nextTick((function(){e.$emit("change",e.range?[e.minValue,e.maxValue]:e.value)}))},getStopStyle:function(e){return this.vertical?{bottom:e+"%"}:{left:e+"%"}}},computed:{stops:function(){var e=this;if(!this.showStops||this.min>this.max)return[];if(0===this.step)return[];for(var t=(this.max-this.min)/this.step,n=100*this.step/(this.max-this.min),i=[],r=1;r100*(e.maxValue-e.min)/(e.max-e.min)})):i.filter((function(t){return t>100*(e.firstValue-e.min)/(e.max-e.min)}))},markList:function(){var e=this;return this.marks?Object.keys(this.marks).map(parseFloat).sort((function(e,t){return e-t})).filter((function(t){return t<=e.max&&t>=e.min})).map((function(t){return{point:t,position:100*(t-e.min)/(e.max-e.min),mark:e.marks[t]}})):[]},minValue:function(){return Math.min(this.firstValue,this.secondValue)},maxValue:function(){return Math.max(this.firstValue,this.secondValue)},barSize:function(){return this.range?100*(this.maxValue-this.minValue)/(this.max-this.min)+"%":100*(this.firstValue-this.min)/(this.max-this.min)+"%"},barStart:function(){return this.range?100*(this.minValue-this.min)/(this.max-this.min)+"%":"0%"},precision:function(){var e=[this.min,this.max,this.step].map((function(e){var t=(""+e).split(".")[1];return t?t.length:0}));return Math.max.apply(null,e)},runwayStyle:function(){return this.vertical?{height:this.height}:{}},barStyle:function(){return this.vertical?{height:this.barSize,bottom:this.barStart}:{width:this.barSize,left:this.barStart}},sliderDisabled:function(){return this.disabled||(this.elForm||{}).disabled}},mounted:function(){var e=void 0;this.range?(Array.isArray(this.value)?(this.firstValue=Math.max(this.min,this.value[0]),this.secondValue=Math.min(this.max,this.value[1])):(this.firstValue=this.min,this.secondValue=this.max),this.oldValue=[this.firstValue,this.secondValue],e=this.firstValue+"-"+this.secondValue):("number"!=typeof this.value||isNaN(this.value)?this.firstValue=this.min:this.firstValue=Math.min(this.max,Math.max(this.min,this.value)),this.oldValue=this.firstValue,e=this.firstValue),this.$el.setAttribute("aria-valuetext",e),this.$el.setAttribute("aria-label",this.label?this.label:"slider between "+this.min+" and "+this.max),this.resetSize(),window.addEventListener("resize",this.resetSize)},beforeDestroy:function(){window.removeEventListener("resize",this.resetSize)}},v=Object(c.a)(h,i,[],!1,null,null,null);v.options.__file="packages/slider/src/main.vue";var m=v.exports;m.install=function(e){e.component(m.name,m)};t.default=m}})},48970:(e,t,n)=>{e.exports=function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist/",n(n.s=94)}({0:function(e,t,n){"use strict";function i(e,t,n,i,r,o,s,a){var l,c="function"==typeof e?e.options:e;if(t&&(c.render=t,c.staticRenderFns=n,c._compiled=!0),i&&(c.functional=!0),o&&(c._scopeId="data-v-"+o),s?(l=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),r&&r.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(s)},c._ssrRegister=l):r&&(l=a?function(){r.call(this,this.$root.$options.shadowRoot)}:r),l)if(c.functional){c._injectStyles=l;var u=c.render;c.render=function(e,t){return l.call(t),u(e,t)}}else{var d=c.beforeCreate;c.beforeCreate=d?[].concat(d,l):[l]}return{exports:e,options:c}}n.d(t,"a",(function(){return i}))},11:function(e,t){e.exports=n(84222)},22:function(e,t){e.exports=n(98618)},4:function(e,t){e.exports=n(52477)},94:function(e,t,n){"use strict";n.r(t);var i=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"el-switch",class:{"is-disabled":e.switchDisabled,"is-checked":e.checked},attrs:{role:"switch","aria-checked":e.checked,"aria-disabled":e.switchDisabled},on:{click:function(t){return t.preventDefault(),e.switchValue(t)}}},[n("input",{ref:"input",staticClass:"el-switch__input",attrs:{type:"checkbox",id:e.id,name:e.name,"true-value":e.activeValue,"false-value":e.inactiveValue,disabled:e.switchDisabled},on:{change:e.handleChange,keydown:function(t){return!("button"in t)&&e._k(t.keyCode,"enter",13,t.key,"Enter")?null:e.switchValue(t)}}}),e.inactiveIconClass||e.inactiveText?n("span",{class:["el-switch__label","el-switch__label--left",e.checked?"":"is-active"]},[e.inactiveIconClass?n("i",{class:[e.inactiveIconClass]}):e._e(),!e.inactiveIconClass&&e.inactiveText?n("span",{attrs:{"aria-hidden":e.checked}},[e._v(e._s(e.inactiveText))]):e._e()]):e._e(),n("span",{ref:"core",staticClass:"el-switch__core",style:{width:e.coreWidth+"px"}}),e.activeIconClass||e.activeText?n("span",{class:["el-switch__label","el-switch__label--right",e.checked?"is-active":""]},[e.activeIconClass?n("i",{class:[e.activeIconClass]}):e._e(),!e.activeIconClass&&e.activeText?n("span",{attrs:{"aria-hidden":!e.checked}},[e._v(e._s(e.activeText))]):e._e()]):e._e()])};i._withStripped=!0;var r=n(4),o=n.n(r),s=n(22),a=n.n(s),l=n(11),c=n.n(l),u={name:"ElSwitch",mixins:[a()("input"),c.a,o.a],inject:{elForm:{default:""}},props:{value:{type:[Boolean,String,Number],default:!1},disabled:{type:Boolean,default:!1},width:{type:Number,default:40},activeIconClass:{type:String,default:""},inactiveIconClass:{type:String,default:""},activeText:String,inactiveText:String,activeColor:{type:String,default:""},inactiveColor:{type:String,default:""},activeValue:{type:[Boolean,String,Number],default:!0},inactiveValue:{type:[Boolean,String,Number],default:!1},name:{type:String,default:""},validateEvent:{type:Boolean,default:!0},id:String},data:function(){return{coreWidth:this.width}},created:function(){~[this.activeValue,this.inactiveValue].indexOf(this.value)||this.$emit("input",this.inactiveValue)},computed:{checked:function(){return this.value===this.activeValue},switchDisabled:function(){return this.disabled||(this.elForm||{}).disabled}},watch:{checked:function(){this.$refs.input.checked=this.checked,(this.activeColor||this.inactiveColor)&&this.setBackgroundColor(),this.validateEvent&&this.dispatch("ElFormItem","el.form.change",[this.value])}},methods:{handleChange:function(e){var t=this,n=this.checked?this.inactiveValue:this.activeValue;this.$emit("input",n),this.$emit("change",n),this.$nextTick((function(){t.$refs.input&&(t.$refs.input.checked=t.checked)}))},setBackgroundColor:function(){var e=this.checked?this.activeColor:this.inactiveColor;this.$refs.core.style.borderColor=e,this.$refs.core.style.backgroundColor=e},switchValue:function(){!this.switchDisabled&&this.handleChange()},getMigratingConfig:function(){return{props:{"on-color":"on-color is renamed to active-color.","off-color":"off-color is renamed to inactive-color.","on-text":"on-text is renamed to active-text.","off-text":"off-text is renamed to inactive-text.","on-value":"on-value is renamed to active-value.","off-value":"off-value is renamed to inactive-value.","on-icon-class":"on-icon-class is renamed to active-icon-class.","off-icon-class":"off-icon-class is renamed to inactive-icon-class."}}}},mounted:function(){this.coreWidth=this.width||40,(this.activeColor||this.inactiveColor)&&this.setBackgroundColor(),this.$refs.input.checked=this.checked}},d=n(0),f=Object(d.a)(u,i,[],!1,null,null,null);f.options.__file="packages/switch/src/component.vue";var p=f.exports;p.install=function(e){e.component(p.name,p)};t.default=p}})},85517:e=>{e.exports=function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist/",n(n.s=101)}({0:function(e,t,n){"use strict";function i(e,t,n,i,r,o,s,a){var l,c="function"==typeof e?e.options:e;if(t&&(c.render=t,c.staticRenderFns=n,c._compiled=!0),i&&(c.functional=!0),o&&(c._scopeId="data-v-"+o),s?(l=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),r&&r.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(s)},c._ssrRegister=l):r&&(l=a?function(){r.call(this,this.$root.$options.shadowRoot)}:r),l)if(c.functional){c._injectStyles=l;var u=c.render;c.render=function(e,t){return l.call(t),u(e,t)}}else{var d=c.beforeCreate;c.beforeCreate=d?[].concat(d,l):[l]}return{exports:e,options:c}}n.d(t,"a",(function(){return i}))},101:function(e,t,n){"use strict";n.r(t);var i=function(){var e=this,t=e.$createElement,n=e._self._c||t;return!e.lazy||e.loaded||e.active?n("div",{directives:[{name:"show",rawName:"v-show",value:e.active,expression:"active"}],staticClass:"el-tab-pane",attrs:{role:"tabpanel","aria-hidden":!e.active,id:"pane-"+e.paneName,"aria-labelledby":"tab-"+e.paneName}},[e._t("default")],2):e._e()};i._withStripped=!0;var r={name:"ElTabPane",componentName:"ElTabPane",props:{label:String,labelContent:Function,name:String,closable:Boolean,disabled:Boolean,lazy:Boolean},data:function(){return{index:null,loaded:!1}},computed:{isClosable:function(){return this.closable||this.$parent.closable},active:function(){var e=this.$parent.currentName===(this.name||this.index);return e&&(this.loaded=!0),e},paneName:function(){return this.name||this.index}},updated:function(){this.$parent.$emit("tab-nav-update")}},o=n(0),s=Object(o.a)(r,i,[],!1,null,null,null);s.options.__file="packages/tabs/src/tab-pane.vue";var a=s.exports;a.install=function(e){e.component(a.name,a)};t.default=a}})},44242:(e,t,n)=>{e.exports=function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist/",n(n.s=63)}({0:function(e,t,n){"use strict";function i(e,t,n,i,r,o,s,a){var l,c="function"==typeof e?e.options:e;if(t&&(c.render=t,c.staticRenderFns=n,c._compiled=!0),i&&(c.functional=!0),o&&(c._scopeId="data-v-"+o),s?(l=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),r&&r.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(s)},c._ssrRegister=l):r&&(l=a?function(){r.call(this,this.$root.$options.shadowRoot)}:r),l)if(c.functional){c._injectStyles=l;var u=c.render;c.render=function(e,t){return l.call(t),u(e,t)}}else{var d=c.beforeCreate;c.beforeCreate=d?[].concat(d,l):[l]}return{exports:e,options:c}}n.d(t,"a",(function(){return i}))},16:function(e,t){e.exports=n(16567)},3:function(e,t){e.exports=n(93104)},63:function(e,t,n){"use strict";n.r(t);var i=function(){var e=this,t=e.$createElement;return(e._self._c||t)("div",{staticClass:"el-tabs__active-bar",class:"is-"+e.rootTabs.tabPosition,style:e.barStyle})};i._withStripped=!0;var r=n(3),o={name:"TabBar",props:{tabs:Array},inject:["rootTabs"],computed:{barStyle:{get:function(){var e=this,t={},n=0,i=0,o=-1!==["top","bottom"].indexOf(this.rootTabs.tabPosition)?"width":"height",s="width"===o?"x":"y",a=function(e){return e.toLowerCase().replace(/( |^)[a-z]/g,(function(e){return e.toUpperCase()}))};this.tabs.every((function(t,s){var l=Object(r.arrayFind)(e.$parent.$refs.tabs||[],(function(e){return e.id.replace("tab-","")===t.paneName}));if(!l)return!1;if(t.active){i=l["client"+a(o)];var c=window.getComputedStyle(l);return"width"===o&&e.tabs.length>1&&(i-=parseFloat(c.paddingLeft)+parseFloat(c.paddingRight)),"width"===o&&(n+=parseFloat(c.paddingLeft)),!1}return n+=l["client"+a(o)],!0}));var l="translate"+a(s)+"("+n+"px)";return t[o]=i+"px",t.transform=l,t.msTransform=l,t.webkitTransform=l,t}}}},s=n(0),a=Object(s.a)(o,i,[],!1,null,null,null);a.options.__file="packages/tabs/src/tab-bar.vue";var l=a.exports,c=n(16);function u(){}var d=function(e){return e.toLowerCase().replace(/( |^)[a-z]/g,(function(e){return e.toUpperCase()}))},f={name:"TabNav",components:{TabBar:l},inject:["rootTabs"],props:{panes:Array,currentName:String,editable:Boolean,onTabClick:{type:Function,default:u},onTabRemove:{type:Function,default:u},type:String,stretch:Boolean},data:function(){return{scrollable:!1,navOffset:0,isFocus:!1,focusable:!0}},computed:{navStyle:function(){return{transform:"translate"+(-1!==["top","bottom"].indexOf(this.rootTabs.tabPosition)?"X":"Y")+"(-"+this.navOffset+"px)"}},sizeName:function(){return-1!==["top","bottom"].indexOf(this.rootTabs.tabPosition)?"width":"height"}},methods:{scrollPrev:function(){var e=this.$refs.navScroll["offset"+d(this.sizeName)],t=this.navOffset;if(t){var n=t>e?t-e:0;this.navOffset=n}},scrollNext:function(){var e=this.$refs.nav["offset"+d(this.sizeName)],t=this.$refs.navScroll["offset"+d(this.sizeName)],n=this.navOffset;if(!(e-n<=t)){var i=e-n>2*t?n+t:e-t;this.navOffset=i}},scrollToActiveTab:function(){if(this.scrollable){var e=this.$refs.nav,t=this.$el.querySelector(".is-active");if(t){var n=this.$refs.navScroll,i=-1!==["top","bottom"].indexOf(this.rootTabs.tabPosition),r=t.getBoundingClientRect(),o=n.getBoundingClientRect(),s=i?e.offsetWidth-o.width:e.offsetHeight-o.height,a=this.navOffset,l=a;i?(r.lefto.right&&(l=a+r.right-o.right)):(r.topo.bottom&&(l=a+(r.bottom-o.bottom))),l=Math.max(l,0),this.navOffset=Math.min(l,s)}}},update:function(){if(this.$refs.nav){var e=this.sizeName,t=this.$refs.nav["offset"+d(e)],n=this.$refs.navScroll["offset"+d(e)],i=this.navOffset;if(n0&&(this.navOffset=0)}},changeTab:function(e){var t=e.keyCode,n=void 0,i=void 0,r=void 0;-1!==[37,38,39,40].indexOf(t)&&(r=e.currentTarget.querySelectorAll("[role=tab]"),i=Array.prototype.indexOf.call(r,e.target),r[n=37===t||38===t?0===i?r.length-1:i-1:i0&&void 0!==arguments[0]&&arguments[0];if(this.$slots.default){var n=this.$slots.default.filter((function(e){return e.tag&&e.componentOptions&&"ElTabPane"===e.componentOptions.Ctor.options.name})).map((function(e){return e.componentInstance})),i=!(n.length===this.panes.length&&n.every((function(t,n){return t===e.panes[n]})));(t||i)&&(this.panes=n)}else 0!==this.panes.length&&(this.panes=[])},handleTabClick:function(e,t,n){e.disabled||(this.setCurrentName(t),this.$emit("tab-click",e,n))},handleTabRemove:function(e,t){e.disabled||(t.stopPropagation(),this.$emit("edit",e.name,"remove"),this.$emit("tab-remove",e.name))},handleTabAdd:function(){this.$emit("edit",null,"add"),this.$emit("tab-add")},setCurrentName:function(e){var t=this,n=function(){t.currentName=e,t.$emit("input",e)};if(this.currentName!==e&&this.beforeLeave){var i=this.beforeLeave(e,this.currentName);i&&i.then?i.then((function(){n(),t.$refs.nav&&t.$refs.nav.removeFocus()}),(function(){})):!1!==i&&n()}else n()}},render:function(e){var t,n=this.type,i=this.handleTabClick,r=this.handleTabRemove,o=this.handleTabAdd,s=this.currentName,a=this.panes,l=this.editable,c=this.addable,u=this.tabPosition,d=this.stretch,f=l||c?e("span",{class:"el-tabs__new-tab",on:{click:o,keydown:function(e){13===e.keyCode&&o()}},attrs:{tabindex:"0"}},[e("i",{class:"el-icon-plus"})]):null,p=e("div",{class:["el-tabs__header","is-"+u]},[f,e("tab-nav",{props:{currentName:s,onTabClick:i,onTabRemove:r,editable:l,type:n,panes:a,stretch:d},ref:"nav"})]),h=e("div",{class:"el-tabs__content"},[this.$slots.default]);return e("div",{class:(t={"el-tabs":!0,"el-tabs--card":"card"===n},t["el-tabs--"+u]=!0,t["el-tabs--border-card"]="border-card"===n,t)},["bottom"!==u?[p,h]:[h,p]])},created:function(){this.currentName||this.setCurrentName("0"),this.$on("tab-nav-update",this.calcPaneInstances.bind(null,!0))},mounted:function(){this.calcPaneInstances()},updated:function(){this.calcPaneInstances()}},m=v,_=Object(s.a)(m,undefined,undefined,!1,null,null,null);_.options.__file="packages/tabs/src/tabs.vue";var g=_.exports;g.install=function(e){e.component(g.name,g)};t.default=g}})},27698:e=>{e.exports=function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist/",n(n.s=132)}({0:function(e,t,n){"use strict";function i(e,t,n,i,r,o,s,a){var l,c="function"==typeof e?e.options:e;if(t&&(c.render=t,c.staticRenderFns=n,c._compiled=!0),i&&(c.functional=!0),o&&(c._scopeId="data-v-"+o),s?(l=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),r&&r.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(s)},c._ssrRegister=l):r&&(l=a?function(){r.call(this,this.$root.$options.shadowRoot)}:r),l)if(c.functional){c._injectStyles=l;var u=c.render;c.render=function(e,t){return l.call(t),u(e,t)}}else{var d=c.beforeCreate;c.beforeCreate=d?[].concat(d,l):[l]}return{exports:e,options:c}}n.d(t,"a",(function(){return i}))},132:function(e,t,n){"use strict";n.r(t);var i={name:"ElTag",props:{text:String,closable:Boolean,type:String,hit:Boolean,disableTransitions:Boolean,color:String,size:String,effect:{type:String,default:"light",validator:function(e){return-1!==["dark","light","plain"].indexOf(e)}}},methods:{handleClose:function(e){e.stopPropagation(),this.$emit("close",e)},handleClick:function(e){this.$emit("click",e)}},computed:{tagSize:function(){return this.size||(this.$ELEMENT||{}).size}},render:function(e){var t=this.type,n=this.tagSize,i=this.hit,r=this.effect,o=e("span",{class:["el-tag",t?"el-tag--"+t:"",n?"el-tag--"+n:"",r?"el-tag--"+r:"",i&&"is-hit"],style:{backgroundColor:this.color},on:{click:this.handleClick}},[this.$slots.default,this.closable&&e("i",{class:"el-tag__close el-icon-close",on:{click:this.handleClose}})]);return this.disableTransitions?o:e("transition",{attrs:{name:"el-zoom-in-center"}},[o])}},r=n(0),o=Object(r.a)(i,undefined,undefined,!1,null,null,null);o.options.__file="packages/tag/src/tag.vue";var s=o.exports;s.install=function(e){e.component(s.name,s)};t.default=s}})},14561:(e,t,n)=>{e.exports=function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist/",n(n.s=138)}({138:function(e,t,n){"use strict";n.r(t);var i=n(5),r=n.n(i),o=n(19),s=n.n(o),a=n(2),l=n(3),c=n(7),u=n.n(c),d={name:"ElTooltip",mixins:[r.a],props:{openDelay:{type:Number,default:0},disabled:Boolean,manual:Boolean,effect:{type:String,default:"dark"},arrowOffset:{type:Number,default:0},popperClass:String,content:String,visibleArrow:{default:!0},transition:{type:String,default:"el-fade-in-linear"},popperOptions:{default:function(){return{boundariesPadding:10,gpuAcceleration:!1}}},enterable:{type:Boolean,default:!0},hideAfter:{type:Number,default:0},tabindex:{type:Number,default:0}},data:function(){return{tooltipId:"el-tooltip-"+Object(l.generateId)(),timeoutPending:null,focusing:!1}},beforeCreate:function(){var e=this;this.$isServer||(this.popperVM=new u.a({data:{node:""},render:function(e){return this.node}}).$mount(),this.debounceClose=s()(200,(function(){return e.handleClosePopper()})))},render:function(e){var t=this;this.popperVM&&(this.popperVM.node=e("transition",{attrs:{name:this.transition},on:{afterLeave:this.doDestroy}},[e("div",{on:{mouseleave:function(){t.setExpectedState(!1),t.debounceClose()},mouseenter:function(){t.setExpectedState(!0)}},ref:"popper",attrs:{role:"tooltip",id:this.tooltipId,"aria-hidden":this.disabled||!this.showPopper?"true":"false"},directives:[{name:"show",value:!this.disabled&&this.showPopper}],class:["el-tooltip__popper","is-"+this.effect,this.popperClass]},[this.$slots.content||this.content])]));var n=this.getFirstElement();if(!n)return null;var i=n.data=n.data||{};return i.staticClass=this.addTooltipClass(i.staticClass),n},mounted:function(){var e=this;this.referenceElm=this.$el,1===this.$el.nodeType&&(this.$el.setAttribute("aria-describedby",this.tooltipId),this.$el.setAttribute("tabindex",this.tabindex),Object(a.on)(this.referenceElm,"mouseenter",this.show),Object(a.on)(this.referenceElm,"mouseleave",this.hide),Object(a.on)(this.referenceElm,"focus",(function(){if(e.$slots.default&&e.$slots.default.length){var t=e.$slots.default[0].componentInstance;t&&t.focus?t.focus():e.handleFocus()}else e.handleFocus()})),Object(a.on)(this.referenceElm,"blur",this.handleBlur),Object(a.on)(this.referenceElm,"click",this.removeFocusing)),this.value&&this.popperVM&&this.popperVM.$nextTick((function(){e.value&&e.updatePopper()}))},watch:{focusing:function(e){e?Object(a.addClass)(this.referenceElm,"focusing"):Object(a.removeClass)(this.referenceElm,"focusing")}},methods:{show:function(){this.setExpectedState(!0),this.handleShowPopper()},hide:function(){this.setExpectedState(!1),this.debounceClose()},handleFocus:function(){this.focusing=!0,this.show()},handleBlur:function(){this.focusing=!1,this.hide()},removeFocusing:function(){this.focusing=!1},addTooltipClass:function(e){return e?"el-tooltip "+e.replace("el-tooltip",""):"el-tooltip"},handleShowPopper:function(){var e=this;this.expectedState&&!this.manual&&(clearTimeout(this.timeout),this.timeout=setTimeout((function(){e.showPopper=!0}),this.openDelay),this.hideAfter>0&&(this.timeoutPending=setTimeout((function(){e.showPopper=!1}),this.hideAfter)))},handleClosePopper:function(){this.enterable&&this.expectedState||this.manual||(clearTimeout(this.timeout),this.timeoutPending&&clearTimeout(this.timeoutPending),this.showPopper=!1,this.disabled&&this.doDestroy())},setExpectedState:function(e){!1===e&&clearTimeout(this.timeoutPending),this.expectedState=e},getFirstElement:function(){var e=this.$slots.default;if(!Array.isArray(e))return null;for(var t=null,n=0;n{"use strict";t.__esModule=!0;var i=n(34594);var r=function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e)}return e.prototype.beforeEnter=function(e){(0,i.addClass)(e,"collapse-transition"),e.dataset||(e.dataset={}),e.dataset.oldPaddingTop=e.style.paddingTop,e.dataset.oldPaddingBottom=e.style.paddingBottom,e.style.height="0",e.style.paddingTop=0,e.style.paddingBottom=0},e.prototype.enter=function(e){e.dataset.oldOverflow=e.style.overflow,0!==e.scrollHeight?(e.style.height=e.scrollHeight+"px",e.style.paddingTop=e.dataset.oldPaddingTop,e.style.paddingBottom=e.dataset.oldPaddingBottom):(e.style.height="",e.style.paddingTop=e.dataset.oldPaddingTop,e.style.paddingBottom=e.dataset.oldPaddingBottom),e.style.overflow="hidden"},e.prototype.afterEnter=function(e){(0,i.removeClass)(e,"collapse-transition"),e.style.height="",e.style.overflow=e.dataset.oldOverflow},e.prototype.beforeLeave=function(e){e.dataset||(e.dataset={}),e.dataset.oldPaddingTop=e.style.paddingTop,e.dataset.oldPaddingBottom=e.style.paddingBottom,e.dataset.oldOverflow=e.style.overflow,e.style.height=e.scrollHeight+"px",e.style.overflow="hidden"},e.prototype.leave=function(e){0!==e.scrollHeight&&((0,i.addClass)(e,"collapse-transition"),e.style.height=0,e.style.paddingTop=0,e.style.paddingBottom=0)},e.prototype.afterLeave=function(e){(0,i.removeClass)(e,"collapse-transition"),e.style.height="",e.style.overflow=e.dataset.oldOverflow,e.style.paddingTop=e.dataset.oldPaddingTop,e.style.paddingBottom=e.dataset.oldPaddingBottom},e}();t.default={name:"ElCollapseTransition",functional:!0,render:function(e,t){var n=t.children;return e("transition",{on:new r},n)}}},79634:(e,t)=>{"use strict";t.__esModule=!0,t.default=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:300,i=arguments.length>3&&void 0!==arguments[3]&&arguments[3];if(!e||!t)throw new Error("instance & callback is required");var r=!1,o=function(){r||(r=!0,t&&t.apply(null,arguments))};i?e.$once("after-leave",o):e.$on("after-leave",o),setTimeout((function(){o()}),n+100)}},1080:(e,t,n)=>{"use strict";t.__esModule=!0;var i,r=n(70538),o=(i=r)&&i.__esModule?i:{default:i},s=n(34594);var a=[],l="@@clickoutsideContext",c=void 0,u=0;function d(e,t,n){return function(){var i=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};!(n&&n.context&&i.target&&r.target)||e.contains(i.target)||e.contains(r.target)||e===i.target||n.context.popperElm&&(n.context.popperElm.contains(i.target)||n.context.popperElm.contains(r.target))||(t.expression&&e[l].methodName&&n.context[e[l].methodName]?n.context[e[l].methodName]():e[l].bindingFn&&e[l].bindingFn())}}!o.default.prototype.$isServer&&(0,s.on)(document,"mousedown",(function(e){return c=e})),!o.default.prototype.$isServer&&(0,s.on)(document,"mouseup",(function(e){a.forEach((function(t){return t[l].documentHandler(e,c)}))})),t.default={bind:function(e,t,n){a.push(e);var i=u++;e[l]={id:i,documentHandler:d(e,t,n),methodName:t.expression,bindingFn:t.value}},update:function(e,t,n){e[l].documentHandler=d(e,t,n),e[l].methodName=t.expression,e[l].bindingFn=t.value},unbind:function(e){for(var t=a.length,n=0;n{"use strict";t.__esModule=!0,t.isInContainer=t.getScrollContainer=t.isScroll=t.getStyle=t.once=t.off=t.on=void 0;var i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};t.hasClass=h,t.addClass=function(e,t){if(!e)return;for(var n=e.className,i=(t||"").split(" "),r=0,o=i.length;r-1}var v=t.getStyle=c<9?function(e,t){if(!s){if(!e||!t)return null;"float"===(t=d(t))&&(t="styleFloat");try{if("opacity"===t)try{return e.filters.item("alpha").opacity/100}catch(e){return 1}return e.style[t]||e.currentStyle?e.currentStyle[t]:null}catch(n){return e.style[t]}}}:function(e,t){if(!s){if(!e||!t)return null;"float"===(t=d(t))&&(t="cssFloat");try{var n=document.defaultView.getComputedStyle(e,"");return e.style[t]||n?n[t]:null}catch(n){return e.style[t]}}};var m=t.isScroll=function(e,t){if(!s)return v(e,null!=t?t?"overflow-y":"overflow-x":"overflow").match(/(scroll|auto|overlay)/)};t.getScrollContainer=function(e,t){if(!s){for(var n=e;n;){if([window,document,document.documentElement].includes(n))return window;if(m(n,t))return n;n=n.parentNode}return n}},t.isInContainer=function(e,t){if(s||!e||!t)return!1;var n=e.getBoundingClientRect(),i=void 0;return i=[window,document,document.documentElement,null,void 0].includes(t)?{top:0,right:window.innerWidth,bottom:window.innerHeight,left:0}:t.getBoundingClientRect(),n.topi.top&&n.right>i.left&&n.left{"use strict";t.__esModule=!0,t.default=function(e){for(var t=1,n=arguments.length;t{"use strict";var i,r;"function"==typeof Symbol&&Symbol.iterator;void 0===(r="function"==typeof(i=function(){var e=window,t={placement:"bottom",gpuAcceleration:!0,offset:0,boundariesElement:"viewport",boundariesPadding:5,preventOverflowOrder:["left","right","top","bottom"],flipBehavior:"flip",arrowElement:"[x-arrow]",arrowOffset:0,modifiers:["shift","offset","preventOverflow","keepTogether","arrow","flip","applyStyle"],modifiersIgnored:[],forceAbsolute:!1};function n(e,n,i){this._reference=e.jquery?e[0]:e,this.state={};var r=null==n,o=n&&"[object Object]"===Object.prototype.toString.call(n);return this._popper=r||o?this.parse(o?n:{}):n.jquery?n[0]:n,this._options=Object.assign({},t,i),this._options.modifiers=this._options.modifiers.map(function(e){if(-1===this._options.modifiersIgnored.indexOf(e))return"applyStyle"===e&&this._popper.setAttribute("x-placement",this._options.placement),this.modifiers[e]||e}.bind(this)),this.state.position=this._getPosition(this._popper,this._reference),d(this._popper,{position:this.state.position,top:0}),this.update(),this._setupEventListeners(),this}function i(t){var n=t.style.display,i=t.style.visibility;t.style.display="block",t.style.visibility="hidden",t.offsetWidth;var r=e.getComputedStyle(t),o=parseFloat(r.marginTop)+parseFloat(r.marginBottom),s=parseFloat(r.marginLeft)+parseFloat(r.marginRight),a={width:t.offsetWidth+s,height:t.offsetHeight+o};return t.style.display=n,t.style.visibility=i,a}function r(e){var t={left:"right",right:"left",bottom:"top",top:"bottom"};return e.replace(/left|right|bottom|top/g,(function(e){return t[e]}))}function o(e){var t=Object.assign({},e);return t.right=t.left+t.width,t.bottom=t.top+t.height,t}function s(e,t){var n,i=0;for(n in e){if(e[n]===t)return i;i++}return null}function a(t,n){return e.getComputedStyle(t,null)[n]}function l(t){var n=t.offsetParent;return n!==e.document.body&&n?n:e.document.documentElement}function c(t){var n=t.parentNode;return n?n===e.document?e.document.body.scrollTop||e.document.body.scrollLeft?e.document.body:e.document.documentElement:-1!==["scroll","auto"].indexOf(a(n,"overflow"))||-1!==["scroll","auto"].indexOf(a(n,"overflow-x"))||-1!==["scroll","auto"].indexOf(a(n,"overflow-y"))?n:c(t.parentNode):t}function u(t){return t!==e.document.body&&("fixed"===a(t,"position")||(t.parentNode?u(t.parentNode):t))}function d(e,t){function n(e){return""!==e&&!isNaN(parseFloat(e))&&isFinite(e)}Object.keys(t).forEach((function(i){var r="";-1!==["width","height","top","right","bottom","left"].indexOf(i)&&n(t[i])&&(r="px"),e.style[i]=t[i]+r}))}function f(e){return e&&"[object Function]"==={}.toString.call(e)}function p(e){var t={width:e.offsetWidth,height:e.offsetHeight,left:e.offsetLeft,top:e.offsetTop};return t.right=t.left+t.width,t.bottom=t.top+t.height,t}function h(e){var t=e.getBoundingClientRect(),n=-1!=navigator.userAgent.indexOf("MSIE")&&"HTML"===e.tagName?-e.scrollTop:t.top;return{left:t.left,top:n,right:t.right,bottom:t.bottom,width:t.right-t.left,height:t.bottom-n}}function v(e,t,n){var i=h(e),r=h(t);if(n){var o=c(t);r.top+=o.scrollTop,r.bottom+=o.scrollTop,r.left+=o.scrollLeft,r.right+=o.scrollLeft}return{top:i.top-r.top,left:i.left-r.left,bottom:i.top-r.top+i.height,right:i.left-r.left+i.width,width:i.width,height:i.height}}function m(t){for(var n=["","ms","webkit","moz","o"],i=0;i1&&console.warn("WARNING: the given `parent` query("+t.parent+") matched more than one element, the first one will be used"),0===s.length)throw"ERROR: the given `parent` doesn't exists!";s=s[0]}return s.length>1&&s instanceof Element==0&&(console.warn("WARNING: you have passed as parent a list of elements, the first one will be used"),s=s[0]),s.appendChild(r),r;function a(e,t){t.forEach((function(t){e.classList.add(t)}))}function l(e,t){t.forEach((function(t){e.setAttribute(t.split(":")[0],t.split(":")[1]||"")}))}},n.prototype._getPosition=function(e,t){var n=l(t);return this._options.forceAbsolute?"absolute":u(t,n)?"fixed":"absolute"},n.prototype._getOffsets=function(e,t,n){n=n.split("-")[0];var r={};r.position=this.state.position;var o="fixed"===r.position,s=v(t,l(e),o),a=i(e);return-1!==["right","left"].indexOf(n)?(r.top=s.top+s.height/2-a.height/2,r.left="left"===n?s.left-a.width:s.right):(r.left=s.left+s.width/2-a.width/2,r.top="top"===n?s.top-a.height:s.bottom),r.width=a.width,r.height=a.height,{popper:r,reference:s}},n.prototype._setupEventListeners=function(){if(this.state.updateBound=this.update.bind(this),e.addEventListener("resize",this.state.updateBound),"window"!==this._options.boundariesElement){var t=c(this._reference);t!==e.document.body&&t!==e.document.documentElement||(t=e),t.addEventListener("scroll",this.state.updateBound),this.state.scrollTarget=t}},n.prototype._removeEventListeners=function(){e.removeEventListener("resize",this.state.updateBound),"window"!==this._options.boundariesElement&&this.state.scrollTarget&&(this.state.scrollTarget.removeEventListener("scroll",this.state.updateBound),this.state.scrollTarget=null),this.state.updateBound=null},n.prototype._getBoundaries=function(t,n,i){var r,o={};if("window"===i){var s=e.document.body,a=e.document.documentElement;r=Math.max(s.scrollHeight,s.offsetHeight,a.clientHeight,a.scrollHeight,a.offsetHeight),o={top:0,right:Math.max(s.scrollWidth,s.offsetWidth,a.clientWidth,a.scrollWidth,a.offsetWidth),bottom:r,left:0}}else if("viewport"===i){var u=l(this._popper),d=c(this._popper),f=p(u),h=function(e){return e==document.body?Math.max(document.documentElement.scrollTop,document.body.scrollTop):e.scrollTop},v=function(e){return e==document.body?Math.max(document.documentElement.scrollLeft,document.body.scrollLeft):e.scrollLeft},m="fixed"===t.offsets.popper.position?0:h(d),_="fixed"===t.offsets.popper.position?0:v(d);o={top:0-(f.top-m),right:e.document.documentElement.clientWidth-(f.left-_),bottom:e.document.documentElement.clientHeight-(f.top-m),left:0-(f.left-_)}}else o=l(this._popper)===i?{top:0,left:0,right:i.clientWidth,bottom:i.clientHeight}:p(i);return o.left+=n,o.right-=n,o.top=o.top+n,o.bottom=o.bottom-n,o},n.prototype.runModifiers=function(e,t,n){var i=t.slice();return void 0!==n&&(i=this._options.modifiers.slice(0,s(this._options.modifiers,n))),i.forEach(function(t){f(t)&&(e=t.call(this,e))}.bind(this)),e},n.prototype.isModifierRequired=function(e,t){var n=s(this._options.modifiers,e);return!!this._options.modifiers.slice(0,n).filter((function(e){return e===t})).length},n.prototype.modifiers={},n.prototype.modifiers.applyStyle=function(e){var t,n={position:e.offsets.popper.position},i=Math.round(e.offsets.popper.left),r=Math.round(e.offsets.popper.top);return this._options.gpuAcceleration&&(t=m("transform"))?(n[t]="translate3d("+i+"px, "+r+"px, 0)",n.top=0,n.left=0):(n.left=i,n.top=r),Object.assign(n,e.styles),d(this._popper,n),this._popper.setAttribute("x-placement",e.placement),this.isModifierRequired(this.modifiers.applyStyle,this.modifiers.arrow)&&e.offsets.arrow&&d(e.arrowElement,e.offsets.arrow),e},n.prototype.modifiers.shift=function(e){var t=e.placement,n=t.split("-")[0],i=t.split("-")[1];if(i){var r=e.offsets.reference,s=o(e.offsets.popper),a={y:{start:{top:r.top},end:{top:r.top+r.height-s.height}},x:{start:{left:r.left},end:{left:r.left+r.width-s.width}}},l=-1!==["bottom","top"].indexOf(n)?"x":"y";e.offsets.popper=Object.assign(s,a[l][i])}return e},n.prototype.modifiers.preventOverflow=function(e){var t=this._options.preventOverflowOrder,n=o(e.offsets.popper),i={left:function(){var t=n.left;return n.lefte.boundaries.right&&(t=Math.min(n.left,e.boundaries.right-n.width)),{left:t}},top:function(){var t=n.top;return n.tope.boundaries.bottom&&(t=Math.min(n.top,e.boundaries.bottom-n.height)),{top:t}}};return t.forEach((function(t){e.offsets.popper=Object.assign(n,i[t]())})),e},n.prototype.modifiers.keepTogether=function(e){var t=o(e.offsets.popper),n=e.offsets.reference,i=Math.floor;return t.righti(n.right)&&(e.offsets.popper.left=i(n.right)),t.bottomi(n.bottom)&&(e.offsets.popper.top=i(n.bottom)),e},n.prototype.modifiers.flip=function(e){if(!this.isModifierRequired(this.modifiers.flip,this.modifiers.preventOverflow))return console.warn("WARNING: preventOverflow modifier is required by flip modifier in order to work, be sure to include it before flip!"),e;if(e.flipped&&e.placement===e._originalPlacement)return e;var t=e.placement.split("-")[0],n=r(t),i=e.placement.split("-")[1]||"",s=[];return(s="flip"===this._options.flipBehavior?[t,n]:this._options.flipBehavior).forEach(function(a,l){if(t===a&&s.length!==l+1){t=e.placement.split("-")[0],n=r(t);var c=o(e.offsets.popper),u=-1!==["right","bottom"].indexOf(t);(u&&Math.floor(e.offsets.reference[t])>Math.floor(c[n])||!u&&Math.floor(e.offsets.reference[t])a[p]&&(e.offsets.popper[d]+=l[d]+h-a[p]);var v=l[d]+(n||l[u]/2-h/2)-a[d];return v=Math.max(Math.min(a[u]-h-8,v),8),r[d]=v,r[f]="",e.offsets.arrow=r,e.arrowElement=t,e},Object.assign||Object.defineProperty(Object,"assign",{enumerable:!1,configurable:!0,writable:!0,value:function(e){if(null==e)throw new TypeError("Cannot convert first argument to object");for(var t=Object(e),n=1;n{"use strict";t.__esModule=!0,t.PopupManager=void 0;var i=l(n(70538)),r=l(n(21615)),o=l(n(7562)),s=l(n(81301)),a=n(34594);function l(e){return e&&e.__esModule?e:{default:e}}var c=1,u=void 0;t.default={props:{visible:{type:Boolean,default:!1},openDelay:{},closeDelay:{},zIndex:{},modal:{type:Boolean,default:!1},modalFade:{type:Boolean,default:!0},modalClass:{},modalAppendToBody:{type:Boolean,default:!1},lockScroll:{type:Boolean,default:!0},closeOnPressEscape:{type:Boolean,default:!1},closeOnClickModal:{type:Boolean,default:!1}},beforeMount:function(){this._popupId="popup-"+c++,o.default.register(this._popupId,this)},beforeDestroy:function(){o.default.deregister(this._popupId),o.default.closeModal(this._popupId),this.restoreBodyStyle()},data:function(){return{opened:!1,bodyPaddingRight:null,computedBodyPaddingRight:0,withoutHiddenClass:!0,rendered:!1}},watch:{visible:function(e){var t=this;if(e){if(this._opening)return;this.rendered?this.open():(this.rendered=!0,i.default.nextTick((function(){t.open()})))}else this.close()}},methods:{open:function(e){var t=this;this.rendered||(this.rendered=!0);var n=(0,r.default)({},this.$props||this,e);this._closeTimer&&(clearTimeout(this._closeTimer),this._closeTimer=null),clearTimeout(this._openTimer);var i=Number(n.openDelay);i>0?this._openTimer=setTimeout((function(){t._openTimer=null,t.doOpen(n)}),i):this.doOpen(n)},doOpen:function(e){if(!this.$isServer&&(!this.willOpen||this.willOpen())&&!this.opened){this._opening=!0;var t=this.$el,n=e.modal,i=e.zIndex;if(i&&(o.default.zIndex=i),n&&(this._closing&&(o.default.closeModal(this._popupId),this._closing=!1),o.default.openModal(this._popupId,o.default.nextZIndex(),this.modalAppendToBody?void 0:t,e.modalClass,e.modalFade),e.lockScroll)){this.withoutHiddenClass=!(0,a.hasClass)(document.body,"el-popup-parent--hidden"),this.withoutHiddenClass&&(this.bodyPaddingRight=document.body.style.paddingRight,this.computedBodyPaddingRight=parseInt((0,a.getStyle)(document.body,"paddingRight"),10)),u=(0,s.default)();var r=document.documentElement.clientHeight0&&(r||"scroll"===l)&&this.withoutHiddenClass&&(document.body.style.paddingRight=this.computedBodyPaddingRight+u+"px"),(0,a.addClass)(document.body,"el-popup-parent--hidden")}"static"===getComputedStyle(t).position&&(t.style.position="absolute"),t.style.zIndex=o.default.nextZIndex(),this.opened=!0,this.onOpen&&this.onOpen(),this.doAfterOpen()}},doAfterOpen:function(){this._opening=!1},close:function(){var e=this;if(!this.willClose||this.willClose()){null!==this._openTimer&&(clearTimeout(this._openTimer),this._openTimer=null),clearTimeout(this._closeTimer);var t=Number(this.closeDelay);t>0?this._closeTimer=setTimeout((function(){e._closeTimer=null,e.doClose()}),t):this.doClose()}},doClose:function(){this._closing=!0,this.onClose&&this.onClose(),this.lockScroll&&setTimeout(this.restoreBodyStyle,200),this.opened=!1,this.doAfterClose()},doAfterClose:function(){o.default.closeModal(this._popupId),this._closing=!1},restoreBodyStyle:function(){this.modal&&this.withoutHiddenClass&&(document.body.style.paddingRight=this.bodyPaddingRight,(0,a.removeClass)(document.body,"el-popup-parent--hidden")),this.withoutHiddenClass=!0}}},t.PopupManager=o.default},7562:(e,t,n)=>{"use strict";t.__esModule=!0;var i,r=n(70538),o=(i=r)&&i.__esModule?i:{default:i},s=n(34594);var a=!1,l=!1,c=void 0,u=function(){if(!o.default.prototype.$isServer){var e=f.modalDom;return e?a=!0:(a=!1,e=document.createElement("div"),f.modalDom=e,e.addEventListener("touchmove",(function(e){e.preventDefault(),e.stopPropagation()})),e.addEventListener("click",(function(){f.doOnModalClick&&f.doOnModalClick()}))),e}},d={},f={modalFade:!0,getInstance:function(e){return d[e]},register:function(e,t){e&&t&&(d[e]=t)},deregister:function(e){e&&(d[e]=null,delete d[e])},nextZIndex:function(){return f.zIndex++},modalStack:[],doOnModalClick:function(){var e=f.modalStack[f.modalStack.length-1];if(e){var t=f.getInstance(e.id);t&&t.closeOnClickModal&&t.close()}},openModal:function(e,t,n,i,r){if(!o.default.prototype.$isServer&&e&&void 0!==t){this.modalFade=r;for(var l=this.modalStack,c=0,d=l.length;c0){var i=t[t.length-1];if(i.id===e){if(i.modalClass)i.modalClass.trim().split(/\s+/).forEach((function(e){return(0,s.removeClass)(n,e)}));t.pop(),t.length>0&&(n.style.zIndex=t[t.length-1].zIndex)}else for(var r=t.length-1;r>=0;r--)if(t[r].id===e){t.splice(r,1);break}}0===t.length&&(this.modalFade&&(0,s.addClass)(n,"v-modal-leave"),setTimeout((function(){0===t.length&&(n.parentNode&&n.parentNode.removeChild(n),n.style.display="none",f.modalDom=void 0),(0,s.removeClass)(n,"v-modal-leave")}),200))}};Object.defineProperty(f,"zIndex",{configurable:!0,get:function(){return l||(c=c||(o.default.prototype.$ELEMENT||{}).zIndex||2e3,l=!0),c},set:function(e){c=e}});o.default.prototype.$isServer||window.addEventListener("keydown",(function(e){if(27===e.keyCode){var t=function(){if(!o.default.prototype.$isServer&&f.modalStack.length>0){var e=f.modalStack[f.modalStack.length-1];if(!e)return;return f.getInstance(e.id)}}();t&&t.closeOnPressEscape&&(t.handleClose?t.handleClose():t.handleAction?t.handleAction("cancel"):t.close())}})),t.default=f},16567:(e,t,n)=>{"use strict";t.__esModule=!0,t.removeResizeListener=t.addResizeListener=void 0;var i,r=n(91033),o=(i=r)&&i.__esModule?i:{default:i},s=n(44592);var a="undefined"==typeof window,l=function(e){var t=e,n=Array.isArray(t),i=0;for(t=n?t:t[Symbol.iterator]();;){var r;if(n){if(i>=t.length)break;r=t[i++]}else{if((i=t.next()).done)break;r=i.value}var o=r.target.__resizeListeners__||[];o.length&&o.forEach((function(e){e()}))}};t.addResizeListener=function(e,t){a||(e.__resizeListeners__||(e.__resizeListeners__=[],e.__ro__=new o.default((0,s.debounce)(16,l)),e.__ro__.observe(e)),e.__resizeListeners__.push(t))},t.removeResizeListener=function(e,t){e&&e.__resizeListeners__&&(e.__resizeListeners__.splice(e.__resizeListeners__.indexOf(t),1),e.__resizeListeners__.length||e.__ro__.disconnect())}},78275:(e,t,n)=>{"use strict";t.__esModule=!0,t.default=function(e,t){if(o.default.prototype.$isServer)return;if(!t)return void(e.scrollTop=0);var n=[],i=t.offsetParent;for(;i&&e!==i&&e.contains(i);)n.push(i),i=i.offsetParent;var r=t.offsetTop+n.reduce((function(e,t){return e+t.offsetTop}),0),s=r+t.offsetHeight,a=e.scrollTop,l=a+e.clientHeight;rl&&(e.scrollTop=s-e.clientHeight)};var i,r=n(70538),o=(i=r)&&i.__esModule?i:{default:i}},81301:(e,t,n)=>{"use strict";t.__esModule=!0,t.default=function(){if(o.default.prototype.$isServer)return 0;if(void 0!==s)return s;var e=document.createElement("div");e.className="el-scrollbar__wrap",e.style.visibility="hidden",e.style.width="100px",e.style.position="absolute",e.style.top="-9999px",document.body.appendChild(e);var t=e.offsetWidth;e.style.overflow="scroll";var n=document.createElement("div");n.style.width="100%",e.appendChild(n);var i=n.offsetWidth;return e.parentNode.removeChild(e),s=t-i};var i,r=n(70538),o=(i=r)&&i.__esModule?i:{default:i};var s=void 0},50167:(e,t)=>{"use strict";t.__esModule=!0,t.isDef=function(e){return null!=e},t.isKorean=function(e){return/([(\uAC00-\uD7AF)|(\u3130-\u318F)])+/gi.test(e)}},5389:(e,t,n)=>{"use strict";t.__esModule=!0,t.isDefined=t.isUndefined=t.isFunction=void 0;var i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};t.isString=function(e){return"[object String]"===Object.prototype.toString.call(e)},t.isObject=function(e){return"[object Object]"===Object.prototype.toString.call(e)},t.isHtmlElement=function(e){return e&&e.nodeType===Node.ELEMENT_NODE};var r,o=n(70538),s=(r=o)&&r.__esModule?r:{default:r};var a=function(e){return e&&"[object Function]"==={}.toString.call(e)};"object"===("undefined"==typeof Int8Array?"undefined":i(Int8Array))||!s.default.prototype.$isServer&&"function"==typeof document.childNodes||(t.isFunction=a=function(e){return"function"==typeof e||!1}),t.isFunction=a;t.isUndefined=function(e){return void 0===e},t.isDefined=function(e){return null!=e}},93104:(e,t,n)=>{"use strict";t.__esModule=!0,t.isMac=t.isEmpty=t.isEqual=t.arrayEquals=t.looseEqual=t.capitalize=t.kebabCase=t.autoprefixer=t.isFirefox=t.isEdge=t.isIE=t.coerceTruthyValueToArray=t.arrayFind=t.arrayFindIndex=t.escapeRegexpString=t.valueEquals=t.generateId=t.getValueByPath=void 0;var i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};t.noop=function(){},t.hasOwn=function(e,t){return l.call(e,t)},t.toObject=function(e){for(var t={},n=0;n0&&void 0!==arguments[0]?arguments[0]:"").replace(/[|\\{}()[\]^$+*?.]/g,"\\$&")};var u=t.arrayFindIndex=function(e,t){for(var n=0;n!==e.length;++n)if(t(e[n]))return n;return-1},d=(t.arrayFind=function(e,t){var n=u(e,t);return-1!==n?e[n]:void 0},t.coerceTruthyValueToArray=function(e){return Array.isArray(e)?e:e?[e]:[]},t.isIE=function(){return!s.default.prototype.$isServer&&!isNaN(Number(document.documentMode))},t.isEdge=function(){return!s.default.prototype.$isServer&&navigator.userAgent.indexOf("Edge")>-1},t.isFirefox=function(){return!s.default.prototype.$isServer&&!!window.navigator.userAgent.match(/firefox/i)},t.autoprefixer=function(e){if("object"!==(void 0===e?"undefined":i(e)))return e;var t=["ms-","webkit-"];return["transform","transition","animation"].forEach((function(n){var i=e[n];n&&i&&t.forEach((function(t){e[t+n]=i}))})),e},t.kebabCase=function(e){var t=/([^-])([A-Z])/g;return e.replace(t,"$1-$2").replace(t,"$1-$2").toLowerCase()},t.capitalize=function(e){return(0,a.isString)(e)?e.charAt(0).toUpperCase()+e.slice(1):e},t.looseEqual=function(e,t){var n=(0,a.isObject)(e),i=(0,a.isObject)(t);return n&&i?JSON.stringify(e)===JSON.stringify(t):!n&&!i&&String(e)===String(t)}),f=t.arrayEquals=function(e,t){if(t=t||[],(e=e||[]).length!==t.length)return!1;for(var n=0;n{"use strict";t.__esModule=!0;var i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};t.isVNode=function(e){return null!==e&&"object"===(void 0===e?"undefined":i(e))&&(0,r.hasOwn)(e,"componentOptions")};var r=n(93104)},70499:(e,t,n)=>{"use strict";t.__esModule=!0;var i,r=n(70538),o=(i=r)&&i.__esModule?i:{default:i},s=n(2680);var a=o.default.prototype.$isServer?function(){}:n(98335),l=function(e){return e.stopPropagation()};t.default={props:{transformOrigin:{type:[Boolean,String],default:!0},placement:{type:String,default:"bottom"},boundariesPadding:{type:Number,default:5},reference:{},popper:{},offset:{default:0},value:Boolean,visibleArrow:Boolean,arrowOffset:{type:Number,default:35},appendToBody:{type:Boolean,default:!0},popperOptions:{type:Object,default:function(){return{gpuAcceleration:!1}}}},data:function(){return{showPopper:!1,currentPlacement:""}},watch:{value:{immediate:!0,handler:function(e){this.showPopper=e,this.$emit("input",e)}},showPopper:function(e){this.disabled||(e?this.updatePopper():this.destroyPopper(),this.$emit("input",e))}},methods:{createPopper:function(){var e=this;if(!this.$isServer&&(this.currentPlacement=this.currentPlacement||this.placement,/^(top|bottom|left|right)(-start|-end)?$/g.test(this.currentPlacement))){var t=this.popperOptions,n=this.popperElm=this.popperElm||this.popper||this.$refs.popper,i=this.referenceElm=this.referenceElm||this.reference||this.$refs.reference;!i&&this.$slots.reference&&this.$slots.reference[0]&&(i=this.referenceElm=this.$slots.reference[0].elm),n&&i&&(this.visibleArrow&&this.appendArrow(n),this.appendToBody&&document.body.appendChild(this.popperElm),this.popperJS&&this.popperJS.destroy&&this.popperJS.destroy(),t.placement=this.currentPlacement,t.offset=this.offset,t.arrowOffset=this.arrowOffset,this.popperJS=new a(i,n,t),this.popperJS.onCreate((function(t){e.$emit("created",e),e.resetTransformOrigin(),e.$nextTick(e.updatePopper)})),"function"==typeof t.onUpdate&&this.popperJS.onUpdate(t.onUpdate),this.popperJS._popper.style.zIndex=s.PopupManager.nextZIndex(),this.popperElm.addEventListener("click",l))}},updatePopper:function(){var e=this.popperJS;e?(e.update(),e._popper&&(e._popper.style.zIndex=s.PopupManager.nextZIndex())):this.createPopper()},doDestroy:function(e){!this.popperJS||this.showPopper&&!e||(this.popperJS.destroy(),this.popperJS=null)},destroyPopper:function(){this.popperJS&&this.resetTransformOrigin()},resetTransformOrigin:function(){if(this.transformOrigin){var e=this.popperJS._popper.getAttribute("x-placement").split("-")[0],t={top:"bottom",bottom:"top",left:"right",right:"left"}[e];this.popperJS._popper.style.transformOrigin="string"==typeof this.transformOrigin?this.transformOrigin:["top","bottom"].indexOf(e)>-1?"center "+t:t+" center"}},appendArrow:function(e){var t=void 0;if(!this.appended){for(var n in this.appended=!0,e.attributes)if(/^_v-/.test(e.attributes[n].name)){t=e.attributes[n].name;break}var i=document.createElement("div");t&&i.setAttribute(t,""),i.setAttribute("x-arrow",""),i.className="popper__arrow",e.appendChild(i)}}},beforeDestroy:function(){this.doDestroy(!0),this.popperElm&&this.popperElm.parentNode===document.body&&(this.popperElm.removeEventListener("click",l),document.body.removeChild(this.popperElm))},deactivated:function(){this.$options.beforeDestroy[0].call(this)}}},18552:(e,t,n)=>{var i=n(10852)(n(55639),"DataView");e.exports=i},1989:(e,t,n)=>{var i=n(51789),r=n(80401),o=n(57667),s=n(21327),a=n(81866);function l(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t{var i=n(27040),r=n(14125),o=n(82117),s=n(67518),a=n(54705);function l(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t{var i=n(10852)(n(55639),"Map");e.exports=i},83369:(e,t,n)=>{var i=n(24785),r=n(11285),o=n(96e3),s=n(49916),a=n(95265);function l(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t{var i=n(10852)(n(55639),"Promise");e.exports=i},58525:(e,t,n)=>{var i=n(10852)(n(55639),"Set");e.exports=i},88668:(e,t,n)=>{var i=n(83369),r=n(90619),o=n(72385);function s(e){var t=-1,n=null==e?0:e.length;for(this.__data__=new i;++t{var i=n(38407),r=n(37465),o=n(63779),s=n(67599),a=n(44758),l=n(34309);function c(e){var t=this.__data__=new i(e);this.size=t.size}c.prototype.clear=r,c.prototype.delete=o,c.prototype.get=s,c.prototype.has=a,c.prototype.set=l,e.exports=c},62705:(e,t,n)=>{var i=n(55639).Symbol;e.exports=i},11149:(e,t,n)=>{var i=n(55639).Uint8Array;e.exports=i},70577:(e,t,n)=>{var i=n(10852)(n(55639),"WeakMap");e.exports=i},96874:e=>{e.exports=function(e,t,n){switch(n.length){case 0:return e.call(t);case 1:return e.call(t,n[0]);case 2:return e.call(t,n[0],n[1]);case 3:return e.call(t,n[0],n[1],n[2])}return e.apply(t,n)}},77412:e=>{e.exports=function(e,t){for(var n=-1,i=null==e?0:e.length;++n{e.exports=function(e,t){for(var n=-1,i=null==e?0:e.length,r=0,o=[];++n{var i=n(22545),r=n(35694),o=n(1469),s=n(44144),a=n(65776),l=n(36719),c=Object.prototype.hasOwnProperty;e.exports=function(e,t){var n=o(e),u=!n&&r(e),d=!n&&!u&&s(e),f=!n&&!u&&!d&&l(e),p=n||u||d||f,h=p?i(e.length,String):[],v=h.length;for(var m in e)!t&&!c.call(e,m)||p&&("length"==m||d&&("offset"==m||"parent"==m)||f&&("buffer"==m||"byteLength"==m||"byteOffset"==m)||a(m,v))||h.push(m);return h}},62488:e=>{e.exports=function(e,t){for(var n=-1,i=t.length,r=e.length;++n{e.exports=function(e,t){for(var n=-1,i=null==e?0:e.length;++n{var i=n(89465),r=n(77813);e.exports=function(e,t,n){(void 0!==n&&!r(e[t],n)||void 0===n&&!(t in e))&&i(e,t,n)}},34865:(e,t,n)=>{var i=n(89465),r=n(77813),o=Object.prototype.hasOwnProperty;e.exports=function(e,t,n){var s=e[t];o.call(e,t)&&r(s,n)&&(void 0!==n||t in e)||i(e,t,n)}},18470:(e,t,n)=>{var i=n(77813);e.exports=function(e,t){for(var n=e.length;n--;)if(i(e[n][0],t))return n;return-1}},89465:(e,t,n)=>{var i=n(38777);e.exports=function(e,t,n){"__proto__"==t&&i?i(e,t,{configurable:!0,enumerable:!0,value:n,writable:!0}):e[t]=n}},3118:(e,t,n)=>{var i=n(13218),r=Object.create,o=function(){function e(){}return function(t){if(!i(t))return{};if(r)return r(t);e.prototype=t;var n=new e;return e.prototype=void 0,n}}();e.exports=o},89881:(e,t,n)=>{var i=n(47816),r=n(99291)(i);e.exports=r},28483:(e,t,n)=>{var i=n(25063)();e.exports=i},47816:(e,t,n)=>{var i=n(28483),r=n(3674);e.exports=function(e,t){return e&&i(e,t,r)}},68866:(e,t,n)=>{var i=n(62488),r=n(1469);e.exports=function(e,t,n){var o=t(e);return r(e)?o:i(o,n(e))}},44239:(e,t,n)=>{var i=n(62705),r=n(89607),o=n(2333),s=i?i.toStringTag:void 0;e.exports=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":s&&s in Object(e)?r(e):o(e)}},9454:(e,t,n)=>{var i=n(44239),r=n(37005);e.exports=function(e){return r(e)&&"[object Arguments]"==i(e)}},90939:(e,t,n)=>{var i=n(2492),r=n(37005);e.exports=function e(t,n,o,s,a){return t===n||(null==t||null==n||!r(t)&&!r(n)?t!=t&&n!=n:i(t,n,o,s,e,a))}},2492:(e,t,n)=>{var i=n(46384),r=n(67114),o=n(18351),s=n(16096),a=n(64160),l=n(1469),c=n(44144),u=n(36719),d="[object Arguments]",f="[object Array]",p="[object Object]",h=Object.prototype.hasOwnProperty;e.exports=function(e,t,n,v,m,_){var g=l(e),b=l(t),y=g?f:a(e),x=b?f:a(t),w=(y=y==d?p:y)==p,C=(x=x==d?p:x)==p,S=y==x;if(S&&c(e)){if(!c(t))return!1;g=!0,w=!1}if(S&&!w)return _||(_=new i),g||u(e)?r(e,t,n,v,m,_):o(e,t,y,n,v,m,_);if(!(1&n)){var k=w&&h.call(e,"__wrapped__"),$=C&&h.call(t,"__wrapped__");if(k||$){var O=k?e.value():e,T=$?t.value():t;return _||(_=new i),m(O,T,n,v,_)}}return!!S&&(_||(_=new i),s(e,t,n,v,m,_))}},28458:(e,t,n)=>{var i=n(23560),r=n(15346),o=n(13218),s=n(80346),a=/^\[object .+?Constructor\]$/,l=Function.prototype,c=Object.prototype,u=l.toString,d=c.hasOwnProperty,f=RegExp("^"+u.call(d).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");e.exports=function(e){return!(!o(e)||r(e))&&(i(e)?f:a).test(s(e))}},38749:(e,t,n)=>{var i=n(44239),r=n(41780),o=n(37005),s={};s["[object Float32Array]"]=s["[object Float64Array]"]=s["[object Int8Array]"]=s["[object Int16Array]"]=s["[object Int32Array]"]=s["[object Uint8Array]"]=s["[object Uint8ClampedArray]"]=s["[object Uint16Array]"]=s["[object Uint32Array]"]=!0,s["[object Arguments]"]=s["[object Array]"]=s["[object ArrayBuffer]"]=s["[object Boolean]"]=s["[object DataView]"]=s["[object Date]"]=s["[object Error]"]=s["[object Function]"]=s["[object Map]"]=s["[object Number]"]=s["[object Object]"]=s["[object RegExp]"]=s["[object Set]"]=s["[object String]"]=s["[object WeakMap]"]=!1,e.exports=function(e){return o(e)&&r(e.length)&&!!s[i(e)]}},280:(e,t,n)=>{var i=n(25726),r=n(86916),o=Object.prototype.hasOwnProperty;e.exports=function(e){if(!i(e))return r(e);var t=[];for(var n in Object(e))o.call(e,n)&&"constructor"!=n&&t.push(n);return t}},10313:(e,t,n)=>{var i=n(13218),r=n(25726),o=n(33498),s=Object.prototype.hasOwnProperty;e.exports=function(e){if(!i(e))return o(e);var t=r(e),n=[];for(var a in e)("constructor"!=a||!t&&s.call(e,a))&&n.push(a);return n}},42980:(e,t,n)=>{var i=n(46384),r=n(86556),o=n(28483),s=n(59783),a=n(13218),l=n(81704),c=n(36390);e.exports=function e(t,n,u,d,f){t!==n&&o(n,(function(o,l){if(f||(f=new i),a(o))s(t,n,l,u,e,d,f);else{var p=d?d(c(t,l),o,l+"",t,n,f):void 0;void 0===p&&(p=o),r(t,l,p)}}),l)}},59783:(e,t,n)=>{var i=n(86556),r=n(64626),o=n(77133),s=n(278),a=n(38517),l=n(35694),c=n(1469),u=n(29246),d=n(44144),f=n(23560),p=n(13218),h=n(68630),v=n(36719),m=n(36390),_=n(59881);e.exports=function(e,t,n,g,b,y,x){var w=m(e,n),C=m(t,n),S=x.get(C);if(S)i(e,n,S);else{var k=y?y(w,C,n+"",e,t,x):void 0,$=void 0===k;if($){var O=c(C),T=!O&&d(C),E=!O&&!T&&v(C);k=C,O||T||E?c(w)?k=w:u(w)?k=s(w):T?($=!1,k=r(C,!0)):E?($=!1,k=o(C,!0)):k=[]:h(C)||l(C)?(k=w,l(w)?k=_(w):p(w)&&!f(w)||(k=a(C))):$=!1}$&&(x.set(C,k),b(k,C,g,y,x),x.delete(C)),i(e,n,k)}}},5976:(e,t,n)=>{var i=n(6557),r=n(45357),o=n(30061);e.exports=function(e,t){return o(r(e,t,i),e+"")}},56560:(e,t,n)=>{var i=n(75703),r=n(38777),o=n(6557),s=r?function(e,t){return r(e,"toString",{configurable:!0,enumerable:!1,value:i(t),writable:!0})}:o;e.exports=s},22545:e=>{e.exports=function(e,t){for(var n=-1,i=Array(e);++n{e.exports=function(e){return function(t){return e(t)}}},74757:e=>{e.exports=function(e,t){return e.has(t)}},54290:(e,t,n)=>{var i=n(6557);e.exports=function(e){return"function"==typeof e?e:i}},74318:(e,t,n)=>{var i=n(11149);e.exports=function(e){var t=new e.constructor(e.byteLength);return new i(t).set(new i(e)),t}},64626:(e,t,n)=>{e=n.nmd(e);var i=n(55639),r=t&&!t.nodeType&&t,o=r&&e&&!e.nodeType&&e,s=o&&o.exports===r?i.Buffer:void 0,a=s?s.allocUnsafe:void 0;e.exports=function(e,t){if(t)return e.slice();var n=e.length,i=a?a(n):new e.constructor(n);return e.copy(i),i}},77133:(e,t,n)=>{var i=n(74318);e.exports=function(e,t){var n=t?i(e.buffer):e.buffer;return new e.constructor(n,e.byteOffset,e.length)}},278:e=>{e.exports=function(e,t){var n=-1,i=e.length;for(t||(t=Array(i));++n{var i=n(34865),r=n(89465);e.exports=function(e,t,n,o){var s=!n;n||(n={});for(var a=-1,l=t.length;++a{var i=n(55639)["__core-js_shared__"];e.exports=i},21463:(e,t,n)=>{var i=n(5976),r=n(16612);e.exports=function(e){return i((function(t,n){var i=-1,o=n.length,s=o>1?n[o-1]:void 0,a=o>2?n[2]:void 0;for(s=e.length>3&&"function"==typeof s?(o--,s):void 0,a&&r(n[0],n[1],a)&&(s=o<3?void 0:s,o=1),t=Object(t);++i{var i=n(98612);e.exports=function(e,t){return function(n,r){if(null==n)return n;if(!i(n))return e(n,r);for(var o=n.length,s=t?o:-1,a=Object(n);(t?s--:++s{e.exports=function(e){return function(t,n,i){for(var r=-1,o=Object(t),s=i(t),a=s.length;a--;){var l=s[e?a:++r];if(!1===n(o[l],l,o))break}return t}}},38777:(e,t,n)=>{var i=n(10852),r=function(){try{var e=i(Object,"defineProperty");return e({},"",{}),e}catch(e){}}();e.exports=r},67114:(e,t,n)=>{var i=n(88668),r=n(82908),o=n(74757);e.exports=function(e,t,n,s,a,l){var c=1&n,u=e.length,d=t.length;if(u!=d&&!(c&&d>u))return!1;var f=l.get(e),p=l.get(t);if(f&&p)return f==t&&p==e;var h=-1,v=!0,m=2&n?new i:void 0;for(l.set(e,t),l.set(t,e);++h{var i=n(62705),r=n(11149),o=n(77813),s=n(67114),a=n(68776),l=n(21814),c=i?i.prototype:void 0,u=c?c.valueOf:void 0;e.exports=function(e,t,n,i,c,d,f){switch(n){case"[object DataView]":if(e.byteLength!=t.byteLength||e.byteOffset!=t.byteOffset)return!1;e=e.buffer,t=t.buffer;case"[object ArrayBuffer]":return!(e.byteLength!=t.byteLength||!d(new r(e),new r(t)));case"[object Boolean]":case"[object Date]":case"[object Number]":return o(+e,+t);case"[object Error]":return e.name==t.name&&e.message==t.message;case"[object RegExp]":case"[object String]":return e==t+"";case"[object Map]":var p=a;case"[object Set]":var h=1&i;if(p||(p=l),e.size!=t.size&&!h)return!1;var v=f.get(e);if(v)return v==t;i|=2,f.set(e,t);var m=s(p(e),p(t),i,c,d,f);return f.delete(e),m;case"[object Symbol]":if(u)return u.call(e)==u.call(t)}return!1}},16096:(e,t,n)=>{var i=n(58234),r=Object.prototype.hasOwnProperty;e.exports=function(e,t,n,o,s,a){var l=1&n,c=i(e),u=c.length;if(u!=i(t).length&&!l)return!1;for(var d=u;d--;){var f=c[d];if(!(l?f in t:r.call(t,f)))return!1}var p=a.get(e),h=a.get(t);if(p&&h)return p==t&&h==e;var v=!0;a.set(e,t),a.set(t,e);for(var m=l;++d{var i="object"==typeof n.g&&n.g&&n.g.Object===Object&&n.g;e.exports=i},58234:(e,t,n)=>{var i=n(68866),r=n(99551),o=n(3674);e.exports=function(e){return i(e,o,r)}},45050:(e,t,n)=>{var i=n(37019);e.exports=function(e,t){var n=e.__data__;return i(t)?n["string"==typeof t?"string":"hash"]:n.map}},10852:(e,t,n)=>{var i=n(28458),r=n(47801);e.exports=function(e,t){var n=r(e,t);return i(n)?n:void 0}},85924:(e,t,n)=>{var i=n(5569)(Object.getPrototypeOf,Object);e.exports=i},89607:(e,t,n)=>{var i=n(62705),r=Object.prototype,o=r.hasOwnProperty,s=r.toString,a=i?i.toStringTag:void 0;e.exports=function(e){var t=o.call(e,a),n=e[a];try{e[a]=void 0;var i=!0}catch(e){}var r=s.call(e);return i&&(t?e[a]=n:delete e[a]),r}},99551:(e,t,n)=>{var i=n(34963),r=n(70479),o=Object.prototype.propertyIsEnumerable,s=Object.getOwnPropertySymbols,a=s?function(e){return null==e?[]:(e=Object(e),i(s(e),(function(t){return o.call(e,t)})))}:r;e.exports=a},64160:(e,t,n)=>{var i=n(18552),r=n(57071),o=n(53818),s=n(58525),a=n(70577),l=n(44239),c=n(80346),u="[object Map]",d="[object Promise]",f="[object Set]",p="[object WeakMap]",h="[object DataView]",v=c(i),m=c(r),_=c(o),g=c(s),b=c(a),y=l;(i&&y(new i(new ArrayBuffer(1)))!=h||r&&y(new r)!=u||o&&y(o.resolve())!=d||s&&y(new s)!=f||a&&y(new a)!=p)&&(y=function(e){var t=l(e),n="[object Object]"==t?e.constructor:void 0,i=n?c(n):"";if(i)switch(i){case v:return h;case m:return u;case _:return d;case g:return f;case b:return p}return t}),e.exports=y},47801:e=>{e.exports=function(e,t){return null==e?void 0:e[t]}},51789:(e,t,n)=>{var i=n(94536);e.exports=function(){this.__data__=i?i(null):{},this.size=0}},80401:e=>{e.exports=function(e){var t=this.has(e)&&delete this.__data__[e];return this.size-=t?1:0,t}},57667:(e,t,n)=>{var i=n(94536),r=Object.prototype.hasOwnProperty;e.exports=function(e){var t=this.__data__;if(i){var n=t[e];return"__lodash_hash_undefined__"===n?void 0:n}return r.call(t,e)?t[e]:void 0}},21327:(e,t,n)=>{var i=n(94536),r=Object.prototype.hasOwnProperty;e.exports=function(e){var t=this.__data__;return i?void 0!==t[e]:r.call(t,e)}},81866:(e,t,n)=>{var i=n(94536);e.exports=function(e,t){var n=this.__data__;return this.size+=this.has(e)?0:1,n[e]=i&&void 0===t?"__lodash_hash_undefined__":t,this}},38517:(e,t,n)=>{var i=n(3118),r=n(85924),o=n(25726);e.exports=function(e){return"function"!=typeof e.constructor||o(e)?{}:i(r(e))}},65776:e=>{var t=/^(?:0|[1-9]\d*)$/;e.exports=function(e,n){var i=typeof e;return!!(n=null==n?9007199254740991:n)&&("number"==i||"symbol"!=i&&t.test(e))&&e>-1&&e%1==0&&e{var i=n(77813),r=n(98612),o=n(65776),s=n(13218);e.exports=function(e,t,n){if(!s(n))return!1;var a=typeof t;return!!("number"==a?r(n)&&o(t,n.length):"string"==a&&t in n)&&i(n[t],e)}},37019:e=>{e.exports=function(e){var t=typeof e;return"string"==t||"number"==t||"symbol"==t||"boolean"==t?"__proto__"!==e:null===e}},15346:(e,t,n)=>{var i,r=n(14429),o=(i=/[^.]+$/.exec(r&&r.keys&&r.keys.IE_PROTO||""))?"Symbol(src)_1."+i:"";e.exports=function(e){return!!o&&o in e}},25726:e=>{var t=Object.prototype;e.exports=function(e){var n=e&&e.constructor;return e===("function"==typeof n&&n.prototype||t)}},27040:e=>{e.exports=function(){this.__data__=[],this.size=0}},14125:(e,t,n)=>{var i=n(18470),r=Array.prototype.splice;e.exports=function(e){var t=this.__data__,n=i(t,e);return!(n<0)&&(n==t.length-1?t.pop():r.call(t,n,1),--this.size,!0)}},82117:(e,t,n)=>{var i=n(18470);e.exports=function(e){var t=this.__data__,n=i(t,e);return n<0?void 0:t[n][1]}},67518:(e,t,n)=>{var i=n(18470);e.exports=function(e){return i(this.__data__,e)>-1}},54705:(e,t,n)=>{var i=n(18470);e.exports=function(e,t){var n=this.__data__,r=i(n,e);return r<0?(++this.size,n.push([e,t])):n[r][1]=t,this}},24785:(e,t,n)=>{var i=n(1989),r=n(38407),o=n(57071);e.exports=function(){this.size=0,this.__data__={hash:new i,map:new(o||r),string:new i}}},11285:(e,t,n)=>{var i=n(45050);e.exports=function(e){var t=i(this,e).delete(e);return this.size-=t?1:0,t}},96e3:(e,t,n)=>{var i=n(45050);e.exports=function(e){return i(this,e).get(e)}},49916:(e,t,n)=>{var i=n(45050);e.exports=function(e){return i(this,e).has(e)}},95265:(e,t,n)=>{var i=n(45050);e.exports=function(e,t){var n=i(this,e),r=n.size;return n.set(e,t),this.size+=n.size==r?0:1,this}},68776:e=>{e.exports=function(e){var t=-1,n=Array(e.size);return e.forEach((function(e,i){n[++t]=[i,e]})),n}},94536:(e,t,n)=>{var i=n(10852)(Object,"create");e.exports=i},86916:(e,t,n)=>{var i=n(5569)(Object.keys,Object);e.exports=i},33498:e=>{e.exports=function(e){var t=[];if(null!=e)for(var n in Object(e))t.push(n);return t}},31167:(e,t,n)=>{e=n.nmd(e);var i=n(31957),r=t&&!t.nodeType&&t,o=r&&e&&!e.nodeType&&e,s=o&&o.exports===r&&i.process,a=function(){try{var e=o&&o.require&&o.require("util").types;return e||s&&s.binding&&s.binding("util")}catch(e){}}();e.exports=a},2333:e=>{var t=Object.prototype.toString;e.exports=function(e){return t.call(e)}},5569:e=>{e.exports=function(e,t){return function(n){return e(t(n))}}},45357:(e,t,n)=>{var i=n(96874),r=Math.max;e.exports=function(e,t,n){return t=r(void 0===t?e.length-1:t,0),function(){for(var o=arguments,s=-1,a=r(o.length-t,0),l=Array(a);++s{var i=n(31957),r="object"==typeof self&&self&&self.Object===Object&&self,o=i||r||Function("return this")();e.exports=o},36390:e=>{e.exports=function(e,t){if(("constructor"!==t||"function"!=typeof e[t])&&"__proto__"!=t)return e[t]}},90619:e=>{e.exports=function(e){return this.__data__.set(e,"__lodash_hash_undefined__"),this}},72385:e=>{e.exports=function(e){return this.__data__.has(e)}},21814:e=>{e.exports=function(e){var t=-1,n=Array(e.size);return e.forEach((function(e){n[++t]=e})),n}},30061:(e,t,n)=>{var i=n(56560),r=n(21275)(i);e.exports=r},21275:e=>{var t=Date.now;e.exports=function(e){var n=0,i=0;return function(){var r=t(),o=16-(r-i);if(i=r,o>0){if(++n>=800)return arguments[0]}else n=0;return e.apply(void 0,arguments)}}},37465:(e,t,n)=>{var i=n(38407);e.exports=function(){this.__data__=new i,this.size=0}},63779:e=>{e.exports=function(e){var t=this.__data__,n=t.delete(e);return this.size=t.size,n}},67599:e=>{e.exports=function(e){return this.__data__.get(e)}},44758:e=>{e.exports=function(e){return this.__data__.has(e)}},34309:(e,t,n)=>{var i=n(38407),r=n(57071),o=n(83369);e.exports=function(e,t){var n=this.__data__;if(n instanceof i){var s=n.__data__;if(!r||s.length<199)return s.push([e,t]),this.size=++n.size,this;n=this.__data__=new o(s)}return n.set(e,t),this.size=n.size,this}},80346:e=>{var t=Function.prototype.toString;e.exports=function(e){if(null!=e){try{return t.call(e)}catch(e){}try{return e+""}catch(e){}}return""}},75703:e=>{e.exports=function(e){return function(){return e}}},66073:(e,t,n)=>{e.exports=n(84486)},77813:e=>{e.exports=function(e,t){return e===t||e!=e&&t!=t}},84486:(e,t,n)=>{var i=n(77412),r=n(89881),o=n(54290),s=n(1469);e.exports=function(e,t){return(s(e)?i:r)(e,o(t))}},6557:e=>{e.exports=function(e){return e}},35694:(e,t,n)=>{var i=n(9454),r=n(37005),o=Object.prototype,s=o.hasOwnProperty,a=o.propertyIsEnumerable,l=i(function(){return arguments}())?i:function(e){return r(e)&&s.call(e,"callee")&&!a.call(e,"callee")};e.exports=l},1469:e=>{var t=Array.isArray;e.exports=t},98612:(e,t,n)=>{var i=n(23560),r=n(41780);e.exports=function(e){return null!=e&&r(e.length)&&!i(e)}},29246:(e,t,n)=>{var i=n(98612),r=n(37005);e.exports=function(e){return r(e)&&i(e)}},44144:(e,t,n)=>{e=n.nmd(e);var i=n(55639),r=n(95062),o=t&&!t.nodeType&&t,s=o&&e&&!e.nodeType&&e,a=s&&s.exports===o?i.Buffer:void 0,l=(a?a.isBuffer:void 0)||r;e.exports=l},18446:(e,t,n)=>{var i=n(90939);e.exports=function(e,t){return i(e,t)}},23560:(e,t,n)=>{var i=n(44239),r=n(13218);e.exports=function(e){if(!r(e))return!1;var t=i(e);return"[object Function]"==t||"[object GeneratorFunction]"==t||"[object AsyncFunction]"==t||"[object Proxy]"==t}},41780:e=>{e.exports=function(e){return"number"==typeof e&&e>-1&&e%1==0&&e<=9007199254740991}},13218:e=>{e.exports=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}},37005:e=>{e.exports=function(e){return null!=e&&"object"==typeof e}},68630:(e,t,n)=>{var i=n(44239),r=n(85924),o=n(37005),s=Function.prototype,a=Object.prototype,l=s.toString,c=a.hasOwnProperty,u=l.call(Object);e.exports=function(e){if(!o(e)||"[object Object]"!=i(e))return!1;var t=r(e);if(null===t)return!0;var n=c.call(t,"constructor")&&t.constructor;return"function"==typeof n&&n instanceof n&&l.call(n)==u}},36719:(e,t,n)=>{var i=n(38749),r=n(7518),o=n(31167),s=o&&o.isTypedArray,a=s?r(s):i;e.exports=a},3674:(e,t,n)=>{var i=n(14636),r=n(280),o=n(98612);e.exports=function(e){return o(e)?i(e):r(e)}},81704:(e,t,n)=>{var i=n(14636),r=n(10313),o=n(98612);e.exports=function(e){return o(e)?i(e,!0):r(e)}},82492:(e,t,n)=>{var i=n(42980),r=n(21463)((function(e,t,n){i(e,t,n)}));e.exports=r},70479:e=>{e.exports=function(){return[]}},95062:e=>{e.exports=function(){return!1}},59881:(e,t,n)=>{var i=n(98363),r=n(81704);e.exports=function(e){return i(e,r(e))}},59109:()=>{},52181:()=>{},39904:()=>{},95454:()=>{},66077:()=>{},75644:()=>{},14538:()=>{},91033:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>S});var i=function(){if("undefined"!=typeof Map)return Map;function e(e,t){var n=-1;return e.some((function(e,i){return e[0]===t&&(n=i,!0)})),n}return function(){function t(){this.__entries__=[]}return Object.defineProperty(t.prototype,"size",{get:function(){return this.__entries__.length},enumerable:!0,configurable:!0}),t.prototype.get=function(t){var n=e(this.__entries__,t),i=this.__entries__[n];return i&&i[1]},t.prototype.set=function(t,n){var i=e(this.__entries__,t);~i?this.__entries__[i][1]=n:this.__entries__.push([t,n])},t.prototype.delete=function(t){var n=this.__entries__,i=e(n,t);~i&&n.splice(i,1)},t.prototype.has=function(t){return!!~e(this.__entries__,t)},t.prototype.clear=function(){this.__entries__.splice(0)},t.prototype.forEach=function(e,t){void 0===t&&(t=null);for(var n=0,i=this.__entries__;n0},e.prototype.connect_=function(){r&&!this.connected_&&(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),l?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener("DOMSubtreeModified",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},e.prototype.disconnect_=function(){r&&this.connected_&&(document.removeEventListener("transitionend",this.onTransitionEnd_),window.removeEventListener("resize",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener("DOMSubtreeModified",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},e.prototype.onTransitionEnd_=function(e){var t=e.propertyName,n=void 0===t?"":t;a.some((function(e){return!!~n.indexOf(e)}))&&this.refresh()},e.getInstance=function(){return this.instance_||(this.instance_=new e),this.instance_},e.instance_=null,e}(),u=function(e,t){for(var n=0,i=Object.keys(t);n0},e}(),w="undefined"!=typeof WeakMap?new WeakMap:new i,C=function e(t){if(!(this instanceof e))throw new TypeError("Cannot call a class as a function.");if(!arguments.length)throw new TypeError("1 argument required, but only 0 present.");var n=c.getInstance(),i=new x(t,n,this);w.set(this,i)};["observe","unobserve","disconnect"].forEach((function(e){C.prototype[e]=function(){var t;return(t=w.get(this))[e].apply(t,arguments)}}));const S=void 0!==o.ResizeObserver?o.ResizeObserver:C},42823:(e,t,n)=>{var i=n(68563);e.exports=function(e,t,n){return void 0===n?i(e,t,!1):i(e,n,!1!==t)}},44592:(e,t,n)=>{var i=n(68563),r=n(42823);e.exports={throttle:i,debounce:r}},68563:e=>{e.exports=function(e,t,n,i){var r,o=0;return"boolean"!=typeof t&&(i=n,n=t,t=void 0),function(){var s=this,a=Number(new Date)-o,l=arguments;function c(){o=Number(new Date),n.apply(s,l)}i&&!r&&c(),r&&clearTimeout(r),void 0===i&&a>e?c():!0!==t&&(r=setTimeout(i?function(){r=void 0}:c,void 0===i?e-a:e))}}},70538:(e,t,n)=>{"use strict";n.r(t),n.d(t,{EffectScope:()=>zn,computed:()=>ft,customRef:()=>it,default:()=>ur,defineAsyncComponent:()=>ci,defineComponent:()=>ki,del:()=>De,effectScope:()=>Fn,getCurrentInstance:()=>pe,getCurrentScope:()=>Vn,h:()=>Wn,inject:()=>qn,isProxy:()=>qe,isReactive:()=>Be,isReadonly:()=>Ue,isRef:()=>Ze,isShallow:()=>He,markRaw:()=>Ge,mergeDefaults:()=>en,nextTick:()=>si,onActivated:()=>_i,onBeforeMount:()=>di,onBeforeUnmount:()=>vi,onBeforeUpdate:()=>pi,onDeactivated:()=>gi,onErrorCaptured:()=>Ci,onMounted:()=>fi,onRenderTracked:()=>yi,onRenderTriggered:()=>xi,onScopeDispose:()=>Bn,onServerPrefetch:()=>bi,onUnmounted:()=>mi,onUpdated:()=>hi,provide:()=>Hn,proxyRefs:()=>tt,reactive:()=>ze,readonly:()=>lt,ref:()=>Ke,set:()=>Le,shallowReactive:()=>Fe,shallowReadonly:()=>dt,shallowRef:()=>Je,toRaw:()=>We,toRef:()=>ot,toRefs:()=>rt,triggerRef:()=>Qe,unref:()=>et,useAttrs:()=>Jt,useCssModule:()=>ai,useCssVars:()=>li,useListeners:()=>Yt,useSlots:()=>Kt,version:()=>Si,watch:()=>Dn,watchEffect:()=>Pn,watchPostEffect:()=>Mn,watchSyncEffect:()=>An});var i=Object.freeze({}),r=Array.isArray;function o(e){return null==e}function s(e){return null!=e}function a(e){return!0===e}function l(e){return"string"==typeof e||"number"==typeof e||"symbol"==typeof e||"boolean"==typeof e}function c(e){return"function"==typeof e}function u(e){return null!==e&&"object"==typeof e}var d=Object.prototype.toString;function f(e){return"[object Object]"===d.call(e)}function p(e){return"[object RegExp]"===d.call(e)}function h(e){var t=parseFloat(String(e));return t>=0&&Math.floor(t)===t&&isFinite(e)}function v(e){return s(e)&&"function"==typeof e.then&&"function"==typeof e.catch}function m(e){return null==e?"":Array.isArray(e)||f(e)&&e.toString===d?JSON.stringify(e,null,2):String(e)}function _(e){var t=parseFloat(e);return isNaN(t)?e:t}function g(e,t){for(var n=Object.create(null),i=e.split(","),r=0;r-1)return e.splice(i,1)}}var w=Object.prototype.hasOwnProperty;function C(e,t){return w.call(e,t)}function S(e){var t=Object.create(null);return function(n){return t[n]||(t[n]=e(n))}}var k=/-(\w)/g,$=S((function(e){return e.replace(k,(function(e,t){return t?t.toUpperCase():""}))})),O=S((function(e){return e.charAt(0).toUpperCase()+e.slice(1)})),T=/\B([A-Z])/g,E=S((function(e){return e.replace(T,"-$1").toLowerCase()}));var j=Function.prototype.bind?function(e,t){return e.bind(t)}:function(e,t){function n(n){var i=arguments.length;return i?i>1?e.apply(t,arguments):e.call(t,n):e.call(t)}return n._length=e.length,n};function I(e,t){t=t||0;for(var n=e.length-t,i=new Array(n);n--;)i[n]=e[n+t];return i}function P(e,t){for(var n in t)e[n]=t[n];return e}function M(e){for(var t={},n=0;n0,ee=J&&J.indexOf("edge/")>0;J&&J.indexOf("android");var te=J&&/iphone|ipad|ipod|ios/.test(J);J&&/chrome\/\d+/.test(J),J&&/phantomjs/.test(J);var ne,ie=J&&J.match(/firefox\/(\d+)/),re={}.watch,oe=!1;if(K)try{var se={};Object.defineProperty(se,"passive",{get:function(){oe=!0}}),window.addEventListener("test-passive",null,se)}catch(e){}var ae=function(){return void 0===ne&&(ne=!K&&void 0!==n.g&&(n.g.process&&"server"===n.g.process.env.VUE_ENV)),ne},le=K&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__;function ce(e){return"function"==typeof e&&/native code/.test(e.toString())}var ue,de="undefined"!=typeof Symbol&&ce(Symbol)&&"undefined"!=typeof Reflect&&ce(Reflect.ownKeys);ue="undefined"!=typeof Set&&ce(Set)?Set:function(){function e(){this.set=Object.create(null)}return e.prototype.has=function(e){return!0===this.set[e]},e.prototype.add=function(e){this.set[e]=!0},e.prototype.clear=function(){this.set=Object.create(null)},e}();var fe=null;function pe(){return fe&&{proxy:fe}}function he(e){void 0===e&&(e=null),e||fe&&fe._scope.off(),fe=e,e&&e._scope.on()}var ve=function(){function e(e,t,n,i,r,o,s,a){this.tag=e,this.data=t,this.children=n,this.text=i,this.elm=r,this.ns=void 0,this.context=o,this.fnContext=void 0,this.fnOptions=void 0,this.fnScopeId=void 0,this.key=t&&t.key,this.componentOptions=s,this.componentInstance=void 0,this.parent=void 0,this.raw=!1,this.isStatic=!1,this.isRootInsert=!0,this.isComment=!1,this.isCloned=!1,this.isOnce=!1,this.asyncFactory=a,this.asyncMeta=void 0,this.isAsyncPlaceholder=!1}return Object.defineProperty(e.prototype,"child",{get:function(){return this.componentInstance},enumerable:!1,configurable:!0}),e}(),me=function(e){void 0===e&&(e="");var t=new ve;return t.text=e,t.isComment=!0,t};function _e(e){return new ve(void 0,void 0,void 0,String(e))}function ge(e){var t=new ve(e.tag,e.data,e.children&&e.children.slice(),e.text,e.elm,e.context,e.componentOptions,e.asyncFactory);return t.ns=e.ns,t.isStatic=e.isStatic,t.key=e.key,t.isComment=e.isComment,t.fnContext=e.fnContext,t.fnOptions=e.fnOptions,t.fnScopeId=e.fnScopeId,t.asyncMeta=e.asyncMeta,t.isCloned=!0,t}var be=0,ye=[],xe=function(){for(var e=0;e0&&(bt((i=yt(i,"".concat(t||"","_").concat(n)))[0])&&bt(u)&&(d[c]=_e(u.text+i[0].text),i.shift()),d.push.apply(d,i)):l(i)?bt(u)?d[c]=_e(u.text+i):""!==i&&d.push(_e(i)):bt(i)&&bt(u)?d[c]=_e(u.text+i.text):(a(e._isVList)&&s(i.tag)&&o(i.key)&&s(t)&&(i.key="__vlist".concat(t,"_").concat(n,"__")),d.push(i)));return d}var xt=1,wt=2;function Ct(e,t,n,i,o,d){return(r(n)||l(n))&&(o=i,i=n,n=void 0),a(d)&&(o=wt),function(e,t,n,i,o){if(s(n)&&s(n.__ob__))return me();s(n)&&s(n.is)&&(t=n.is);if(!t)return me();0;r(i)&&c(i[0])&&((n=n||{}).scopedSlots={default:i[0]},i.length=0);o===wt?i=gt(i):o===xt&&(i=function(e){for(var t=0;t0,a=t?!!t.$stable:!s,l=t&&t.$key;if(t){if(t._normalized)return t._normalized;if(a&&r&&r!==i&&l===r.$key&&!s&&!r.$hasNormal)return r;for(var c in o={},t)t[c]&&"$"!==c[0]&&(o[c]=Ut(e,n,c,t[c]))}else o={};for(var u in n)u in o||(o[u]=qt(n,u));return t&&Object.isExtensible(t)&&(t._normalized=o),G(o,"$stable",a),G(o,"$key",l),G(o,"$hasNormal",s),o}function Ut(e,t,n,i){var o=function(){var t=fe;he(e);var n=arguments.length?i.apply(null,arguments):i({}),o=(n=n&&"object"==typeof n&&!r(n)?[n]:gt(n))&&n[0];return he(t),n&&(!o||1===n.length&&o.isComment&&!Bt(o))?void 0:n};return i.proxy&&Object.defineProperty(t,n,{get:o,enumerable:!0,configurable:!0}),o}function qt(e,t){return function(){return e[t]}}function Wt(e){return{get attrs(){if(!e._attrsProxy){var t=e._attrsProxy={};G(t,"_v_attr_proxy",!0),Gt(t,e.$attrs,i,e,"$attrs")}return e._attrsProxy},get listeners(){e._listenersProxy||Gt(e._listenersProxy={},e.$listeners,i,e,"$listeners");return e._listenersProxy},get slots(){return function(e){e._slotsProxy||Zt(e._slotsProxy={},e.$scopedSlots);return e._slotsProxy}(e)},emit:j(e.$emit,e),expose:function(t){t&&Object.keys(t).forEach((function(n){return nt(e,t,n)}))}}}function Gt(e,t,n,i,r){var o=!1;for(var s in t)s in e?t[s]!==n[s]&&(o=!0):(o=!0,Xt(e,s,i,r));for(var s in e)s in t||(o=!0,delete e[s]);return o}function Xt(e,t,n,i){Object.defineProperty(e,t,{enumerable:!0,configurable:!0,get:function(){return n[i][t]}})}function Zt(e,t){for(var n in t)e[n]=t[n];for(var n in e)n in t||delete e[n]}function Kt(){return Qt().slots}function Jt(){return Qt().attrs}function Yt(){return Qt().listeners}function Qt(){var e=fe;return e._setupContext||(e._setupContext=Wt(e))}function en(e,t){var n=r(e)?e.reduce((function(e,t){return e[t]={},e}),{}):e;for(var i in t){var o=n[i];o?r(o)||c(o)?n[i]={type:o,default:t[i]}:o.default=t[i]:null===o&&(n[i]={default:t[i]})}return n}var tn,nn=null;function rn(e,t){return(e.__esModule||de&&"Module"===e[Symbol.toStringTag])&&(e=e.default),u(e)?t.extend(e):e}function on(e){if(r(e))for(var t=0;tdocument.createEvent("Event").timeStamp&&(Cn=function(){return Sn.now()})}var kn=function(e,t){if(e.post){if(!t.post)return 1}else if(t.post)return-1;return e.id-t.id};function $n(){var e,t;for(wn=Cn(),yn=!0,mn.sort(kn),xn=0;xnxn&&mn[n].id>e.id;)n--;mn.splice(n+1,0,e)}else mn.push(e);bn||(bn=!0,si($n))}}var Tn="watcher",En="".concat(Tn," callback"),jn="".concat(Tn," getter"),In="".concat(Tn," cleanup");function Pn(e,t){return Rn(e,null,t)}function Mn(e,t){return Rn(e,null,{flush:"post"})}function An(e,t){return Rn(e,null,{flush:"sync"})}var Nn,Ln={};function Dn(e,t,n){return Rn(e,t,n)}function Rn(e,t,n){var o=void 0===n?i:n,s=o.immediate,a=o.deep,l=o.flush,u=void 0===l?"pre":l;o.onTrack,o.onTrigger;var d,f,p=fe,h=function(e,t,n){return void 0===n&&(n=null),Xn(e,null,n,p,t)},v=!1,m=!1;if(Ze(e)?(d=function(){return e.value},v=He(e)):Be(e)?(d=function(){return e.__ob__.dep.depend(),e},a=!0):r(e)?(m=!0,v=e.some((function(e){return Be(e)||He(e)})),d=function(){return e.map((function(e){return Ze(e)?e.value:Be(e)?Oi(e):c(e)?h(e,jn):void 0}))}):d=c(e)?t?function(){return h(e,jn)}:function(){if(!p||!p._isDestroyed)return f&&f(),h(e,Tn,[g])}:A,t&&a){var _=d;d=function(){return Oi(_())}}var g=function(e){f=b.onStop=function(){h(e,In)}};if(ae())return g=A,t?s&&h(t,En,[d(),m?[]:void 0,g]):d(),A;var b=new ji(fe,d,A,{lazy:!0});b.noRecurse=!t;var y=m?[]:Ln;return b.run=function(){if(b.active)if(t){var e=b.get();(a||v||(m?e.some((function(e,t){return F(e,y[t])})):F(e,y)))&&(f&&f(),h(t,En,[e,y===Ln?void 0:y,g]),y=e)}else b.get()},"sync"===u?b.update=b.run:"post"===u?(b.post=!0,b.update=function(){return On(b)}):b.update=function(){if(p&&p===fe&&!p._isMounted){var e=p._preWatchers||(p._preWatchers=[]);e.indexOf(b)<0&&e.push(b)}else On(b)},t?s?b.run():y=b.get():"post"===u&&p?p.$once("hook:mounted",(function(){return b.get()})):b.get(),function(){b.teardown()}}var zn=function(){function e(e){void 0===e&&(e=!1),this.detached=e,this.active=!0,this.effects=[],this.cleanups=[],this.parent=Nn,!e&&Nn&&(this.index=(Nn.scopes||(Nn.scopes=[])).push(this)-1)}return e.prototype.run=function(e){if(this.active){var t=Nn;try{return Nn=this,e()}finally{Nn=t}}else 0},e.prototype.on=function(){Nn=this},e.prototype.off=function(){Nn=this.parent},e.prototype.stop=function(e){if(this.active){var t=void 0,n=void 0;for(t=0,n=this.effects.length;t1)return n&&c(t)?t.call(i):t}else 0}function Wn(e,t,n){return Ct(fe,e,t,n,2,!0)}function Gn(e,t,n){Se();try{if(t)for(var i=t;i=i.$parent;){var r=i.$options.errorCaptured;if(r)for(var o=0;o-1)if(o&&!C(r,"default"))s=!1;else if(""===s||s===E(e)){var l=cr(String,r.type);(l<0||a-1:"string"==typeof e?e.split(",").indexOf(t)>-1:!!p(e)&&e.test(t)}function hr(e,t){var n=e.cache,i=e.keys,r=e._vnode;for(var o in n){var s=n[o];if(s){var a=s.name;a&&!t(a)&&vr(n,o,i,r)}}}function vr(e,t,n,i){var r=e[t];!r||i&&r.tag===i.tag||r.componentInstance.$destroy(),e[t]=null,x(n,t)}!function(e){e.prototype._init=function(e){var t=this;t._uid=Fi++,t._isVue=!0,t.__v_skip=!0,t._scope=new zn(!0),t._scope._vm=!0,e&&e._isComponent?function(e,t){var n=e.$options=Object.create(e.constructor.options),i=t._parentVnode;n.parent=t.parent,n._parentVnode=i;var r=i.componentOptions;n.propsData=r.propsData,n._parentListeners=r.listeners,n._renderChildren=r.children,n._componentTag=r.tag,t.render&&(n.render=t.render,n.staticRenderFns=t.staticRenderFns)}(t,e):t.$options=ir(Vi(t.constructor),e||{},t),t._renderProxy=t,t._self=t,function(e){var t=e.$options,n=t.parent;if(n&&!t.abstract){for(;n.$options.abstract&&n.$parent;)n=n.$parent;n.$children.push(e)}e.$parent=n,e.$root=n?n.$root:e,e.$children=[],e.$refs={},e._provided=n?n._provided:Object.create(null),e._watcher=null,e._inactive=null,e._directInactive=!1,e._isMounted=!1,e._isDestroyed=!1,e._isBeingDestroyed=!1}(t),function(e){e._events=Object.create(null),e._hasHookEvent=!1;var t=e.$options._parentListeners;t&&cn(e,t)}(t),function(e){e._vnode=null,e._staticTrees=null;var t=e.$options,n=e.$vnode=t._parentVnode,r=n&&n.context;e.$slots=Ft(t._renderChildren,r),e.$scopedSlots=n?Ht(e.$parent,n.data.scopedSlots,e.$slots):i,e._c=function(t,n,i,r){return Ct(e,t,n,i,r,!1)},e.$createElement=function(t,n,i,r){return Ct(e,t,n,i,r,!0)};var o=n&&n.data;Ne(e,"$attrs",o&&o.attrs||i,null,!0),Ne(e,"$listeners",t._parentListeners||i,null,!0)}(t),vn(t,"beforeCreate",void 0,!1),function(e){var t=zi(e.$options.inject,e);t&&(Ie(!1),Object.keys(t).forEach((function(n){Ne(e,n,t[n])})),Ie(!0))}(t),Mi(t),function(e){var t=e.$options.provide;if(t){var n=c(t)?t.call(e):t;if(!u(n))return;for(var i=Un(e),r=de?Reflect.ownKeys(n):Object.keys(n),o=0;o1?I(n):n;for(var i=I(arguments,1),r='event handler for "'.concat(e,'"'),o=0,s=n.length;oparseInt(this.max)&&vr(t,n[0],n,this._vnode),this.vnodeToCache=null}}},created:function(){this.cache=Object.create(null),this.keys=[]},destroyed:function(){for(var e in this.cache)vr(this.cache,e,this.keys)},mounted:function(){var e=this;this.cacheVNode(),this.$watch("include",(function(t){hr(e,(function(e){return pr(t,e)}))})),this.$watch("exclude",(function(t){hr(e,(function(e){return!pr(t,e)}))}))},updated:function(){this.cacheVNode()},render:function(){var e=this.$slots.default,t=on(e),n=t&&t.componentOptions;if(n){var i=fr(n),r=this.include,o=this.exclude;if(r&&(!i||!pr(r,i))||o&&i&&pr(o,i))return t;var s=this.cache,a=this.keys,l=null==t.key?n.Ctor.cid+(n.tag?"::".concat(n.tag):""):t.key;s[l]?(t.componentInstance=s[l].componentInstance,x(a,l),a.push(l)):(this.vnodeToCache=t,this.keyToCache=l),t.data.keepAlive=!0}return t||e&&e[0]}},gr={KeepAlive:_r};!function(e){var t={get:function(){return U}};Object.defineProperty(e,"config",t),e.util={warn:Ki,extend:P,mergeOptions:ir,defineReactive:Ne},e.set=Le,e.delete=De,e.nextTick=si,e.observable=function(e){return Ae(e),e},e.options=Object.create(null),B.forEach((function(t){e.options[t+"s"]=Object.create(null)})),e.options._base=e,P(e.options.components,gr),function(e){e.use=function(e){var t=this._installedPlugins||(this._installedPlugins=[]);if(t.indexOf(e)>-1)return this;var n=I(arguments,1);return n.unshift(this),c(e.install)?e.install.apply(e,n):c(e)&&e.apply(null,n),t.push(e),this}}(e),function(e){e.mixin=function(e){return this.options=ir(this.options,e),this}}(e),dr(e),function(e){B.forEach((function(t){e[t]=function(e,n){return n?("component"===t&&f(n)&&(n.name=n.name||e,n=this.options._base.extend(n)),"directive"===t&&c(n)&&(n={bind:n,update:n}),this.options[t+"s"][e]=n,n):this.options[t+"s"][e]}}))}(e)}(ur),Object.defineProperty(ur.prototype,"$isServer",{get:ae}),Object.defineProperty(ur.prototype,"$ssrContext",{get:function(){return this.$vnode&&this.$vnode.ssrContext}}),Object.defineProperty(ur,"FunctionalRenderContext",{value:Bi}),ur.version=Si;var br=g("style,class"),yr=g("input,textarea,option,select,progress"),xr=function(e,t,n){return"value"===n&&yr(e)&&"button"!==t||"selected"===n&&"option"===e||"checked"===n&&"input"===e||"muted"===n&&"video"===e},wr=g("contenteditable,draggable,spellcheck"),Cr=g("events,caret,typing,plaintext-only"),Sr=function(e,t){return Er(t)||"false"===t?"false":"contenteditable"===e&&Cr(t)?t:"true"},kr=g("allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,default,defaultchecked,defaultmuted,defaultselected,defer,disabled,enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,required,reversed,scoped,seamless,selected,sortable,truespeed,typemustmatch,visible"),$r="http://www.w3.org/1999/xlink",Or=function(e){return":"===e.charAt(5)&&"xlink"===e.slice(0,5)},Tr=function(e){return Or(e)?e.slice(6,e.length):""},Er=function(e){return null==e||!1===e};function jr(e){for(var t=e.data,n=e,i=e;s(i.componentInstance);)(i=i.componentInstance._vnode)&&i.data&&(t=Ir(i.data,t));for(;s(n=n.parent);)n&&n.data&&(t=Ir(t,n.data));return function(e,t){if(s(e)||s(t))return Pr(e,Mr(t));return""}(t.staticClass,t.class)}function Ir(e,t){return{staticClass:Pr(e.staticClass,t.staticClass),class:s(e.class)?[e.class,t.class]:t.class}}function Pr(e,t){return e?t?e+" "+t:e:t||""}function Mr(e){return Array.isArray(e)?function(e){for(var t,n="",i=0,r=e.length;i-1?oo(e,t,n):kr(t)?Er(n)?e.removeAttribute(t):(n="allowfullscreen"===t&&"EMBED"===e.tagName?"true":t,e.setAttribute(t,n)):wr(t)?e.setAttribute(t,Sr(t,n)):Or(t)?Er(n)?e.removeAttributeNS($r,Tr(t)):e.setAttributeNS($r,t,n):oo(e,t,n)}function oo(e,t,n){if(Er(n))e.removeAttribute(t);else{if(Y&&!Q&&"TEXTAREA"===e.tagName&&"placeholder"===t&&""!==n&&!e.__ieph){var i=function(t){t.stopImmediatePropagation(),e.removeEventListener("input",i)};e.addEventListener("input",i),e.__ieph=!0}e.setAttribute(t,n)}}var so={create:io,update:io};function ao(e,t){var n=t.elm,i=t.data,r=e.data;if(!(o(i.staticClass)&&o(i.class)&&(o(r)||o(r.staticClass)&&o(r.class)))){var a=jr(t),l=n._transitionClasses;s(l)&&(a=Pr(a,Mr(l))),a!==n._prevClass&&(n.setAttribute("class",a),n._prevClass=a)}}var lo,co,uo,fo,po,ho,vo={create:ao,update:ao},mo=/[\w).+\-_$\]]/;function _o(e){var t,n,i,r,o,s=!1,a=!1,l=!1,c=!1,u=0,d=0,f=0,p=0;for(i=0;i=0&&" "===(v=e.charAt(h));h--);v&&mo.test(v)||(c=!0)}}else void 0===r?(p=i+1,r=e.slice(0,i).trim()):m();function m(){(o||(o=[])).push(e.slice(p,i).trim()),p=i+1}if(void 0===r?r=e.slice(0,i).trim():0!==p&&m(),o)for(i=0;i-1?{exp:e.slice(0,fo),key:'"'+e.slice(fo+1)+'"'}:{exp:e,key:null};co=e,fo=po=ho=0;for(;!Ao();)No(uo=Mo())?Do(uo):91===uo&&Lo(uo);return{exp:e.slice(0,po),key:e.slice(po+1,ho)}}(e);return null===n.key?"".concat(e,"=").concat(t):"$set(".concat(n.exp,", ").concat(n.key,", ").concat(t,")")}function Mo(){return co.charCodeAt(++fo)}function Ao(){return fo>=lo}function No(e){return 34===e||39===e}function Lo(e){var t=1;for(po=fo;!Ao();)if(No(e=Mo()))Do(e);else if(91===e&&t++,93===e&&t--,0===t){ho=fo;break}}function Do(e){for(var t=e;!Ao()&&(e=Mo())!==t;);}var Ro,zo="__r",Fo="__c";function Vo(e,t,n){var i=Ro;return function r(){null!==t.apply(null,arguments)&&Uo(e,r,n,i)}}var Bo=Yn&&!(ie&&Number(ie[1])<=53);function Ho(e,t,n,i){if(Bo){var r=wn,o=t;t=o._wrapper=function(e){if(e.target===e.currentTarget||e.timeStamp>=r||e.timeStamp<=0||e.target.ownerDocument!==document)return o.apply(this,arguments)}}Ro.addEventListener(e,t,oe?{capture:n,passive:i}:n)}function Uo(e,t,n,i){(i||Ro).removeEventListener(e,t._wrapper||t,n)}function qo(e,t){if(!o(e.data.on)||!o(t.data.on)){var n=t.data.on||{},i=e.data.on||{};Ro=t.elm||e.elm,function(e){if(s(e[zo])){var t=Y?"change":"input";e[t]=[].concat(e[zo],e[t]||[]),delete e[zo]}s(e[Fo])&&(e.change=[].concat(e[Fo],e.change||[]),delete e[Fo])}(n),vt(n,i,Ho,Uo,Vo,t.context),Ro=void 0}}var Wo,Go={create:qo,update:qo,destroy:function(e){return qo(e,Wr)}};function Xo(e,t){if(!o(e.data.domProps)||!o(t.data.domProps)){var n,i,r=t.elm,l=e.data.domProps||{},c=t.data.domProps||{};for(n in(s(c.__ob__)||a(c._v_attr_proxy))&&(c=t.data.domProps=P({},c)),l)n in c||(r[n]="");for(n in c){if(i=c[n],"textContent"===n||"innerHTML"===n){if(t.children&&(t.children.length=0),i===l[n])continue;1===r.childNodes.length&&r.removeChild(r.childNodes[0])}if("value"===n&&"PROGRESS"!==r.tagName){r._value=i;var u=o(i)?"":String(i);Zo(r,u)&&(r.value=u)}else if("innerHTML"===n&&Lr(r.tagName)&&o(r.innerHTML)){(Wo=Wo||document.createElement("div")).innerHTML="".concat(i,"");for(var d=Wo.firstChild;r.firstChild;)r.removeChild(r.firstChild);for(;d.firstChild;)r.appendChild(d.firstChild)}else if(i!==l[n])try{r[n]=i}catch(e){}}}}function Zo(e,t){return!e.composing&&("OPTION"===e.tagName||function(e,t){var n=!0;try{n=document.activeElement!==e}catch(e){}return n&&e.value!==t}(e,t)||function(e,t){var n=e.value,i=e._vModifiers;if(s(i)){if(i.number)return _(n)!==_(t);if(i.trim)return n.trim()!==t.trim()}return n!==t}(e,t))}var Ko={create:Xo,update:Xo},Jo=S((function(e){var t={},n=/:(.+)/;return e.split(/;(?![^(]*\))/g).forEach((function(e){if(e){var i=e.split(n);i.length>1&&(t[i[0].trim()]=i[1].trim())}})),t}));function Yo(e){var t=Qo(e.style);return e.staticStyle?P(e.staticStyle,t):t}function Qo(e){return Array.isArray(e)?M(e):"string"==typeof e?Jo(e):e}var es,ts=/^--/,ns=/\s*!important$/,is=function(e,t,n){if(ts.test(t))e.style.setProperty(t,n);else if(ns.test(n))e.style.setProperty(E(t),n.replace(ns,""),"important");else{var i=os(t);if(Array.isArray(n))for(var r=0,o=n.length;r-1?t.split(ls).forEach((function(t){return e.classList.add(t)})):e.classList.add(t);else{var n=" ".concat(e.getAttribute("class")||""," ");n.indexOf(" "+t+" ")<0&&e.setAttribute("class",(n+t).trim())}}function us(e,t){if(t&&(t=t.trim()))if(e.classList)t.indexOf(" ")>-1?t.split(ls).forEach((function(t){return e.classList.remove(t)})):e.classList.remove(t),e.classList.length||e.removeAttribute("class");else{for(var n=" ".concat(e.getAttribute("class")||""," "),i=" "+t+" ";n.indexOf(i)>=0;)n=n.replace(i," ");(n=n.trim())?e.setAttribute("class",n):e.removeAttribute("class")}}function ds(e){if(e){if("object"==typeof e){var t={};return!1!==e.css&&P(t,fs(e.name||"v")),P(t,e),t}return"string"==typeof e?fs(e):void 0}}var fs=S((function(e){return{enterClass:"".concat(e,"-enter"),enterToClass:"".concat(e,"-enter-to"),enterActiveClass:"".concat(e,"-enter-active"),leaveClass:"".concat(e,"-leave"),leaveToClass:"".concat(e,"-leave-to"),leaveActiveClass:"".concat(e,"-leave-active")}})),ps=K&&!Q,hs="transition",vs="animation",ms="transition",_s="transitionend",gs="animation",bs="animationend";ps&&(void 0===window.ontransitionend&&void 0!==window.onwebkittransitionend&&(ms="WebkitTransition",_s="webkitTransitionEnd"),void 0===window.onanimationend&&void 0!==window.onwebkitanimationend&&(gs="WebkitAnimation",bs="webkitAnimationEnd"));var ys=K?window.requestAnimationFrame?window.requestAnimationFrame.bind(window):setTimeout:function(e){return e()};function xs(e){ys((function(){ys(e)}))}function ws(e,t){var n=e._transitionClasses||(e._transitionClasses=[]);n.indexOf(t)<0&&(n.push(t),cs(e,t))}function Cs(e,t){e._transitionClasses&&x(e._transitionClasses,t),us(e,t)}function Ss(e,t,n){var i=$s(e,t),r=i.type,o=i.timeout,s=i.propCount;if(!r)return n();var a=r===hs?_s:bs,l=0,c=function(){e.removeEventListener(a,u),n()},u=function(t){t.target===e&&++l>=s&&c()};setTimeout((function(){l0&&(n=hs,u=s,d=o.length):t===vs?c>0&&(n=vs,u=c,d=l.length):d=(n=(u=Math.max(s,c))>0?s>c?hs:vs:null)?n===hs?o.length:l.length:0,{type:n,timeout:u,propCount:d,hasTransform:n===hs&&ks.test(i[ms+"Property"])}}function Os(e,t){for(;e.length1}function Ms(e,t){!0!==t.data.show&&Es(t)}var As=function(e){var t,n,i={},c=e.modules,u=e.nodeOps;for(t=0;th?y(e,o(n[_+1])?null:n[_+1].elm,n,p,_,i):p>_&&w(t,d,h)}(d,v,_,n,c):s(_)?(s(e.text)&&u.setTextContent(d,""),y(d,null,_,0,_.length-1,n)):s(v)?w(v,0,v.length-1):s(e.text)&&u.setTextContent(d,""):e.text!==t.text&&u.setTextContent(d,t.text),s(h)&&s(p=h.hook)&&s(p=p.postpatch)&&p(e,t)}}}function $(e,t,n){if(a(n)&&s(e.parent))e.parent.data.pendingInsert=t;else for(var i=0;i-1,s.selected!==o&&(s.selected=o);else if(D(zs(s),i))return void(e.selectedIndex!==a&&(e.selectedIndex=a));r||(e.selectedIndex=-1)}}function Rs(e,t){return t.every((function(t){return!D(t,e)}))}function zs(e){return"_value"in e?e._value:e.value}function Fs(e){e.target.composing=!0}function Vs(e){e.target.composing&&(e.target.composing=!1,Bs(e.target,"input"))}function Bs(e,t){var n=document.createEvent("HTMLEvents");n.initEvent(t,!0,!0),e.dispatchEvent(n)}function Hs(e){return!e.componentInstance||e.data&&e.data.transition?e:Hs(e.componentInstance._vnode)}var Us={bind:function(e,t,n){var i=t.value,r=(n=Hs(n)).data&&n.data.transition,o=e.__vOriginalDisplay="none"===e.style.display?"":e.style.display;i&&r?(n.data.show=!0,Es(n,(function(){e.style.display=o}))):e.style.display=i?o:"none"},update:function(e,t,n){var i=t.value;!i!=!t.oldValue&&((n=Hs(n)).data&&n.data.transition?(n.data.show=!0,i?Es(n,(function(){e.style.display=e.__vOriginalDisplay})):js(n,(function(){e.style.display="none"}))):e.style.display=i?e.__vOriginalDisplay:"none")},unbind:function(e,t,n,i,r){r||(e.style.display=e.__vOriginalDisplay)}},qs={model:Ns,show:Us},Ws={name:String,appear:Boolean,css:Boolean,mode:String,type:String,enterClass:String,leaveClass:String,enterToClass:String,leaveToClass:String,enterActiveClass:String,leaveActiveClass:String,appearClass:String,appearActiveClass:String,appearToClass:String,duration:[Number,String,Object]};function Gs(e){var t=e&&e.componentOptions;return t&&t.Ctor.options.abstract?Gs(on(t.children)):e}function Xs(e){var t={},n=e.$options;for(var i in n.propsData)t[i]=e[i];var r=n._parentListeners;for(var i in r)t[$(i)]=r[i];return t}function Zs(e,t){if(/\d-keep-alive$/.test(t.tag))return e("keep-alive",{props:t.componentOptions.propsData})}var Ks=function(e){return e.tag||Bt(e)},Js=function(e){return"show"===e.name},Ys={name:"transition",props:Ws,abstract:!0,render:function(e){var t=this,n=this.$slots.default;if(n&&(n=n.filter(Ks)).length){0;var i=this.mode;0;var r=n[0];if(function(e){for(;e=e.parent;)if(e.data.transition)return!0}(this.$vnode))return r;var o=Gs(r);if(!o)return r;if(this._leaving)return Zs(e,r);var s="__transition-".concat(this._uid,"-");o.key=null==o.key?o.isComment?s+"comment":s+o.tag:l(o.key)?0===String(o.key).indexOf(s)?o.key:s+o.key:o.key;var a=(o.data||(o.data={})).transition=Xs(this),c=this._vnode,u=Gs(c);if(o.data.directives&&o.data.directives.some(Js)&&(o.data.show=!0),u&&u.data&&!function(e,t){return t.key===e.key&&t.tag===e.tag}(o,u)&&!Bt(u)&&(!u.componentInstance||!u.componentInstance._vnode.isComment)){var d=u.data.transition=P({},a);if("out-in"===i)return this._leaving=!0,mt(d,"afterLeave",(function(){t._leaving=!1,t.$forceUpdate()})),Zs(e,r);if("in-out"===i){if(Bt(o))return c;var f,p=function(){f()};mt(a,"afterEnter",p),mt(a,"enterCancelled",p),mt(d,"delayLeave",(function(e){f=e}))}}return r}}},Qs=P({tag:String,moveClass:String},Ws);delete Qs.mode;var ea={props:Qs,beforeMount:function(){var e=this,t=this._update;this._update=function(n,i){var r=dn(e);e.__patch__(e._vnode,e.kept,!1,!0),e._vnode=e.kept,r(),t.call(e,n,i)}},render:function(e){for(var t=this.tag||this.$vnode.data.tag||"span",n=Object.create(null),i=this.prevChildren=this.children,r=this.$slots.default||[],o=this.children=[],s=Xs(this),a=0;a-1?zr[e]=t.constructor===window.HTMLUnknownElement||t.constructor===window.HTMLElement:zr[e]=/HTMLUnknownElement/.test(t.toString())},P(ur.options.directives,qs),P(ur.options.components,ra),ur.prototype.__patch__=K?As:A,ur.prototype.$mount=function(e,t){return function(e,t,n){var i;e.$el=t,e.$options.render||(e.$options.render=me),vn(e,"beforeMount"),i=function(){e._update(e._render(),n)},new ji(e,i,A,{before:function(){e._isMounted&&!e._isDestroyed&&vn(e,"beforeUpdate")}},!0),n=!1;var r=e._preWatchers;if(r)for(var o=0;o\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/,ma=/^\s*((?:v-[\w-]+:|@|:|#)\[[^=]+?\][^\s"'<>\/=]*)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/,_a="[a-zA-Z_][\\-\\.0-9_a-zA-Z".concat(q.source,"]*"),ga="((?:".concat(_a,"\\:)?").concat(_a,")"),ba=new RegExp("^<".concat(ga)),ya=/^\s*(\/?)>/,xa=new RegExp("^<\\/".concat(ga,"[^>]*>")),wa=/^]+>/i,Ca=/^",""":'"',"&":"&"," ":"\n"," ":"\t","'":"'"},Ta=/&(?:lt|gt|quot|amp|#39);/g,Ea=/&(?:lt|gt|quot|amp|#39|#10|#9);/g,ja=g("pre,textarea",!0),Ia=function(e,t){return e&&ja(e)&&"\n"===t[0]};function Pa(e,t){var n=t?Ea:Ta;return e.replace(n,(function(e){return Oa[e]}))}function Ma(e,t){for(var n,i,r=[],o=t.expectHTML,s=t.isUnaryTag||N,a=t.canBeLeftOpenTag||N,l=0,c=function(){if(n=e,i&&ka(i)){var c=0,f=i.toLowerCase(),p=$a[f]||($a[f]=new RegExp("([\\s\\S]*?)(]*>)","i"));w=e.replace(p,(function(e,n,i){return c=i.length,ka(f)||"noscript"===f||(n=n.replace(//g,"$1").replace(//g,"$1")),Ia(f,n)&&(n=n.slice(1)),t.chars&&t.chars(n),""}));l+=e.length-w.length,e=w,d(f,l-c,l)}else{var h=e.indexOf("<");if(0===h){if(Ca.test(e)){var v=e.indexOf("--\x3e");if(v>=0)return t.shouldKeepComment&&t.comment&&t.comment(e.substring(4,v),l,l+v+3),u(v+3),"continue"}if(Sa.test(e)){var m=e.indexOf("]>");if(m>=0)return u(m+2),"continue"}var _=e.match(wa);if(_)return u(_[0].length),"continue";var g=e.match(xa);if(g){var b=l;return u(g[0].length),d(g[1],b,l),"continue"}var y=function(){var t=e.match(ba);if(t){var n={tagName:t[1],attrs:[],start:l};u(t[0].length);for(var i=void 0,r=void 0;!(i=e.match(ya))&&(r=e.match(ma)||e.match(va));)r.start=l,u(r[0].length),r.end=l,n.attrs.push(r);if(i)return n.unarySlash=i[1],u(i[0].length),n.end=l,n}}();if(y)return function(e){var n=e.tagName,l=e.unarySlash;o&&("p"===i&&ha(n)&&d(i),a(n)&&i===n&&d(n));for(var c=s(n)||!!l,u=e.attrs.length,f=new Array(u),p=0;p=0){for(w=e.slice(h);!(xa.test(w)||ba.test(w)||Ca.test(w)||Sa.test(w)||(C=w.indexOf("<",1))<0);)h+=C,w=e.slice(h);x=e.substring(0,h)}h<0&&(x=e),x&&u(x.length),t.chars&&x&&t.chars(x,l-x.length,l)}if(e===n)return t.chars&&t.chars(e),"break"};e;){if("break"===c())break}function u(t){l+=t,e=e.substring(t)}function d(e,n,o){var s,a;if(null==n&&(n=l),null==o&&(o=l),e)for(a=e.toLowerCase(),s=r.length-1;s>=0&&r[s].lowerCasedTag!==a;s--);else s=0;if(s>=0){for(var c=r.length-1;c>=s;c--)t.end&&t.end(r[c].tag,n,o);r.length=s,i=s&&r[s-1].tag}else"br"===a?t.start&&t.start(e,[],!0,n,o):"p"===a&&(t.start&&t.start(e,[],!1,n,o),t.end&&t.end(e,n,o))}d()}var Aa,Na,La,Da,Ra,za,Fa,Va,Ba=/^@|^v-on:/,Ha=/^v-|^@|^:|^#/,Ua=/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/,qa=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,Wa=/^\(|\)$/g,Ga=/^\[.*\]$/,Xa=/:(.*)$/,Za=/^:|^\.|^v-bind:/,Ka=/\.[^.\]]+(?=[^\]]*$)/g,Ja=/^v-slot(:|$)|^#/,Ya=/[\r\n]/,Qa=/[ \f\t\r\n]+/g,el=S(da),tl="_empty_";function nl(e,t,n){return{type:1,tag:e,attrsList:t,attrsMap:cl(t),rawAttrsMap:{},parent:n,children:[]}}function il(e,t){Aa=t.warn||bo,za=t.isPreTag||N,Fa=t.mustUseProp||N,Va=t.getTagNamespace||N;var n=t.isReservedTag||N;(function(e){return!(!(e.component||e.attrsMap[":is"]||e.attrsMap["v-bind:is"])&&(e.attrsMap.is?n(e.attrsMap.is):n(e.tag)))}),La=yo(t.modules,"transformNode"),Da=yo(t.modules,"preTransformNode"),Ra=yo(t.modules,"postTransformNode"),Na=t.delimiters;var i,r,o=[],s=!1!==t.preserveWhitespace,a=t.whitespace,l=!1,c=!1;function u(e){if(d(e),l||e.processed||(e=rl(e,t)),o.length||e===i||i.if&&(e.elseif||e.else)&&sl(i,{exp:e.elseif,block:e}),r&&!e.forbidden)if(e.elseif||e.else)s=e,a=function(e){for(var t=e.length;t--;){if(1===e[t].type)return e[t];e.pop()}}(r.children),a&&a.if&&sl(a,{exp:s.elseif,block:s});else{if(e.slotScope){var n=e.slotTarget||'"default"';(r.scopedSlots||(r.scopedSlots={}))[n]=e}r.children.push(e),e.parent=r}var s,a;e.children=e.children.filter((function(e){return!e.slotScope})),d(e),e.pre&&(l=!1),za(e.tag)&&(c=!1);for(var u=0;ul&&(a.push(o=e.slice(l,r)),s.push(JSON.stringify(o)));var c=_o(i[1].trim());s.push("_s(".concat(c,")")),a.push({"@binding":c}),l=r+i[0].length}return l-1")+("true"===o?":(".concat(t,")"):":_q(".concat(t,",").concat(o,")"))),$o(e,"change","var $$a=".concat(t,",")+"$$el=$event.target,"+"$$c=$$el.checked?(".concat(o,"):(").concat(s,");")+"if(Array.isArray($$a)){"+"var $$v=".concat(i?"_n("+r+")":r,",")+"$$i=_i($$a,$$v);"+"if($$el.checked){$$i<0&&(".concat(Po(t,"$$a.concat([$$v])"),")}")+"else{$$i>-1&&(".concat(Po(t,"$$a.slice(0,$$i).concat($$a.slice($$i+1))"),")}")+"}else{".concat(Po(t,"$$c"),"}"),null,!0)}(e,i,r);else if("input"===o&&"radio"===s)!function(e,t,n){var i=n&&n.number,r=Oo(e,"value")||"null";r=i?"_n(".concat(r,")"):r,xo(e,"checked","_q(".concat(t,",").concat(r,")")),$o(e,"change",Po(t,r),null,!0)}(e,i,r);else if("input"===o||"textarea"===o)!function(e,t,n){var i=e.attrsMap.type;0;var r=n||{},o=r.lazy,s=r.number,a=r.trim,l=!o&&"range"!==i,c=o?"change":"range"===i?zo:"input",u="$event.target.value";a&&(u="$event.target.value.trim()");s&&(u="_n(".concat(u,")"));var d=Po(t,u);l&&(d="if($event.target.composing)return;".concat(d));xo(e,"value","(".concat(t,")")),$o(e,c,d,null,!0),(a||s)&&$o(e,"blur","$forceUpdate()")}(e,i,r);else{if(!U.isReservedTag(o))return Io(e,i,r),!1}return!0},text:function(e,t){t.value&&xo(e,"textContent","_s(".concat(t.value,")"),t)},html:function(e,t){t.value&&xo(e,"innerHTML","_s(".concat(t.value,")"),t)}},_l={expectHTML:!0,modules:pl,directives:ml,isPreTag:function(e){return"pre"===e},isUnaryTag:fa,mustUseProp:xr,canBeLeftOpenTag:pa,isReservedTag:Dr,getTagNamespace:Rr,staticKeys:function(e){return e.reduce((function(e,t){return e.concat(t.staticKeys||[])}),[]).join(",")}(pl)},gl=S((function(e){return g("type,tag,attrsList,attrsMap,plain,parent,children,attrs,start,end,rawAttrsMap"+(e?","+e:""))}));function bl(e,t){e&&(hl=gl(t.staticKeys||""),vl=t.isReservedTag||N,yl(e),xl(e,!1))}function yl(e){if(e.static=function(e){if(2===e.type)return!1;if(3===e.type)return!0;return!(!e.pre&&(e.hasBindings||e.if||e.for||b(e.tag)||!vl(e.tag)||function(e){for(;e.parent;){if("template"!==(e=e.parent).tag)return!1;if(e.for)return!0}return!1}(e)||!Object.keys(e).every(hl)))}(e),1===e.type){if(!vl(e.tag)&&"slot"!==e.tag&&null==e.attrsMap["inline-template"])return;for(var t=0,n=e.children.length;t|^function(?:\s+[\w$]+)?\s*\(/,Cl=/\([^)]*?\);*$/,Sl=/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['[^']*?']|\["[^"]*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*$/,kl={esc:27,tab:9,enter:13,space:32,up:38,left:37,right:39,down:40,delete:[8,46]},$l={esc:["Esc","Escape"],tab:"Tab",enter:"Enter",space:[" ","Spacebar"],up:["Up","ArrowUp"],left:["Left","ArrowLeft"],right:["Right","ArrowRight"],down:["Down","ArrowDown"],delete:["Backspace","Delete","Del"]},Ol=function(e){return"if(".concat(e,")return null;")},Tl={stop:"$event.stopPropagation();",prevent:"$event.preventDefault();",self:Ol("$event.target !== $event.currentTarget"),ctrl:Ol("!$event.ctrlKey"),shift:Ol("!$event.shiftKey"),alt:Ol("!$event.altKey"),meta:Ol("!$event.metaKey"),left:Ol("'button' in $event && $event.button !== 0"),middle:Ol("'button' in $event && $event.button !== 1"),right:Ol("'button' in $event && $event.button !== 2")};function El(e,t){var n=t?"nativeOn:":"on:",i="",r="";for(var o in e){var s=jl(e[o]);e[o]&&e[o].dynamic?r+="".concat(o,",").concat(s,","):i+='"'.concat(o,'":').concat(s,",")}return i="{".concat(i.slice(0,-1),"}"),r?n+"_d(".concat(i,",[").concat(r.slice(0,-1),"])"):n+i}function jl(e){if(!e)return"function(){}";if(Array.isArray(e))return"[".concat(e.map((function(e){return jl(e)})).join(","),"]");var t=Sl.test(e.value),n=wl.test(e.value),i=Sl.test(e.value.replace(Cl,""));if(e.modifiers){var r="",o="",s=[],a=function(t){if(Tl[t])o+=Tl[t],kl[t]&&s.push(t);else if("exact"===t){var n=e.modifiers;o+=Ol(["ctrl","shift","alt","meta"].filter((function(e){return!n[e]})).map((function(e){return"$event.".concat(e,"Key")})).join("||"))}else s.push(t)};for(var l in e.modifiers)a(l);s.length&&(r+=function(e){return"if(!$event.type.indexOf('key')&&"+"".concat(e.map(Il).join("&&"),")return null;")}(s)),o&&(r+=o);var c=t?"return ".concat(e.value,".apply(null, arguments)"):n?"return (".concat(e.value,").apply(null, arguments)"):i?"return ".concat(e.value):e.value;return"function($event){".concat(r).concat(c,"}")}return t||n?e.value:"function($event){".concat(i?"return ".concat(e.value):e.value,"}")}function Il(e){var t=parseInt(e,10);if(t)return"$event.keyCode!==".concat(t);var n=kl[e],i=$l[e];return"_k($event.keyCode,"+"".concat(JSON.stringify(e),",")+"".concat(JSON.stringify(n),",")+"$event.key,"+"".concat(JSON.stringify(i))+")"}var Pl={on:function(e,t){e.wrapListeners=function(e){return"_g(".concat(e,",").concat(t.value,")")}},bind:function(e,t){e.wrapData=function(n){return"_b(".concat(n,",'").concat(e.tag,"',").concat(t.value,",").concat(t.modifiers&&t.modifiers.prop?"true":"false").concat(t.modifiers&&t.modifiers.sync?",true":"",")")}},cloak:A},Ml=function(e){this.options=e,this.warn=e.warn||bo,this.transforms=yo(e.modules,"transformCode"),this.dataGenFns=yo(e.modules,"genData"),this.directives=P(P({},Pl),e.directives);var t=e.isReservedTag||N;this.maybeComponent=function(e){return!!e.component||!t(e.tag)},this.onceId=0,this.staticRenderFns=[],this.pre=!1};function Al(e,t){var n=new Ml(t),i=e?"script"===e.tag?"null":Nl(e,n):'_c("div")';return{render:"with(this){return ".concat(i,"}"),staticRenderFns:n.staticRenderFns}}function Nl(e,t){if(e.parent&&(e.pre=e.pre||e.parent.pre),e.staticRoot&&!e.staticProcessed)return Ll(e,t);if(e.once&&!e.onceProcessed)return Dl(e,t);if(e.for&&!e.forProcessed)return Fl(e,t);if(e.if&&!e.ifProcessed)return Rl(e,t);if("template"!==e.tag||e.slotTarget||t.pre){if("slot"===e.tag)return function(e,t){var n=e.slotName||'"default"',i=Ul(e,t),r="_t(".concat(n).concat(i?",function(){return ".concat(i,"}"):""),o=e.attrs||e.dynamicAttrs?Gl((e.attrs||[]).concat(e.dynamicAttrs||[]).map((function(e){return{name:$(e.name),value:e.value,dynamic:e.dynamic}}))):null,s=e.attrsMap["v-bind"];!o&&!s||i||(r+=",null");o&&(r+=",".concat(o));s&&(r+="".concat(o?"":",null",",").concat(s));return r+")"}(e,t);var n=void 0;if(e.component)n=function(e,t,n){var i=t.inlineTemplate?null:Ul(t,n,!0);return"_c(".concat(e,",").concat(Vl(t,n)).concat(i?",".concat(i):"",")")}(e.component,e,t);else{var i=void 0,r=t.maybeComponent(e);(!e.plain||e.pre&&r)&&(i=Vl(e,t));var o=void 0,s=t.options.bindings;r&&s&&!1!==s.__isScriptSetup&&(o=function(e,t){var n=$(t),i=O(n),r=function(r){return e[t]===r?t:e[n]===r?n:e[i]===r?i:void 0},o=r("setup-const")||r("setup-reactive-const");if(o)return o;var s=r("setup-let")||r("setup-ref")||r("setup-maybe-ref");if(s)return s}(s,e.tag)),o||(o="'".concat(e.tag,"'"));var a=e.inlineTemplate?null:Ul(e,t,!0);n="_c(".concat(o).concat(i?",".concat(i):"").concat(a?",".concat(a):"",")")}for(var l=0;l>>0}(s)):"",")")}(e,e.scopedSlots,t),",")),e.model&&(n+="model:{value:".concat(e.model.value,",callback:").concat(e.model.callback,",expression:").concat(e.model.expression,"},")),e.inlineTemplate){var o=function(e,t){var n=e.children[0];0;if(n&&1===n.type){var i=Al(n,t.options);return"inlineTemplate:{render:function(){".concat(i.render,"},staticRenderFns:[").concat(i.staticRenderFns.map((function(e){return"function(){".concat(e,"}")})).join(","),"]}")}}(e,t);o&&(n+="".concat(o,","))}return n=n.replace(/,$/,"")+"}",e.dynamicAttrs&&(n="_b(".concat(n,',"').concat(e.tag,'",').concat(Gl(e.dynamicAttrs),")")),e.wrapData&&(n=e.wrapData(n)),e.wrapListeners&&(n=e.wrapListeners(n)),n}function Bl(e){return 1===e.type&&("slot"===e.tag||e.children.some(Bl))}function Hl(e,t){var n=e.attrsMap["slot-scope"];if(e.if&&!e.ifProcessed&&!n)return Rl(e,t,Hl,"null");if(e.for&&!e.forProcessed)return Fl(e,t,Hl);var i=e.slotScope===tl?"":String(e.slotScope),r="function(".concat(i,"){")+"return ".concat("template"===e.tag?e.if&&n?"(".concat(e.if,")?").concat(Ul(e,t)||"undefined",":undefined"):Ul(e,t)||"undefined":Nl(e,t),"}"),o=i?"":",proxy:true";return"{key:".concat(e.slotTarget||'"default"',",fn:").concat(r).concat(o,"}")}function Ul(e,t,n,i,r){var o=e.children;if(o.length){var s=o[0];if(1===o.length&&s.for&&"template"!==s.tag&&"slot"!==s.tag){var a=n?t.maybeComponent(s)?",1":",0":"";return"".concat((i||Nl)(s,t)).concat(a)}var l=n?function(e,t){for(var n=0,i=0;i':'
',Yl.innerHTML.indexOf(" ")>0}var nc=!!K&&tc(!1),ic=!!K&&tc(!0),rc=S((function(e){var t=Vr(e);return t&&t.innerHTML})),oc=ur.prototype.$mount;ur.prototype.$mount=function(e,t){if((e=e&&Vr(e))===document.body||e===document.documentElement)return this;var n=this.$options;if(!n.render){var i=n.template;if(i)if("string"==typeof i)"#"===i.charAt(0)&&(i=rc(i));else{if(!i.nodeType)return this;i=i.innerHTML}else e&&(i=function(e){if(e.outerHTML)return e.outerHTML;var t=document.createElement("div");return t.appendChild(e.cloneNode(!0)),t.innerHTML}(e));if(i){0;var r=ec(i,{outputSourceRange:!1,shouldDecodeNewlines:nc,shouldDecodeNewlinesForHref:ic,delimiters:n.delimiters,comments:n.comments},this),o=r.render,s=r.staticRenderFns;n.render=o,n.staticRenderFns=s}}return oc.call(this,e,t)},ur.compile=ec}},__webpack_module_cache__={},deferred;function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={id:e,loaded:!1,exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.loaded=!0,n.exports}__webpack_require__.m=__webpack_modules__,deferred=[],__webpack_require__.O=(e,t,n,i)=>{if(!t){var r=1/0;for(l=0;l=i)&&Object.keys(__webpack_require__.O).every((e=>__webpack_require__.O[e](t[s])))?t.splice(s--,1):(o=!1,i0&&deferred[l-1][2]>i;l--)deferred[l]=deferred[l-1];deferred[l]=[t,n,i]},__webpack_require__.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return __webpack_require__.d(t,{a:t}),t},__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},__webpack_require__.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),(()=>{var e={524:0,127:0,449:0,199:0,657:0,12:0,837:0,592:0};__webpack_require__.O.j=t=>0===e[t];var t=(t,n)=>{var i,r,[o,s,a]=n,l=0;if(o.some((t=>0!==e[t]))){for(i in s)__webpack_require__.o(s,i)&&(__webpack_require__.m[i]=s[i]);if(a)var c=a(__webpack_require__)}for(t&&t(n);l__webpack_require__(44988))),__webpack_require__.O(void 0,[127,449,199,657,12,837,592],(()=>__webpack_require__(95454))),__webpack_require__.O(void 0,[127,449,199,657,12,837,592],(()=>__webpack_require__(66077))),__webpack_require__.O(void 0,[127,449,199,657,12,837,592],(()=>__webpack_require__(75644))),__webpack_require__.O(void 0,[127,449,199,657,12,837,592],(()=>__webpack_require__(14538))),__webpack_require__.O(void 0,[127,449,199,657,12,837,592],(()=>__webpack_require__(59109))),__webpack_require__.O(void 0,[127,449,199,657,12,837,592],(()=>__webpack_require__(52181)));var __webpack_exports__=__webpack_require__.O(void 0,[127,449,199,657,12,837,592],(()=>__webpack_require__(39904)));__webpack_exports__=__webpack_require__.O(__webpack_exports__)})();PK!RFBB'public/js/inventory-list.js.LICENSE.txtnu[;;;/*! * Vue.js v2.7.14 * (c) 2014-2022 Evan You * Released under the MIT License. */ /** * Checks if an event is supported in the current execution environment. * * NOTE: This will not work correctly for non-generic events such as `change`, * `reset`, `load`, `error`, and `select`. * * Borrows from Modernizr. * * @param {string} eventNameSuffix Event name, e.g. "click". * @param {?boolean} capture Check if the capture phase is supported. * @return {boolean} True if the event is supported. * @internal * @license Modernizr 3.0.0pre (Custom Build) | MIT */PK! public/js/razorpay_handler.jsnu[;;;(()=>{function r(o){return r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(r){return typeof r}:function(r){return r&&"function"==typeof Symbol&&r.constructor===Symbol&&r!==Symbol.prototype?"symbol":typeof r},r(o)}function o(o,t){for(var n=0;n",{id:"form_success",class:"ff-message-success ff_razorpay_text"}).html(n.data.message).insertAfter(r.$form),"initRazorPayModal"===n.data.actionName?r.initRazorPayModal(n.data):alert("No method found")}))}},{key:"initRazorPayModal",value:function(r){var o=this,t=r.modal_data;t.handler=function(t){o.formInstance.hideFormSubmissionProgress(o.$form);var n={action:"fluentform_razorpay_confirm_payment",transaction_hash:r.transaction_hash,form_id:o.formId,razorpay_order_id:t.razorpay_order_id,razorpay_payment_id:t.razorpay_payment_id,razorpay_signature:t.razorpay_signature};o.$form.parent().find(".ff_razorpay_text").remove(),jQuery("
",{id:o.formId+"_success",class:"ff-message-success ff_msg_temp ff_razorpay_text"}).html(r.confirming_text).insertAfter(o.$form),o.formInstance.showFormSubmissionProgress(o.$form),o.formInstance.sendData(o.$form,n)},t.modal={escape:!1,ondismiss:function(){o.$form.parent().find(".ff_razorpay_text").remove(),o.formInstance.hideFormSubmissionProgress(o.$form)}};var n=new Razorpay(t);n.on("payment.failed",(function(r){console.log(r),o.formInstance.hideFormSubmissionProgress(o.$form)})),this.formInstance.showFormSubmissionProgress(this.$form),n.open()}}])&&o(t.prototype,n),e&&o(t,e),Object.defineProperty(t,"prototype",{writable:!1}),r}();(t=jQuery).each(t("form.fluentform_has_payment"),(function(){var r=t(this);r.on("fluentform_init_single",(function(o,t){new n(r,t).init()}))}))})();PK!g _ _ public/js/payment-settings.jsnu[;;;/*! For license information please see payment-settings.js.LICENSE.txt */ (()=>{var e,t={76994:(e,t,n)=>{var i=n(40410)(n(21921),"DataView");e.exports=i},84570:(e,t,n)=>{var i=n(89542),r=n(87099),o=n(93509),a=n(47658),s=n(53165);function l(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t{var i=n(80461),r=n(69591),o=n(24042),a=n(47892),s=n(53436);function l(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t{var i=n(40410)(n(21921),"Map");e.exports=i},54746:(e,t,n)=>{var i=n(84168),r=n(57877),o=n(16771),a=n(79716),s=n(5193);function l(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t{var i=n(40410)(n(21921),"Promise");e.exports=i},86206:(e,t,n)=>{var i=n(40410)(n(21921),"Set");e.exports=i},55956:(e,t,n)=>{var i=n(54746),r=n(38660),o=n(81652);function a(e){var t=-1,n=null==e?0:e.length;for(this.__data__=new i;++t{var i=n(74706),r=n(10377),o=n(92789),a=n(49313),s=n(43362),l=n(8349);function c(e){var t=this.__data__=new i(e);this.size=t.size}c.prototype.clear=r,c.prototype.delete=o,c.prototype.get=a,c.prototype.has=s,c.prototype.set=l,e.exports=c},95879:(e,t,n)=>{var i=n(21921).Symbol;e.exports=i},24950:(e,t,n)=>{var i=n(21921).Uint8Array;e.exports=i},55882:(e,t,n)=>{var i=n(40410)(n(21921),"WeakMap");e.exports=i},86177:e=>{e.exports=function(e,t){for(var n=-1,i=null==e?0:e.length;++n{e.exports=function(e,t){for(var n=-1,i=null==e?0:e.length,r=0,o=[];++n{var i=n(69557),r=n(39651),o=n(60586),a=n(4540),s=n(63514),l=n(16611),c=Object.prototype.hasOwnProperty;e.exports=function(e,t){var n=o(e),u=!n&&r(e),d=!n&&!u&&a(e),f=!n&&!u&&!d&&l(e),h=n||u||d||f,p=h?i(e.length,String):[],m=p.length;for(var v in e)!t&&!c.call(e,v)||h&&("length"==v||d&&("offset"==v||"parent"==v)||f&&("buffer"==v||"byteLength"==v||"byteOffset"==v)||s(v,m))||p.push(v);return p}},70865:e=>{e.exports=function(e,t){for(var n=-1,i=null==e?0:e.length,r=Array(i);++n{e.exports=function(e,t){for(var n=-1,i=t.length,r=e.length;++n{e.exports=function(e,t,n,i){var r=-1,o=null==e?0:e.length;for(i&&o&&(n=e[++r]);++r{e.exports=function(e,t){for(var n=-1,i=null==e?0:e.length;++n{e.exports=function(e){return e.split("")}},33733:e=>{var t=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;e.exports=function(e){return e.match(t)||[]}},33470:(e,t,n)=>{var i=n(42834),r=n(99395),o=Object.prototype.hasOwnProperty;e.exports=function(e,t,n){var a=e[t];o.call(e,t)&&r(a,n)&&(void 0!==n||t in e)||i(e,t,n)}},77788:(e,t,n)=>{var i=n(99395);e.exports=function(e,t){for(var n=e.length;n--;)if(i(e[n][0],t))return n;return-1}},18274:(e,t,n)=>{var i=n(71587),r=n(60811);e.exports=function(e,t){return e&&i(t,r(t),e)}},15328:(e,t,n)=>{var i=n(71587),r=n(71917);e.exports=function(e,t){return e&&i(t,r(t),e)}},42834:(e,t,n)=>{var i=n(830);e.exports=function(e,t,n){"__proto__"==t&&i?i(e,t,{configurable:!0,enumerable:!0,value:n,writable:!0}):e[t]=n}},94212:(e,t,n)=>{var i=n(31631),r=n(86177),o=n(33470),a=n(18274),s=n(15328),l=n(79675),c=n(56190),u=n(69355),d=n(16304),f=n(30697),h=n(56493),p=n(53404),m=n(49350),v=n(13667),g=n(97326),b=n(60586),y=n(4540),_=n(67171),x=n(36837),w=n(72640),C=n(60811),S=n(71917),k="[object Arguments]",O="[object Function]",$="[object Object]",j={};j[k]=j["[object Array]"]=j["[object ArrayBuffer]"]=j["[object DataView]"]=j["[object Boolean]"]=j["[object Date]"]=j["[object Float32Array]"]=j["[object Float64Array]"]=j["[object Int8Array]"]=j["[object Int16Array]"]=j["[object Int32Array]"]=j["[object Map]"]=j["[object Number]"]=j[$]=j["[object RegExp]"]=j["[object Set]"]=j["[object String]"]=j["[object Symbol]"]=j["[object Uint8Array]"]=j["[object Uint8ClampedArray]"]=j["[object Uint16Array]"]=j["[object Uint32Array]"]=!0,j["[object Error]"]=j[O]=j["[object WeakMap]"]=!1,e.exports=function e(t,n,M,T,D,E){var P,A=1&n,N=2&n,I=4&n;if(M&&(P=D?M(t,T,D,E):M(t)),void 0!==P)return P;if(!x(t))return t;var F=b(t);if(F){if(P=m(t),!A)return c(t,P)}else{var R=p(t),L=R==O||"[object GeneratorFunction]"==R;if(y(t))return l(t,A);if(R==$||R==k||L&&!D){if(P=N||L?{}:g(t),!A)return N?d(t,s(P,t)):u(t,a(P,t))}else{if(!j[R])return D?t:{};P=v(t,R,A)}}E||(E=new i);var V=E.get(t);if(V)return V;E.set(t,P),w(t)?t.forEach((function(i){P.add(e(i,n,M,i,t,E))})):_(t)&&t.forEach((function(i,r){P.set(r,e(i,n,M,r,t,E))}));var z=F?void 0:(I?N?h:f:N?S:C)(t);return r(z||t,(function(i,r){z&&(i=t[r=i]),o(P,r,e(i,n,M,r,t,E))})),P}},99604:(e,t,n)=>{var i=n(36837),r=Object.create,o=function(){function e(){}return function(t){if(!i(t))return{};if(r)return r(t);e.prototype=t;var n=new e;return e.prototype=void 0,n}}();e.exports=o},79925:(e,t,n)=>{var i=n(57097),r=n(16324)(i);e.exports=r},78704:(e,t,n)=>{var i=n(79925);e.exports=function(e,t){var n=[];return i(e,(function(e,i,r){t(e,i,r)&&n.push(e)})),n}},61147:e=>{e.exports=function(e,t,n,i){for(var r=e.length,o=n+(i?1:-1);i?o--:++o{var i=n(37391)();e.exports=i},57097:(e,t,n)=>{var i=n(62216),r=n(60811);e.exports=function(e,t){return e&&i(e,t,r)}},48148:(e,t,n)=>{var i=n(77831),r=n(10736);e.exports=function(e,t){for(var n=0,o=(t=i(t,e)).length;null!=e&&n{var i=n(52131),r=n(60586);e.exports=function(e,t,n){var o=t(e);return r(e)?o:i(o,n(e))}},90093:(e,t,n)=>{var i=n(95879),r=n(21145),o=n(46165),a=i?i.toStringTag:void 0;e.exports=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":a&&a in Object(e)?r(e):o(e)}},4264:e=>{var t=Object.prototype.hasOwnProperty;e.exports=function(e,n){return null!=e&&t.call(e,n)}},56210:e=>{e.exports=function(e,t){return null!=e&&t in Object(e)}},31691:(e,t,n)=>{var i=n(61147),r=n(99206),o=n(94214);e.exports=function(e,t,n){return t==t?o(e,t,n):i(e,r,n)}},23449:(e,t,n)=>{var i=n(90093),r=n(8e4);e.exports=function(e){return r(e)&&"[object Arguments]"==i(e)}},53211:(e,t,n)=>{var i=n(55887),r=n(8e4);e.exports=function e(t,n,o,a,s){return t===n||(null==t||null==n||!r(t)&&!r(n)?t!=t&&n!=n:i(t,n,o,a,e,s))}},55887:(e,t,n)=>{var i=n(31631),r=n(79851),o=n(32498),a=n(72036),s=n(53404),l=n(60586),c=n(4540),u=n(16611),d="[object Arguments]",f="[object Array]",h="[object Object]",p=Object.prototype.hasOwnProperty;e.exports=function(e,t,n,m,v,g){var b=l(e),y=l(t),_=b?f:s(e),x=y?f:s(t),w=(_=_==d?h:_)==h,C=(x=x==d?h:x)==h,S=_==x;if(S&&c(e)){if(!c(t))return!1;b=!0,w=!1}if(S&&!w)return g||(g=new i),b||u(e)?r(e,t,n,m,v,g):o(e,t,_,n,m,v,g);if(!(1&n)){var k=w&&p.call(e,"__wrapped__"),O=C&&p.call(t,"__wrapped__");if(k||O){var $=k?e.value():e,j=O?t.value():t;return g||(g=new i),v($,j,n,m,g)}}return!!S&&(g||(g=new i),a(e,t,n,m,v,g))}},92093:(e,t,n)=>{var i=n(53404),r=n(8e4);e.exports=function(e){return r(e)&&"[object Map]"==i(e)}},60312:(e,t,n)=>{var i=n(31631),r=n(53211);e.exports=function(e,t,n,o){var a=n.length,s=a,l=!o;if(null==e)return!s;for(e=Object(e);a--;){var c=n[a];if(l&&c[2]?c[1]!==e[c[0]]:!(c[0]in e))return!1}for(;++a{e.exports=function(e){return e!=e}},4175:(e,t,n)=>{var i=n(53602),r=n(55502),o=n(36837),a=n(37211),s=/^\[object .+?Constructor\]$/,l=Function.prototype,c=Object.prototype,u=l.toString,d=c.hasOwnProperty,f=RegExp("^"+u.call(d).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");e.exports=function(e){return!(!o(e)||r(e))&&(i(e)?f:s).test(a(e))}},93417:(e,t,n)=>{var i=n(53404),r=n(8e4);e.exports=function(e){return r(e)&&"[object Set]"==i(e)}},68405:(e,t,n)=>{var i=n(90093),r=n(51150),o=n(8e4),a={};a["[object Float32Array]"]=a["[object Float64Array]"]=a["[object Int8Array]"]=a["[object Int16Array]"]=a["[object Int32Array]"]=a["[object Uint8Array]"]=a["[object Uint8ClampedArray]"]=a["[object Uint16Array]"]=a["[object Uint32Array]"]=!0,a["[object Arguments]"]=a["[object Array]"]=a["[object ArrayBuffer]"]=a["[object Boolean]"]=a["[object DataView]"]=a["[object Date]"]=a["[object Error]"]=a["[object Function]"]=a["[object Map]"]=a["[object Number]"]=a["[object Object]"]=a["[object RegExp]"]=a["[object Set]"]=a["[object String]"]=a["[object WeakMap]"]=!1,e.exports=function(e){return o(e)&&r(e.length)&&!!a[i(e)]}},46226:(e,t,n)=>{var i=n(77561),r=n(95997),o=n(90542),a=n(60586),s=n(34835);e.exports=function(e){return"function"==typeof e?e:null==e?o:"object"==typeof e?a(e)?r(e[0],e[1]):i(e):s(e)}},33040:(e,t,n)=>{var i=n(83167),r=n(31455),o=Object.prototype.hasOwnProperty;e.exports=function(e){if(!i(e))return r(e);var t=[];for(var n in Object(e))o.call(e,n)&&"constructor"!=n&&t.push(n);return t}},86553:(e,t,n)=>{var i=n(36837),r=n(83167),o=n(94770),a=Object.prototype.hasOwnProperty;e.exports=function(e){if(!i(e))return o(e);var t=r(e),n=[];for(var s in e)("constructor"!=s||!t&&a.call(e,s))&&n.push(s);return n}},95199:(e,t,n)=>{var i=n(79925),r=n(7182);e.exports=function(e,t){var n=-1,o=r(e)?Array(e.length):[];return i(e,(function(e,i,r){o[++n]=t(e,i,r)})),o}},77561:(e,t,n)=>{var i=n(60312),r=n(50348),o=n(9092);e.exports=function(e){var t=r(e);return 1==t.length&&t[0][2]?o(t[0][0],t[0][1]):function(n){return n===e||i(n,e,t)}}},95997:(e,t,n)=>{var i=n(53211),r=n(33366),o=n(18386),a=n(84914),s=n(9334),l=n(9092),c=n(10736);e.exports=function(e,t){return a(e)&&s(t)?l(c(e),t):function(n){var a=r(n,e);return void 0===a&&a===t?o(n,e):i(t,a,3)}}},4968:e=>{e.exports=function(e){return function(t){return null==t?void 0:t[e]}}},36535:(e,t,n)=>{var i=n(48148);e.exports=function(e){return function(t){return i(t,e)}}},667:e=>{e.exports=function(e){return function(t){return null==e?void 0:e[t]}}},71701:e=>{e.exports=function(e,t,n){var i=-1,r=e.length;t<0&&(t=-t>r?0:r+t),(n=n>r?r:n)<0&&(n+=r),r=t>n?0:n-t>>>0,t>>>=0;for(var o=Array(r);++i{e.exports=function(e,t){for(var n=-1,i=Array(e);++n{var i=n(95879),r=n(70865),o=n(60586),a=n(190),s=i?i.prototype:void 0,l=s?s.toString:void 0;e.exports=function e(t){if("string"==typeof t)return t;if(o(t))return r(t,e)+"";if(a(t))return l?l.call(t):"";var n=t+"";return"0"==n&&1/t==-Infinity?"-0":n}},821:(e,t,n)=>{var i=n(67089),r=/^\s+/;e.exports=function(e){return e?e.slice(0,i(e)+1).replace(r,""):e}},16403:e=>{e.exports=function(e){return function(t){return e(t)}}},30293:(e,t,n)=>{var i=n(70865);e.exports=function(e,t){return i(t,(function(t){return e[t]}))}},44934:e=>{e.exports=function(e,t){return e.has(t)}},42898:(e,t,n)=>{var i=n(90542);e.exports=function(e){return"function"==typeof e?e:i}},77831:(e,t,n)=>{var i=n(60586),r=n(84914),o=n(40683),a=n(13454);e.exports=function(e,t){return i(e)?e:r(e,t)?[e]:o(a(e))}},22487:(e,t,n)=>{var i=n(71701);e.exports=function(e,t,n){var r=e.length;return n=void 0===n?r:n,!t&&n>=r?e:i(e,t,n)}},4894:(e,t,n)=>{var i=n(24950);e.exports=function(e){var t=new e.constructor(e.byteLength);return new i(t).set(new i(e)),t}},79675:(e,t,n)=>{e=n.nmd(e);var i=n(21921),r=t&&!t.nodeType&&t,o=r&&e&&!e.nodeType&&e,a=o&&o.exports===r?i.Buffer:void 0,s=a?a.allocUnsafe:void 0;e.exports=function(e,t){if(t)return e.slice();var n=e.length,i=s?s(n):new e.constructor(n);return e.copy(i),i}},27399:(e,t,n)=>{var i=n(4894);e.exports=function(e,t){var n=t?i(e.buffer):e.buffer;return new e.constructor(n,e.byteOffset,e.byteLength)}},47009:e=>{var t=/\w*$/;e.exports=function(e){var n=new e.constructor(e.source,t.exec(e));return n.lastIndex=e.lastIndex,n}},71503:(e,t,n)=>{var i=n(95879),r=i?i.prototype:void 0,o=r?r.valueOf:void 0;e.exports=function(e){return o?Object(o.call(e)):{}}},10510:(e,t,n)=>{var i=n(4894);e.exports=function(e,t){var n=t?i(e.buffer):e.buffer;return new e.constructor(n,e.byteOffset,e.length)}},56190:e=>{e.exports=function(e,t){var n=-1,i=e.length;for(t||(t=Array(i));++n{var i=n(33470),r=n(42834);e.exports=function(e,t,n,o){var a=!n;n||(n={});for(var s=-1,l=t.length;++s{var i=n(71587),r=n(98593);e.exports=function(e,t){return i(e,r(e),t)}},16304:(e,t,n)=>{var i=n(71587),r=n(48031);e.exports=function(e,t){return i(e,r(e),t)}},54401:(e,t,n)=>{var i=n(21921)["__core-js_shared__"];e.exports=i},16324:(e,t,n)=>{var i=n(7182);e.exports=function(e,t){return function(n,r){if(null==n)return n;if(!i(n))return e(n,r);for(var o=n.length,a=t?o:-1,s=Object(n);(t?a--:++a{e.exports=function(e){return function(t,n,i){for(var r=-1,o=Object(t),a=i(t),s=a.length;s--;){var l=a[e?s:++r];if(!1===n(o[l],l,o))break}return t}}},62509:(e,t,n)=>{var i=n(22487),r=n(35709),o=n(68877),a=n(13454);e.exports=function(e){return function(t){t=a(t);var n=r(t)?o(t):void 0,s=n?n[0]:t.charAt(0),l=n?i(n,1).join(""):t.slice(1);return s[e]()+l}}},74566:(e,t,n)=>{var i=n(14037),r=n(93609),o=n(51162),a=RegExp("['’]","g");e.exports=function(e){return function(t){return i(o(r(t).replace(a,"")),e,"")}}},19593:(e,t,n)=>{var i=n(667)({À:"A",Á:"A",Â:"A",Ã:"A",Ä:"A",Å:"A",à:"a",á:"a",â:"a",ã:"a",ä:"a",å:"a",Ç:"C",ç:"c",Ð:"D",ð:"d",È:"E",É:"E",Ê:"E",Ë:"E",è:"e",é:"e",ê:"e",ë:"e",Ì:"I",Í:"I",Î:"I",Ï:"I",ì:"i",í:"i",î:"i",ï:"i",Ñ:"N",ñ:"n",Ò:"O",Ó:"O",Ô:"O",Õ:"O",Ö:"O",Ø:"O",ò:"o",ó:"o",ô:"o",õ:"o",ö:"o",ø:"o",Ù:"U",Ú:"U",Û:"U",Ü:"U",ù:"u",ú:"u",û:"u",ü:"u",Ý:"Y",ý:"y",ÿ:"y",Æ:"Ae",æ:"ae",Þ:"Th",þ:"th",ß:"ss",Ā:"A",Ă:"A",Ą:"A",ā:"a",ă:"a",ą:"a",Ć:"C",Ĉ:"C",Ċ:"C",Č:"C",ć:"c",ĉ:"c",ċ:"c",č:"c",Ď:"D",Đ:"D",ď:"d",đ:"d",Ē:"E",Ĕ:"E",Ė:"E",Ę:"E",Ě:"E",ē:"e",ĕ:"e",ė:"e",ę:"e",ě:"e",Ĝ:"G",Ğ:"G",Ġ:"G",Ģ:"G",ĝ:"g",ğ:"g",ġ:"g",ģ:"g",Ĥ:"H",Ħ:"H",ĥ:"h",ħ:"h",Ĩ:"I",Ī:"I",Ĭ:"I",Į:"I",İ:"I",ĩ:"i",ī:"i",ĭ:"i",į:"i",ı:"i",Ĵ:"J",ĵ:"j",Ķ:"K",ķ:"k",ĸ:"k",Ĺ:"L",Ļ:"L",Ľ:"L",Ŀ:"L",Ł:"L",ĺ:"l",ļ:"l",ľ:"l",ŀ:"l",ł:"l",Ń:"N",Ņ:"N",Ň:"N",Ŋ:"N",ń:"n",ņ:"n",ň:"n",ŋ:"n",Ō:"O",Ŏ:"O",Ő:"O",ō:"o",ŏ:"o",ő:"o",Ŕ:"R",Ŗ:"R",Ř:"R",ŕ:"r",ŗ:"r",ř:"r",Ś:"S",Ŝ:"S",Ş:"S",Š:"S",ś:"s",ŝ:"s",ş:"s",š:"s",Ţ:"T",Ť:"T",Ŧ:"T",ţ:"t",ť:"t",ŧ:"t",Ũ:"U",Ū:"U",Ŭ:"U",Ů:"U",Ű:"U",Ų:"U",ũ:"u",ū:"u",ŭ:"u",ů:"u",ű:"u",ų:"u",Ŵ:"W",ŵ:"w",Ŷ:"Y",ŷ:"y",Ÿ:"Y",Ź:"Z",Ż:"Z",Ž:"Z",ź:"z",ż:"z",ž:"z",IJ:"IJ",ij:"ij",Œ:"Oe",œ:"oe",ʼn:"'n",ſ:"s"});e.exports=i},830:(e,t,n)=>{var i=n(40410),r=function(){try{var e=i(Object,"defineProperty");return e({},"",{}),e}catch(e){}}();e.exports=r},79851:(e,t,n)=>{var i=n(55956),r=n(73843),o=n(44934);e.exports=function(e,t,n,a,s,l){var c=1&n,u=e.length,d=t.length;if(u!=d&&!(c&&d>u))return!1;var f=l.get(e),h=l.get(t);if(f&&h)return f==t&&h==e;var p=-1,m=!0,v=2&n?new i:void 0;for(l.set(e,t),l.set(t,e);++p{var i=n(95879),r=n(24950),o=n(99395),a=n(79851),s=n(97753),l=n(24590),c=i?i.prototype:void 0,u=c?c.valueOf:void 0;e.exports=function(e,t,n,i,c,d,f){switch(n){case"[object DataView]":if(e.byteLength!=t.byteLength||e.byteOffset!=t.byteOffset)return!1;e=e.buffer,t=t.buffer;case"[object ArrayBuffer]":return!(e.byteLength!=t.byteLength||!d(new r(e),new r(t)));case"[object Boolean]":case"[object Date]":case"[object Number]":return o(+e,+t);case"[object Error]":return e.name==t.name&&e.message==t.message;case"[object RegExp]":case"[object String]":return e==t+"";case"[object Map]":var h=s;case"[object Set]":var p=1&i;if(h||(h=l),e.size!=t.size&&!p)return!1;var m=f.get(e);if(m)return m==t;i|=2,f.set(e,t);var v=a(h(e),h(t),i,c,d,f);return f.delete(e),v;case"[object Symbol]":if(u)return u.call(e)==u.call(t)}return!1}},72036:(e,t,n)=>{var i=n(30697),r=Object.prototype.hasOwnProperty;e.exports=function(e,t,n,o,a,s){var l=1&n,c=i(e),u=c.length;if(u!=i(t).length&&!l)return!1;for(var d=u;d--;){var f=c[d];if(!(l?f in t:r.call(t,f)))return!1}var h=s.get(e),p=s.get(t);if(h&&p)return h==t&&p==e;var m=!0;s.set(e,t),s.set(t,e);for(var v=l;++d{var i="object"==typeof n.g&&n.g&&n.g.Object===Object&&n.g;e.exports=i},30697:(e,t,n)=>{var i=n(29504),r=n(98593),o=n(60811);e.exports=function(e){return i(e,o,r)}},56493:(e,t,n)=>{var i=n(29504),r=n(48031),o=n(71917);e.exports=function(e){return i(e,o,r)}},41561:(e,t,n)=>{var i=n(12600);e.exports=function(e,t){var n=e.__data__;return i(t)?n["string"==typeof t?"string":"hash"]:n.map}},50348:(e,t,n)=>{var i=n(9334),r=n(60811);e.exports=function(e){for(var t=r(e),n=t.length;n--;){var o=t[n],a=e[o];t[n]=[o,a,i(a)]}return t}},40410:(e,t,n)=>{var i=n(4175),r=n(9970);e.exports=function(e,t){var n=r(e,t);return i(n)?n:void 0}},56162:(e,t,n)=>{var i=n(2839)(Object.getPrototypeOf,Object);e.exports=i},21145:(e,t,n)=>{var i=n(95879),r=Object.prototype,o=r.hasOwnProperty,a=r.toString,s=i?i.toStringTag:void 0;e.exports=function(e){var t=o.call(e,s),n=e[s];try{e[s]=void 0;var i=!0}catch(e){}var r=a.call(e);return i&&(t?e[s]=n:delete e[s]),r}},98593:(e,t,n)=>{var i=n(90018),r=n(46099),o=Object.prototype.propertyIsEnumerable,a=Object.getOwnPropertySymbols,s=a?function(e){return null==e?[]:(e=Object(e),i(a(e),(function(t){return o.call(e,t)})))}:r;e.exports=s},48031:(e,t,n)=>{var i=n(52131),r=n(56162),o=n(98593),a=n(46099),s=Object.getOwnPropertySymbols?function(e){for(var t=[];e;)i(t,o(e)),e=r(e);return t}:a;e.exports=s},53404:(e,t,n)=>{var i=n(76994),r=n(73677),o=n(48442),a=n(86206),s=n(55882),l=n(90093),c=n(37211),u="[object Map]",d="[object Promise]",f="[object Set]",h="[object WeakMap]",p="[object DataView]",m=c(i),v=c(r),g=c(o),b=c(a),y=c(s),_=l;(i&&_(new i(new ArrayBuffer(1)))!=p||r&&_(new r)!=u||o&&_(o.resolve())!=d||a&&_(new a)!=f||s&&_(new s)!=h)&&(_=function(e){var t=l(e),n="[object Object]"==t?e.constructor:void 0,i=n?c(n):"";if(i)switch(i){case m:return p;case v:return u;case g:return d;case b:return f;case y:return h}return t}),e.exports=_},9970:e=>{e.exports=function(e,t){return null==e?void 0:e[t]}},96588:(e,t,n)=>{var i=n(77831),r=n(39651),o=n(60586),a=n(63514),s=n(51150),l=n(10736);e.exports=function(e,t,n){for(var c=-1,u=(t=i(t,e)).length,d=!1;++c{var t=RegExp("[\\u200d\\ud800-\\udfff\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff\\ufe0e\\ufe0f]");e.exports=function(e){return t.test(e)}},88594:e=>{var t=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;e.exports=function(e){return t.test(e)}},89542:(e,t,n)=>{var i=n(58315);e.exports=function(){this.__data__=i?i(null):{},this.size=0}},87099:e=>{e.exports=function(e){var t=this.has(e)&&delete this.__data__[e];return this.size-=t?1:0,t}},93509:(e,t,n)=>{var i=n(58315),r=Object.prototype.hasOwnProperty;e.exports=function(e){var t=this.__data__;if(i){var n=t[e];return"__lodash_hash_undefined__"===n?void 0:n}return r.call(t,e)?t[e]:void 0}},47658:(e,t,n)=>{var i=n(58315),r=Object.prototype.hasOwnProperty;e.exports=function(e){var t=this.__data__;return i?void 0!==t[e]:r.call(t,e)}},53165:(e,t,n)=>{var i=n(58315);e.exports=function(e,t){var n=this.__data__;return this.size+=this.has(e)?0:1,n[e]=i&&void 0===t?"__lodash_hash_undefined__":t,this}},49350:e=>{var t=Object.prototype.hasOwnProperty;e.exports=function(e){var n=e.length,i=new e.constructor(n);return n&&"string"==typeof e[0]&&t.call(e,"index")&&(i.index=e.index,i.input=e.input),i}},13667:(e,t,n)=>{var i=n(4894),r=n(27399),o=n(47009),a=n(71503),s=n(10510);e.exports=function(e,t,n){var l=e.constructor;switch(t){case"[object ArrayBuffer]":return i(e);case"[object Boolean]":case"[object Date]":return new l(+e);case"[object DataView]":return r(e,n);case"[object Float32Array]":case"[object Float64Array]":case"[object Int8Array]":case"[object Int16Array]":case"[object Int32Array]":case"[object Uint8Array]":case"[object Uint8ClampedArray]":case"[object Uint16Array]":case"[object Uint32Array]":return s(e,n);case"[object Map]":case"[object Set]":return new l;case"[object Number]":case"[object String]":return new l(e);case"[object RegExp]":return o(e);case"[object Symbol]":return a(e)}}},97326:(e,t,n)=>{var i=n(99604),r=n(56162),o=n(83167);e.exports=function(e){return"function"!=typeof e.constructor||o(e)?{}:i(r(e))}},63514:e=>{var t=/^(?:0|[1-9]\d*)$/;e.exports=function(e,n){var i=typeof e;return!!(n=null==n?9007199254740991:n)&&("number"==i||"symbol"!=i&&t.test(e))&&e>-1&&e%1==0&&e{var i=n(99395),r=n(7182),o=n(63514),a=n(36837);e.exports=function(e,t,n){if(!a(n))return!1;var s=typeof t;return!!("number"==s?r(n)&&o(t,n.length):"string"==s&&t in n)&&i(n[t],e)}},84914:(e,t,n)=>{var i=n(60586),r=n(190),o=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,a=/^\w*$/;e.exports=function(e,t){if(i(e))return!1;var n=typeof e;return!("number"!=n&&"symbol"!=n&&"boolean"!=n&&null!=e&&!r(e))||(a.test(e)||!o.test(e)||null!=t&&e in Object(t))}},12600:e=>{e.exports=function(e){var t=typeof e;return"string"==t||"number"==t||"symbol"==t||"boolean"==t?"__proto__"!==e:null===e}},55502:(e,t,n)=>{var i,r=n(54401),o=(i=/[^.]+$/.exec(r&&r.keys&&r.keys.IE_PROTO||""))?"Symbol(src)_1."+i:"";e.exports=function(e){return!!o&&o in e}},83167:e=>{var t=Object.prototype;e.exports=function(e){var n=e&&e.constructor;return e===("function"==typeof n&&n.prototype||t)}},9334:(e,t,n)=>{var i=n(36837);e.exports=function(e){return e==e&&!i(e)}},80461:e=>{e.exports=function(){this.__data__=[],this.size=0}},69591:(e,t,n)=>{var i=n(77788),r=Array.prototype.splice;e.exports=function(e){var t=this.__data__,n=i(t,e);return!(n<0)&&(n==t.length-1?t.pop():r.call(t,n,1),--this.size,!0)}},24042:(e,t,n)=>{var i=n(77788);e.exports=function(e){var t=this.__data__,n=i(t,e);return n<0?void 0:t[n][1]}},47892:(e,t,n)=>{var i=n(77788);e.exports=function(e){return i(this.__data__,e)>-1}},53436:(e,t,n)=>{var i=n(77788);e.exports=function(e,t){var n=this.__data__,r=i(n,e);return r<0?(++this.size,n.push([e,t])):n[r][1]=t,this}},84168:(e,t,n)=>{var i=n(84570),r=n(74706),o=n(73677);e.exports=function(){this.size=0,this.__data__={hash:new i,map:new(o||r),string:new i}}},57877:(e,t,n)=>{var i=n(41561);e.exports=function(e){var t=i(this,e).delete(e);return this.size-=t?1:0,t}},16771:(e,t,n)=>{var i=n(41561);e.exports=function(e){return i(this,e).get(e)}},79716:(e,t,n)=>{var i=n(41561);e.exports=function(e){return i(this,e).has(e)}},5193:(e,t,n)=>{var i=n(41561);e.exports=function(e,t){var n=i(this,e),r=n.size;return n.set(e,t),this.size+=n.size==r?0:1,this}},97753:e=>{e.exports=function(e){var t=-1,n=Array(e.size);return e.forEach((function(e,i){n[++t]=[i,e]})),n}},9092:e=>{e.exports=function(e,t){return function(n){return null!=n&&(n[e]===t&&(void 0!==t||e in Object(n)))}}},7412:(e,t,n)=>{var i=n(77756);e.exports=function(e){var t=i(e,(function(e){return 500===n.size&&n.clear(),e})),n=t.cache;return t}},58315:(e,t,n)=>{var i=n(40410)(Object,"create");e.exports=i},31455:(e,t,n)=>{var i=n(2839)(Object.keys,Object);e.exports=i},94770:e=>{e.exports=function(e){var t=[];if(null!=e)for(var n in Object(e))t.push(n);return t}},72573:(e,t,n)=>{e=n.nmd(e);var i=n(90090),r=t&&!t.nodeType&&t,o=r&&e&&!e.nodeType&&e,a=o&&o.exports===r&&i.process,s=function(){try{var e=o&&o.require&&o.require("util").types;return e||a&&a.binding&&a.binding("util")}catch(e){}}();e.exports=s},46165:e=>{var t=Object.prototype.toString;e.exports=function(e){return t.call(e)}},2839:e=>{e.exports=function(e,t){return function(n){return e(t(n))}}},21921:(e,t,n)=>{var i=n(90090),r="object"==typeof self&&self&&self.Object===Object&&self,o=i||r||Function("return this")();e.exports=o},38660:e=>{e.exports=function(e){return this.__data__.set(e,"__lodash_hash_undefined__"),this}},81652:e=>{e.exports=function(e){return this.__data__.has(e)}},24590:e=>{e.exports=function(e){var t=-1,n=Array(e.size);return e.forEach((function(e){n[++t]=e})),n}},10377:(e,t,n)=>{var i=n(74706);e.exports=function(){this.__data__=new i,this.size=0}},92789:e=>{e.exports=function(e){var t=this.__data__,n=t.delete(e);return this.size=t.size,n}},49313:e=>{e.exports=function(e){return this.__data__.get(e)}},43362:e=>{e.exports=function(e){return this.__data__.has(e)}},8349:(e,t,n)=>{var i=n(74706),r=n(73677),o=n(54746);e.exports=function(e,t){var n=this.__data__;if(n instanceof i){var a=n.__data__;if(!r||a.length<199)return a.push([e,t]),this.size=++n.size,this;n=this.__data__=new o(a)}return n.set(e,t),this.size=n.size,this}},94214:e=>{e.exports=function(e,t,n){for(var i=n-1,r=e.length;++i{var i=n(77816),r=n(35709),o=n(12453);e.exports=function(e){return r(e)?o(e):i(e)}},40683:(e,t,n)=>{var i=n(7412),r=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,o=/\\(\\)?/g,a=i((function(e){var t=[];return 46===e.charCodeAt(0)&&t.push(""),e.replace(r,(function(e,n,i,r){t.push(i?r.replace(o,"$1"):n||e)})),t}));e.exports=a},10736:(e,t,n)=>{var i=n(190);e.exports=function(e){if("string"==typeof e||i(e))return e;var t=e+"";return"0"==t&&1/e==-Infinity?"-0":t}},37211:e=>{var t=Function.prototype.toString;e.exports=function(e){if(null!=e){try{return t.call(e)}catch(e){}try{return e+""}catch(e){}}return""}},67089:e=>{var t=/\s/;e.exports=function(e){for(var n=e.length;n--&&t.test(e.charAt(n)););return n}},12453:e=>{var t="\\ud800-\\udfff",n="["+t+"]",i="[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]",r="\\ud83c[\\udffb-\\udfff]",o="[^"+t+"]",a="(?:\\ud83c[\\udde6-\\uddff]){2}",s="[\\ud800-\\udbff][\\udc00-\\udfff]",l="(?:"+i+"|"+r+")"+"?",c="[\\ufe0e\\ufe0f]?",u=c+l+("(?:\\u200d(?:"+[o,a,s].join("|")+")"+c+l+")*"),d="(?:"+[o+i+"?",i,a,s,n].join("|")+")",f=RegExp(r+"(?="+r+")|"+d+u,"g");e.exports=function(e){return e.match(f)||[]}},62360:e=>{var t="\\ud800-\\udfff",n="\\u2700-\\u27bf",i="a-z\\xdf-\\xf6\\xf8-\\xff",r="A-Z\\xc0-\\xd6\\xd8-\\xde",o="\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",a="["+o+"]",s="\\d+",l="["+n+"]",c="["+i+"]",u="[^"+t+o+s+n+i+r+"]",d="(?:\\ud83c[\\udde6-\\uddff]){2}",f="[\\ud800-\\udbff][\\udc00-\\udfff]",h="["+r+"]",p="(?:"+c+"|"+u+")",m="(?:"+h+"|"+u+")",v="(?:['’](?:d|ll|m|re|s|t|ve))?",g="(?:['’](?:D|LL|M|RE|S|T|VE))?",b="(?:[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|\\ud83c[\\udffb-\\udfff])?",y="[\\ufe0e\\ufe0f]?",_=y+b+("(?:\\u200d(?:"+["[^"+t+"]",d,f].join("|")+")"+y+b+")*"),x="(?:"+[l,d,f].join("|")+")"+_,w=RegExp([h+"?"+c+"+"+v+"(?="+[a,h,"$"].join("|")+")",m+"+"+g+"(?="+[a,h+p,"$"].join("|")+")",h+"?"+p+"+"+v,h+"+"+g,"\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])","\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])",s,x].join("|"),"g");e.exports=function(e){return e.match(w)||[]}},95249:(e,t,n)=>{var i=n(71701),r=n(54030),o=n(85038),a=Math.ceil,s=Math.max;e.exports=function(e,t,n){t=(n?r(e,t,n):void 0===t)?1:s(o(t),0);var l=null==e?0:e.length;if(!l||t<1)return[];for(var c=0,u=0,d=Array(a(l/t));c{var i=n(94212);e.exports=function(e){return i(e,5)}},93609:(e,t,n)=>{var i=n(19593),r=n(13454),o=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,a=RegExp("[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]","g");e.exports=function(e){return(e=r(e))&&e.replace(o,i).replace(a,"")}},71104:(e,t,n)=>{e.exports=n(86487)},99395:e=>{e.exports=function(e,t){return e===t||e!=e&&t!=t}},2707:(e,t,n)=>{var i=n(90018),r=n(78704),o=n(46226),a=n(60586);e.exports=function(e,t){return(a(e)?i:r)(e,o(t,3))}},86487:(e,t,n)=>{var i=n(86177),r=n(79925),o=n(42898),a=n(60586);e.exports=function(e,t){return(a(e)?i:r)(e,o(t))}},33366:(e,t,n)=>{var i=n(48148);e.exports=function(e,t,n){var r=null==e?void 0:i(e,t);return void 0===r?n:r}},6067:(e,t,n)=>{var i=n(4264),r=n(96588);e.exports=function(e,t){return null!=e&&r(e,t,i)}},18386:(e,t,n)=>{var i=n(56210),r=n(96588);e.exports=function(e,t){return null!=e&&r(e,t,i)}},90542:e=>{e.exports=function(e){return e}},14162:(e,t,n)=>{var i=n(31691),r=n(7182),o=n(49827),a=n(85038),s=n(18428),l=Math.max;e.exports=function(e,t,n,c){e=r(e)?e:s(e),n=n&&!c?a(n):0;var u=e.length;return n<0&&(n=l(u+n,0)),o(e)?n<=u&&e.indexOf(t,n)>-1:!!u&&i(e,t,n)>-1}},39651:(e,t,n)=>{var i=n(23449),r=n(8e4),o=Object.prototype,a=o.hasOwnProperty,s=o.propertyIsEnumerable,l=i(function(){return arguments}())?i:function(e){return r(e)&&a.call(e,"callee")&&!s.call(e,"callee")};e.exports=l},60586:e=>{var t=Array.isArray;e.exports=t},7182:(e,t,n)=>{var i=n(53602),r=n(51150);e.exports=function(e){return null!=e&&r(e.length)&&!i(e)}},4540:(e,t,n)=>{e=n.nmd(e);var i=n(21921),r=n(32494),o=t&&!t.nodeType&&t,a=o&&e&&!e.nodeType&&e,s=a&&a.exports===o?i.Buffer:void 0,l=(s?s.isBuffer:void 0)||r;e.exports=l},43785:(e,t,n)=>{var i=n(33040),r=n(53404),o=n(39651),a=n(60586),s=n(7182),l=n(4540),c=n(83167),u=n(16611),d=Object.prototype.hasOwnProperty;e.exports=function(e){if(null==e)return!0;if(s(e)&&(a(e)||"string"==typeof e||"function"==typeof e.splice||l(e)||u(e)||o(e)))return!e.length;var t=r(e);if("[object Map]"==t||"[object Set]"==t)return!e.size;if(c(e))return!i(e).length;for(var n in e)if(d.call(e,n))return!1;return!0}},53602:(e,t,n)=>{var i=n(90093),r=n(36837);e.exports=function(e){if(!r(e))return!1;var t=i(e);return"[object Function]"==t||"[object GeneratorFunction]"==t||"[object AsyncFunction]"==t||"[object Proxy]"==t}},51150:e=>{e.exports=function(e){return"number"==typeof e&&e>-1&&e%1==0&&e<=9007199254740991}},67171:(e,t,n)=>{var i=n(92093),r=n(16403),o=n(72573),a=o&&o.isMap,s=a?r(a):i;e.exports=s},36837:e=>{e.exports=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}},8e4:e=>{e.exports=function(e){return null!=e&&"object"==typeof e}},72640:(e,t,n)=>{var i=n(93417),r=n(16403),o=n(72573),a=o&&o.isSet,s=a?r(a):i;e.exports=s},49827:(e,t,n)=>{var i=n(90093),r=n(60586),o=n(8e4);e.exports=function(e){return"string"==typeof e||!r(e)&&o(e)&&"[object String]"==i(e)}},190:(e,t,n)=>{var i=n(90093),r=n(8e4);e.exports=function(e){return"symbol"==typeof e||r(e)&&"[object Symbol]"==i(e)}},16611:(e,t,n)=>{var i=n(68405),r=n(16403),o=n(72573),a=o&&o.isTypedArray,s=a?r(a):i;e.exports=s},60811:(e,t,n)=>{var i=n(33426),r=n(33040),o=n(7182);e.exports=function(e){return o(e)?i(e):r(e)}},71917:(e,t,n)=>{var i=n(33426),r=n(86553),o=n(7182);e.exports=function(e){return o(e)?i(e,!0):r(e)}},39416:(e,t,n)=>{var i=n(70865),r=n(46226),o=n(95199),a=n(60586);e.exports=function(e,t){return(a(e)?i:o)(e,r(t,3))}},77756:(e,t,n)=>{var i=n(54746);function r(e,t){if("function"!=typeof e||null!=t&&"function"!=typeof t)throw new TypeError("Expected a function");var n=function(){var i=arguments,r=t?t.apply(this,i):i[0],o=n.cache;if(o.has(r))return o.get(r);var a=e.apply(this,i);return n.cache=o.set(r,a)||o,a};return n.cache=new(r.Cache||i),n}r.Cache=i,e.exports=r},34835:(e,t,n)=>{var i=n(4968),r=n(36535),o=n(84914),a=n(10736);e.exports=function(e){return o(e)?i(a(e)):r(e)}},36752:(e,t,n)=>{var i=n(74566)((function(e,t,n){return e+(n?"_":"")+t.toLowerCase()}));e.exports=i},48155:(e,t,n)=>{var i=n(74566),r=n(30380),o=i((function(e,t,n){return e+(n?" ":"")+r(t)}));e.exports=o},46099:e=>{e.exports=function(){return[]}},32494:e=>{e.exports=function(){return!1}},504:(e,t,n)=>{var i=n(46252),r=1/0;e.exports=function(e){return e?(e=i(e))===r||e===-1/0?17976931348623157e292*(e<0?-1:1):e==e?e:0:0===e?e:0}},85038:(e,t,n)=>{var i=n(504);e.exports=function(e){var t=i(e),n=t%1;return t==t?n?t-n:t:0}},46252:(e,t,n)=>{var i=n(821),r=n(36837),o=n(190),a=/^[-+]0x[0-9a-f]+$/i,s=/^0b[01]+$/i,l=/^0o[0-7]+$/i,c=parseInt;e.exports=function(e){if("number"==typeof e)return e;if(o(e))return NaN;if(r(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=r(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=i(e);var n=s.test(e);return n||l.test(e)?c(e.slice(2),n?2:8):a.test(e)?NaN:+e}},13454:(e,t,n)=>{var i=n(75358);e.exports=function(e){return null==e?"":i(e)}},30380:(e,t,n)=>{var i=n(62509)("toUpperCase");e.exports=i},18428:(e,t,n)=>{var i=n(30293),r=n(60811);e.exports=function(e){return null==e?[]:i(e,r(e))}},51162:(e,t,n)=>{var i=n(33733),r=n(88594),o=n(13454),a=n(62360);e.exports=function(e,t,n){return e=o(e),void 0===(t=n?void 0:t)?r(e)?a(e):i(e):e.match(t)||[]}},36890:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>k});var i=n(88239),r=n(72444),o=/%[sdj%]/g;function a(){for(var e=arguments.length,t=Array(e),n=0;n=a)return e;switch(e){case"%s":return String(t[i++]);case"%d":return Number(t[i++]);case"%j":try{return JSON.stringify(t[i++])}catch(e){return"[Circular]"}break;default:return e}})),l=t[i];i()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,url:new RegExp("^(?!mailto:)(?:(?:http|https|ftp)://|//)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$","i"),hex:/^#?([a-f0-9]{6}|[a-f0-9]{3})$/i},m={integer:function(e){return m.number(e)&&parseInt(e,10)===e},float:function(e){return m.number(e)&&!m.integer(e)},array:function(e){return Array.isArray(e)},regexp:function(e){if(e instanceof RegExp)return!0;try{return!!new RegExp(e)}catch(e){return!1}},date:function(e){return"function"==typeof e.getTime&&"function"==typeof e.getMonth&&"function"==typeof e.getYear},number:function(e){return!isNaN(e)&&"number"==typeof e},object:function(e){return"object"===(void 0===e?"undefined":(0,r.Z)(e))&&!m.array(e)},method:function(e){return"function"==typeof e},email:function(e){return"string"==typeof e&&!!e.match(p.email)&&e.length<255},url:function(e){return"string"==typeof e&&!!e.match(p.url)},hex:function(e){return"string"==typeof e&&!!e.match(p.hex)}};const v=function(e,t,n,i,o){if(e.required&&void 0===t)f(e,t,n,i,o);else{var s=e.type;["integer","float","array","regexp","object","method","email","number","date","url","hex"].indexOf(s)>-1?m[s](t)||i.push(a(o.messages.types[s],e.fullField,e.type)):s&&(void 0===t?"undefined":(0,r.Z)(t))!==e.type&&i.push(a(o.messages.types[s],e.fullField,e.type))}};var g="enum";const b={required:f,whitespace:h,type:v,range:function(e,t,n,i,r){var o="number"==typeof e.len,s="number"==typeof e.min,l="number"==typeof e.max,c=t,u=null,d="number"==typeof t,f="string"==typeof t,h=Array.isArray(t);if(d?u="number":f?u="string":h&&(u="array"),!u)return!1;h&&(c=t.length),f&&(c=t.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g,"_").length),o?c!==e.len&&i.push(a(r.messages[u].len,e.fullField,e.len)):s&&!l&&ce.max?i.push(a(r.messages[u].max,e.fullField,e.max)):s&&l&&(ce.max)&&i.push(a(r.messages[u].range,e.fullField,e.min,e.max))},enum:function(e,t,n,i,r){e[g]=Array.isArray(e[g])?e[g]:[],-1===e[g].indexOf(t)&&i.push(a(r.messages[g],e.fullField,e[g].join(", ")))},pattern:function(e,t,n,i,r){if(e.pattern)if(e.pattern instanceof RegExp)e.pattern.lastIndex=0,e.pattern.test(t)||i.push(a(r.messages.pattern.mismatch,e.fullField,t,e.pattern));else if("string"==typeof e.pattern){new RegExp(e.pattern).test(t)||i.push(a(r.messages.pattern.mismatch,e.fullField,t,e.pattern))}}};const y=function(e,t,n,i,o){var a=[],s=Array.isArray(t)?"array":void 0===t?"undefined":(0,r.Z)(t);b.required(e,t,i,a,o,s),n(a)};const _=function(e,t,n,i,r){var o=e.type,a=[];if(e.required||!e.required&&i.hasOwnProperty(e.field)){if(s(t,o)&&!e.required)return n();b.required(e,t,i,a,r,o),s(t,o)||b.type(e,t,i,a,r)}n(a)},x={string:function(e,t,n,i,r){var o=[];if(e.required||!e.required&&i.hasOwnProperty(e.field)){if(s(t,"string")&&!e.required)return n();b.required(e,t,i,o,r,"string"),s(t,"string")||(b.type(e,t,i,o,r),b.range(e,t,i,o,r),b.pattern(e,t,i,o,r),!0===e.whitespace&&b.whitespace(e,t,i,o,r))}n(o)},method:function(e,t,n,i,r){var o=[];if(e.required||!e.required&&i.hasOwnProperty(e.field)){if(s(t)&&!e.required)return n();b.required(e,t,i,o,r),void 0!==t&&b.type(e,t,i,o,r)}n(o)},number:function(e,t,n,i,r){var o=[];if(e.required||!e.required&&i.hasOwnProperty(e.field)){if(s(t)&&!e.required)return n();b.required(e,t,i,o,r),void 0!==t&&(b.type(e,t,i,o,r),b.range(e,t,i,o,r))}n(o)},boolean:function(e,t,n,i,r){var o=[];if(e.required||!e.required&&i.hasOwnProperty(e.field)){if(s(t)&&!e.required)return n();b.required(e,t,i,o,r),void 0!==t&&b.type(e,t,i,o,r)}n(o)},regexp:function(e,t,n,i,r){var o=[];if(e.required||!e.required&&i.hasOwnProperty(e.field)){if(s(t)&&!e.required)return n();b.required(e,t,i,o,r),s(t)||b.type(e,t,i,o,r)}n(o)},integer:function(e,t,n,i,r){var o=[];if(e.required||!e.required&&i.hasOwnProperty(e.field)){if(s(t)&&!e.required)return n();b.required(e,t,i,o,r),void 0!==t&&(b.type(e,t,i,o,r),b.range(e,t,i,o,r))}n(o)},float:function(e,t,n,i,r){var o=[];if(e.required||!e.required&&i.hasOwnProperty(e.field)){if(s(t)&&!e.required)return n();b.required(e,t,i,o,r),void 0!==t&&(b.type(e,t,i,o,r),b.range(e,t,i,o,r))}n(o)},array:function(e,t,n,i,r){var o=[];if(e.required||!e.required&&i.hasOwnProperty(e.field)){if(s(t,"array")&&!e.required)return n();b.required(e,t,i,o,r,"array"),s(t,"array")||(b.type(e,t,i,o,r),b.range(e,t,i,o,r))}n(o)},object:function(e,t,n,i,r){var o=[];if(e.required||!e.required&&i.hasOwnProperty(e.field)){if(s(t)&&!e.required)return n();b.required(e,t,i,o,r),void 0!==t&&b.type(e,t,i,o,r)}n(o)},enum:function(e,t,n,i,r){var o=[];if(e.required||!e.required&&i.hasOwnProperty(e.field)){if(s(t)&&!e.required)return n();b.required(e,t,i,o,r),t&&b.enum(e,t,i,o,r)}n(o)},pattern:function(e,t,n,i,r){var o=[];if(e.required||!e.required&&i.hasOwnProperty(e.field)){if(s(t,"string")&&!e.required)return n();b.required(e,t,i,o,r),s(t,"string")||b.pattern(e,t,i,o,r)}n(o)},date:function(e,t,n,i,r){var o=[];if(e.required||!e.required&&i.hasOwnProperty(e.field)){if(s(t)&&!e.required)return n();if(b.required(e,t,i,o,r),!s(t)){var a=void 0;a="number"==typeof t?new Date(t):t,b.type(e,a,i,o,r),a&&b.range(e,a.getTime(),i,o,r)}}n(o)},url:_,hex:_,email:_,required:y};function w(){return{default:"Validation error on field %s",required:"%s is required",enum:"%s must be one of %s",whitespace:"%s cannot be empty",date:{format:"%s date %s is invalid for format %s",parse:"%s date could not be parsed, %s is invalid ",invalid:"%s date %s is invalid"},types:{string:"%s is not a %s",method:"%s is not a %s (function)",array:"%s is not an %s",object:"%s is not an %s",number:"%s is not a %s",date:"%s is not a %s",boolean:"%s is not a %s",integer:"%s is not an %s",float:"%s is not a %s",regexp:"%s is not a valid %s",email:"%s is not a valid %s",url:"%s is not a valid %s",hex:"%s is not a valid %s"},string:{len:"%s must be exactly %s characters",min:"%s must be at least %s characters",max:"%s cannot be longer than %s characters",range:"%s must be between %s and %s characters"},number:{len:"%s must equal %s",min:"%s cannot be less than %s",max:"%s cannot be greater than %s",range:"%s must be between %s and %s"},array:{len:"%s must be exactly %s in length",min:"%s cannot be less than %s in length",max:"%s cannot be greater than %s in length",range:"%s must be between %s and %s in length"},pattern:{mismatch:"%s value %s does not match pattern %s"},clone:function(){var e=JSON.parse(JSON.stringify(this));return e.clone=this.clone,e}}}var C=w();function S(e){this.rules=null,this._messages=C,this.define(e)}S.prototype={messages:function(e){return e&&(this._messages=d(w(),e)),this._messages},define:function(e){if(!e)throw new Error("Cannot configure a schema with no rules");if("object"!==(void 0===e?"undefined":(0,r.Z)(e))||Array.isArray(e))throw new Error("Rules must be an object");this.rules={};var t=void 0,n=void 0;for(t in e)e.hasOwnProperty(t)&&(n=e[t],this.rules[t]=Array.isArray(n)?n:[n])},validate:function(e){var t=this,n=e,o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},s=arguments[2];if("function"==typeof o&&(s=o,o={}),this.rules&&0!==Object.keys(this.rules).length){if(o.messages){var l=this.messages();l===C&&(l=w()),d(l,o.messages),o.messages=l}else o.messages=this.messages();var f=void 0,h=void 0,p={};(o.keys||Object.keys(this.rules)).forEach((function(r){f=t.rules[r],h=n[r],f.forEach((function(o){var a=o;"function"==typeof a.transform&&(n===e&&(n=(0,i.Z)({},n)),h=n[r]=a.transform(h)),(a="function"==typeof a?{validator:a}:(0,i.Z)({},a)).validator=t.getValidationMethod(a),a.field=r,a.fullField=a.fullField||r,a.type=t.getType(a),a.validator&&(p[r]=p[r]||[],p[r].push({rule:a,value:h,source:n,field:r}))}))}));var m={};c(p,o,(function(e,t){var n=e.rule,s=!("object"!==n.type&&"array"!==n.type||"object"!==(0,r.Z)(n.fields)&&"object"!==(0,r.Z)(n.defaultField));function l(e,t){return(0,i.Z)({},t,{fullField:n.fullField+"."+e})}function c(){var r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];if(Array.isArray(r)||(r=[r]),r.length,r.length&&n.message&&(r=[].concat(n.message)),r=r.map(u(n)),o.first&&r.length)return m[n.field]=1,t(r);if(s){if(n.required&&!e.value)return r=n.message?[].concat(n.message).map(u(n)):o.error?[o.error(n,a(o.messages.required,n.field))]:[],t(r);var c={};if(n.defaultField)for(var d in e.value)e.value.hasOwnProperty(d)&&(c[d]=n.defaultField);for(var f in c=(0,i.Z)({},c,e.rule.fields))if(c.hasOwnProperty(f)){var h=Array.isArray(c[f])?c[f]:[c[f]];c[f]=h.map(l.bind(null,f))}var p=new S(c);p.messages(o.messages),e.rule.options&&(e.rule.options.messages=o.messages,e.rule.options.error=o.error),p.validate(e.value,e.rule.options||o,(function(e){t(e&&e.length?r.concat(e):e)}))}else t(r)}s=s&&(n.required||!n.required&&e.value),n.field=e.field;var d=n.validator(n,e.value,c,e.source,o);d&&d.then&&d.then((function(){return c()}),(function(e){return c(e)}))}),(function(e){!function(e){var t,n=void 0,i=void 0,r=[],o={};for(n=0;n{"use strict";var i=n(80664),r=n.n(i),o=n(14923),a=n.n(o),s=n(88331),l=n.n(s),c=n(67787),u=n.n(c),d=n(17113),f=n.n(d),h=n(66177),p=n.n(h),m=n(35034),v=n.n(m),g=n(63364),b=n.n(g),y=n(75652),_=n.n(y),x=n(24650),w=n.n(x),C=n(71937),S=n.n(C),k=n(22428),O=n.n(k),$=n(45614),j=n.n($),M=n(67186),T=n.n(M),D=n(62618),E=n.n(D),P=n(13235),A=n.n(P),N=n(85517),I=n.n(N),F=n(48970),R=n.n(F),L=n(44242),V=n.n(L),z=n(91119),B=n.n(z),H=n(10642),W=n.n(H),q=n(82626),U=n.n(q),Y=n(81337),K=n.n(Y),G=n(21530),X=n.n(G),J=n(50905),Z=n.n(J),Q=n(41955),ee=n.n(Q),te=n(40032),ne=n.n(te),ie=n(14561),re=n.n(ie),oe=n(54223),ae=n.n(oe),se=n(46066),le=n.n(se),ce=n(7626),ue=n.n(ce),de=n(87563),fe=n.n(de),he=n(26426),pe=n.n(he),me=n(30272),ve=n.n(me),ge=n(16473),be=n.n(ge),ye=n(73591),_e=n.n(ye),xe=n(70538);function we(e,t){for(var n in t)e[n]=t[n];return e}var Ce=/[!'()*]/g,Se=function(e){return"%"+e.charCodeAt(0).toString(16)},ke=/%2C/g,Oe=function(e){return encodeURIComponent(e).replace(Ce,Se).replace(ke,",")};function $e(e){try{return decodeURIComponent(e)}catch(e){0}return e}var je=function(e){return null==e||"object"==typeof e?e:String(e)};function Me(e){var t={};return(e=e.trim().replace(/^(\?|#|&)/,""))?(e.split("&").forEach((function(e){var n=e.replace(/\+/g," ").split("="),i=$e(n.shift()),r=n.length>0?$e(n.join("=")):null;void 0===t[i]?t[i]=r:Array.isArray(t[i])?t[i].push(r):t[i]=[t[i],r]})),t):t}function Te(e){var t=e?Object.keys(e).map((function(t){var n=e[t];if(void 0===n)return"";if(null===n)return Oe(t);if(Array.isArray(n)){var i=[];return n.forEach((function(e){void 0!==e&&(null===e?i.push(Oe(t)):i.push(Oe(t)+"="+Oe(e)))})),i.join("&")}return Oe(t)+"="+Oe(n)})).filter((function(e){return e.length>0})).join("&"):null;return t?"?"+t:""}var De=/\/?$/;function Ee(e,t,n,i){var r=i&&i.options.stringifyQuery,o=t.query||{};try{o=Pe(o)}catch(e){}var a={name:t.name||e&&e.name,meta:e&&e.meta||{},path:t.path||"/",hash:t.hash||"",query:o,params:t.params||{},fullPath:Ie(t,r),matched:e?Ne(e):[]};return n&&(a.redirectedFrom=Ie(n,r)),Object.freeze(a)}function Pe(e){if(Array.isArray(e))return e.map(Pe);if(e&&"object"==typeof e){var t={};for(var n in e)t[n]=Pe(e[n]);return t}return e}var Ae=Ee(null,{path:"/"});function Ne(e){for(var t=[];e;)t.unshift(e),e=e.parent;return t}function Ie(e,t){var n=e.path,i=e.query;void 0===i&&(i={});var r=e.hash;return void 0===r&&(r=""),(n||"/")+(t||Te)(i)+r}function Fe(e,t,n){return t===Ae?e===t:!!t&&(e.path&&t.path?e.path.replace(De,"")===t.path.replace(De,"")&&(n||e.hash===t.hash&&Re(e.query,t.query)):!(!e.name||!t.name)&&(e.name===t.name&&(n||e.hash===t.hash&&Re(e.query,t.query)&&Re(e.params,t.params))))}function Re(e,t){if(void 0===e&&(e={}),void 0===t&&(t={}),!e||!t)return e===t;var n=Object.keys(e).sort(),i=Object.keys(t).sort();return n.length===i.length&&n.every((function(n,r){var o=e[n];if(i[r]!==n)return!1;var a=t[n];return null==o||null==a?o===a:"object"==typeof o&&"object"==typeof a?Re(o,a):String(o)===String(a)}))}function Le(e){for(var t=0;t=0&&(t=e.slice(i),e=e.slice(0,i));var r=e.indexOf("?");return r>=0&&(n=e.slice(r+1),e=e.slice(0,r)),{path:e,query:n,hash:t}}(r.path||""),c=t&&t.path||"/",u=l.path?Be(l.path,c,n||r.append):c,d=function(e,t,n){void 0===t&&(t={});var i,r=n||Me;try{i=r(e||"")}catch(e){i={}}for(var o in t){var a=t[o];i[o]=Array.isArray(a)?a.map(je):je(a)}return i}(l.query,r.query,i&&i.options.parseQuery),f=r.hash||l.hash;return f&&"#"!==f.charAt(0)&&(f="#"+f),{_normalized:!0,path:u,query:d,hash:f}}var ct,ut=function(){},dt={name:"RouterLink",props:{to:{type:[String,Object],required:!0},tag:{type:String,default:"a"},custom:Boolean,exact:Boolean,exactPath:Boolean,append:Boolean,replace:Boolean,activeClass:String,exactActiveClass:String,ariaCurrentValue:{type:String,default:"page"},event:{type:[String,Array],default:"click"}},render:function(e){var t=this,n=this.$router,i=this.$route,r=n.resolve(this.to,i,this.append),o=r.location,a=r.route,s=r.href,l={},c=n.options.linkActiveClass,u=n.options.linkExactActiveClass,d=null==c?"router-link-active":c,f=null==u?"router-link-exact-active":u,h=null==this.activeClass?d:this.activeClass,p=null==this.exactActiveClass?f:this.exactActiveClass,m=a.redirectedFrom?Ee(null,lt(a.redirectedFrom),null,n):a;l[p]=Fe(i,m,this.exactPath),l[h]=this.exact||this.exactPath?l[p]:function(e,t){return 0===e.path.replace(De,"/").indexOf(t.path.replace(De,"/"))&&(!t.hash||e.hash===t.hash)&&function(e,t){for(var n in t)if(!(n in e))return!1;return!0}(e.query,t.query)}(i,m);var v=l[p]?this.ariaCurrentValue:null,g=function(e){ft(e)&&(t.replace?n.replace(o,ut):n.push(o,ut))},b={click:ft};Array.isArray(this.event)?this.event.forEach((function(e){b[e]=g})):b[this.event]=g;var y={class:l},_=!this.$scopedSlots.$hasNormal&&this.$scopedSlots.default&&this.$scopedSlots.default({href:s,route:a,navigate:g,isActive:l[h],isExactActive:l[p]});if(_){if(1===_.length)return _[0];if(_.length>1||!_.length)return 0===_.length?e():e("span",{},_)}if("a"===this.tag)y.on=b,y.attrs={href:s,"aria-current":v};else{var x=ht(this.$slots.default);if(x){x.isStatic=!1;var w=x.data=we({},x.data);for(var C in w.on=w.on||{},w.on){var S=w.on[C];C in b&&(w.on[C]=Array.isArray(S)?S:[S])}for(var k in b)k in w.on?w.on[k].push(b[k]):w.on[k]=g;var O=x.data.attrs=we({},x.data.attrs);O.href=s,O["aria-current"]=v}else y.on=b}return e(this.tag,y,this.$slots.default)}};function ft(e){if(!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey||e.defaultPrevented||void 0!==e.button&&0!==e.button)){if(e.currentTarget&&e.currentTarget.getAttribute){var t=e.currentTarget.getAttribute("target");if(/\b_blank\b/i.test(t))return}return e.preventDefault&&e.preventDefault(),!0}}function ht(e){if(e)for(var t,n=0;n-1&&(s.params[f]=n.params[f]);return s.path=st(u.path,s.params),l(u,s,a)}if(s.path){s.params={};for(var h=0;h-1}function qt(e,t){return Wt(e)&&e._isRouter&&(null==t||e.type===t)}function Ut(e,t,n){var i=function(r){r>=e.length?n():e[r]?t(e[r],(function(){i(r+1)})):i(r+1)};i(0)}function Yt(e){return function(t,n,i){var r=!1,o=0,a=null;Kt(e,(function(e,t,n,s){if("function"==typeof e&&void 0===e.cid){r=!0,o++;var l,c=Jt((function(t){var r;((r=t).__esModule||Xt&&"Module"===r[Symbol.toStringTag])&&(t=t.default),e.resolved="function"==typeof t?t:ct.extend(t),n.components[s]=t,--o<=0&&i()})),u=Jt((function(e){var t="Failed to resolve async component "+s+": "+e;a||(a=Wt(e)?e:new Error(t),i(a))}));try{l=e(c,u)}catch(e){u(e)}if(l)if("function"==typeof l.then)l.then(c,u);else{var d=l.component;d&&"function"==typeof d.then&&d.then(c,u)}}})),r||i()}}function Kt(e,t){return Gt(e.map((function(e){return Object.keys(e.components).map((function(n){return t(e.components[n],e.instances[n],e,n)}))})))}function Gt(e){return Array.prototype.concat.apply([],e)}var Xt="function"==typeof Symbol&&"symbol"==typeof Symbol.toStringTag;function Jt(e){var t=!1;return function(){for(var n=[],i=arguments.length;i--;)n[i]=arguments[i];if(!t)return t=!0,e.apply(this,n)}}var Zt=function(e,t){this.router=e,this.base=function(e){if(!e)if(pt){var t=document.querySelector("base");e=(e=t&&t.getAttribute("href")||"/").replace(/^https?:\/\/[^\/]+/,"")}else e="/";"/"!==e.charAt(0)&&(e="/"+e);return e.replace(/\/$/,"")}(t),this.current=Ae,this.pending=null,this.ready=!1,this.readyCbs=[],this.readyErrorCbs=[],this.errorCbs=[],this.listeners=[]};function Qt(e,t,n,i){var r=Kt(e,(function(e,i,r,o){var a=function(e,t){"function"!=typeof e&&(e=ct.extend(e));return e.options[t]}(e,t);if(a)return Array.isArray(a)?a.map((function(e){return n(e,i,r,o)})):n(a,i,r,o)}));return Gt(i?r.reverse():r)}function en(e,t){if(t)return function(){return e.apply(t,arguments)}}Zt.prototype.listen=function(e){this.cb=e},Zt.prototype.onReady=function(e,t){this.ready?e():(this.readyCbs.push(e),t&&this.readyErrorCbs.push(t))},Zt.prototype.onError=function(e){this.errorCbs.push(e)},Zt.prototype.transitionTo=function(e,t,n){var i,r=this;try{i=this.router.match(e,this.current)}catch(e){throw this.errorCbs.forEach((function(t){t(e)})),e}var o=this.current;this.confirmTransition(i,(function(){r.updateRoute(i),t&&t(i),r.ensureURL(),r.router.afterHooks.forEach((function(e){e&&e(i,o)})),r.ready||(r.ready=!0,r.readyCbs.forEach((function(e){e(i)})))}),(function(e){n&&n(e),e&&!r.ready&&(qt(e,Lt.redirected)&&o===Ae||(r.ready=!0,r.readyErrorCbs.forEach((function(t){t(e)}))))}))},Zt.prototype.confirmTransition=function(e,t,n){var i=this,r=this.current;this.pending=e;var o,a,s=function(e){!qt(e)&&Wt(e)&&(i.errorCbs.length?i.errorCbs.forEach((function(t){t(e)})):console.error(e)),n&&n(e)},l=e.matched.length-1,c=r.matched.length-1;if(Fe(e,r)&&l===c&&e.matched[l]===r.matched[c])return this.ensureURL(),e.hash&&$t(this.router,r,e,!1),s(((a=Bt(o=r,e,Lt.duplicated,'Avoided redundant navigation to current location: "'+o.fullPath+'".')).name="NavigationDuplicated",a));var u=function(e,t){var n,i=Math.max(e.length,t.length);for(n=0;n0)){var t=this.router,n=t.options.scrollBehavior,i=It&&n;i&&this.listeners.push(Ot());var r=function(){var n=e.current,r=nn(e.base);e.current===Ae&&r===e._startLocation||e.transitionTo(r,(function(e){i&&$t(t,e,n,!0)}))};window.addEventListener("popstate",r),this.listeners.push((function(){window.removeEventListener("popstate",r)}))}},t.prototype.go=function(e){window.history.go(e)},t.prototype.push=function(e,t,n){var i=this,r=this.current;this.transitionTo(e,(function(e){Ft(He(i.base+e.fullPath)),$t(i.router,e,r,!1),t&&t(e)}),n)},t.prototype.replace=function(e,t,n){var i=this,r=this.current;this.transitionTo(e,(function(e){Rt(He(i.base+e.fullPath)),$t(i.router,e,r,!1),t&&t(e)}),n)},t.prototype.ensureURL=function(e){if(nn(this.base)!==this.current.fullPath){var t=He(this.base+this.current.fullPath);e?Ft(t):Rt(t)}},t.prototype.getCurrentLocation=function(){return nn(this.base)},t}(Zt);function nn(e){var t=window.location.pathname,n=t.toLowerCase(),i=e.toLowerCase();return!e||n!==i&&0!==n.indexOf(He(i+"/"))||(t=t.slice(e.length)),(t||"/")+window.location.search+window.location.hash}var rn=function(e){function t(t,n,i){e.call(this,t,n),i&&function(e){var t=nn(e);if(!/^\/#/.test(t))return window.location.replace(He(e+"/#"+t)),!0}(this.base)||on()}return e&&(t.__proto__=e),t.prototype=Object.create(e&&e.prototype),t.prototype.constructor=t,t.prototype.setupListeners=function(){var e=this;if(!(this.listeners.length>0)){var t=this.router.options.scrollBehavior,n=It&&t;n&&this.listeners.push(Ot());var i=function(){var t=e.current;on()&&e.transitionTo(an(),(function(i){n&&$t(e.router,i,t,!0),It||cn(i.fullPath)}))},r=It?"popstate":"hashchange";window.addEventListener(r,i),this.listeners.push((function(){window.removeEventListener(r,i)}))}},t.prototype.push=function(e,t,n){var i=this,r=this.current;this.transitionTo(e,(function(e){ln(e.fullPath),$t(i.router,e,r,!1),t&&t(e)}),n)},t.prototype.replace=function(e,t,n){var i=this,r=this.current;this.transitionTo(e,(function(e){cn(e.fullPath),$t(i.router,e,r,!1),t&&t(e)}),n)},t.prototype.go=function(e){window.history.go(e)},t.prototype.ensureURL=function(e){var t=this.current.fullPath;an()!==t&&(e?ln(t):cn(t))},t.prototype.getCurrentLocation=function(){return an()},t}(Zt);function on(){var e=an();return"/"===e.charAt(0)||(cn("/"+e),!1)}function an(){var e=window.location.href,t=e.indexOf("#");return t<0?"":e=e.slice(t+1)}function sn(e){var t=window.location.href,n=t.indexOf("#");return(n>=0?t.slice(0,n):t)+"#"+e}function ln(e){It?Ft(sn(e)):window.location.hash=e}function cn(e){It?Rt(sn(e)):window.location.replace(sn(e))}var un=function(e){function t(t,n){e.call(this,t,n),this.stack=[],this.index=-1}return e&&(t.__proto__=e),t.prototype=Object.create(e&&e.prototype),t.prototype.constructor=t,t.prototype.push=function(e,t,n){var i=this;this.transitionTo(e,(function(e){i.stack=i.stack.slice(0,i.index+1).concat(e),i.index++,t&&t(e)}),n)},t.prototype.replace=function(e,t,n){var i=this;this.transitionTo(e,(function(e){i.stack=i.stack.slice(0,i.index).concat(e),t&&t(e)}),n)},t.prototype.go=function(e){var t=this,n=this.index+e;if(!(n<0||n>=this.stack.length)){var i=this.stack[n];this.confirmTransition(i,(function(){var e=t.current;t.index=n,t.updateRoute(i),t.router.afterHooks.forEach((function(t){t&&t(i,e)}))}),(function(e){qt(e,Lt.duplicated)&&(t.index=n)}))}},t.prototype.getCurrentLocation=function(){var e=this.stack[this.stack.length-1];return e?e.fullPath:"/"},t.prototype.ensureURL=function(){},t}(Zt),dn=function(e){void 0===e&&(e={}),this.app=null,this.apps=[],this.options=e,this.beforeHooks=[],this.resolveHooks=[],this.afterHooks=[],this.matcher=bt(e.routes||[],this);var t=e.mode||"hash";switch(this.fallback="history"===t&&!It&&!1!==e.fallback,this.fallback&&(t="hash"),pt||(t="abstract"),this.mode=t,t){case"history":this.history=new tn(this,e.base);break;case"hash":this.history=new rn(this,e.base,this.fallback);break;case"abstract":this.history=new un(this,e.base)}},fn={currentRoute:{configurable:!0}};dn.prototype.match=function(e,t,n){return this.matcher.match(e,t,n)},fn.currentRoute.get=function(){return this.history&&this.history.current},dn.prototype.init=function(e){var t=this;if(this.apps.push(e),e.$once("hook:destroyed",(function(){var n=t.apps.indexOf(e);n>-1&&t.apps.splice(n,1),t.app===e&&(t.app=t.apps[0]||null),t.app||t.history.teardown()})),!this.app){this.app=e;var n=this.history;if(n instanceof tn||n instanceof rn){var i=function(e){n.setupListeners(),function(e){var i=n.current,r=t.options.scrollBehavior;It&&r&&"fullPath"in e&&$t(t,e,i,!1)}(e)};n.transitionTo(n.getCurrentLocation(),i,i)}n.listen((function(e){t.apps.forEach((function(t){t._route=e}))}))}},dn.prototype.beforeEach=function(e){return pn(this.beforeHooks,e)},dn.prototype.beforeResolve=function(e){return pn(this.resolveHooks,e)},dn.prototype.afterEach=function(e){return pn(this.afterHooks,e)},dn.prototype.onReady=function(e,t){this.history.onReady(e,t)},dn.prototype.onError=function(e){this.history.onError(e)},dn.prototype.push=function(e,t,n){var i=this;if(!t&&!n&&"undefined"!=typeof Promise)return new Promise((function(t,n){i.history.push(e,t,n)}));this.history.push(e,t,n)},dn.prototype.replace=function(e,t,n){var i=this;if(!t&&!n&&"undefined"!=typeof Promise)return new Promise((function(t,n){i.history.replace(e,t,n)}));this.history.replace(e,t,n)},dn.prototype.go=function(e){this.history.go(e)},dn.prototype.back=function(){this.go(-1)},dn.prototype.forward=function(){this.go(1)},dn.prototype.getMatchedComponents=function(e){var t=e?e.matched?e:this.resolve(e).route:this.currentRoute;return t?[].concat.apply([],t.matched.map((function(e){return Object.keys(e.components).map((function(t){return e.components[t]}))}))):[]},dn.prototype.resolve=function(e,t,n){var i=lt(e,t=t||this.history.current,n,this),r=this.match(i,t),o=r.redirectedFrom||r.fullPath,a=function(e,t,n){var i="hash"===n?"#"+t:t;return e?He(e+"/"+i):i}(this.history.base,o,this.mode);return{location:i,route:r,href:a,normalizedTo:i,resolved:r}},dn.prototype.getRoutes=function(){return this.matcher.getRoutes()},dn.prototype.addRoute=function(e,t){this.matcher.addRoute(e,t),this.history.current!==Ae&&this.history.transitionTo(this.history.getCurrentLocation())},dn.prototype.addRoutes=function(e){this.matcher.addRoutes(e),this.history.current!==Ae&&this.history.transitionTo(this.history.getCurrentLocation())},Object.defineProperties(dn.prototype,fn);var hn=dn;function pn(e,t){return e.push(t),function(){var n=e.indexOf(t);n>-1&&e.splice(n,1)}}dn.install=function e(t){if(!e.installed||ct!==t){e.installed=!0,ct=t;var n=function(e){return void 0!==e},i=function(e,t){var i=e.$options._parentVnode;n(i)&&n(i=i.data)&&n(i=i.registerRouteInstance)&&i(e,t)};t.mixin({beforeCreate:function(){n(this.$options.router)?(this._routerRoot=this,this._router=this.$options.router,this._router.init(this),t.util.defineReactive(this,"_route",this._router.history.current)):this._routerRoot=this.$parent&&this.$parent._routerRoot||this,i(this,this)},destroyed:function(){i(this)}}),Object.defineProperty(t.prototype,"$router",{get:function(){return this._routerRoot._router}}),Object.defineProperty(t.prototype,"$route",{get:function(){return this._routerRoot._route}}),t.component("RouterView",Ve),t.component("RouterLink",dt);var r=t.config.optionMergeStrategies;r.beforeRouteEnter=r.beforeRouteLeave=r.beforeRouteUpdate=r.created}},dn.version="3.6.5",dn.isNavigationFailure=qt,dn.NavigationFailureType=Lt,dn.START_LOCATION=Ae,pt&&window.Vue&&window.Vue.use(dn);var mn=n(1802),vn=n(39903);const gn={$success:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"Success";this.$notify.success({title:t,message:e,position:"bottom-right"})},$fail:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"Error";this.$notify.error({title:t,message:e,position:"bottom-right"})},$warning:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"Warning";this.$notify.warning({title:t,message:e,position:"bottom-right"})},$copy:function(){this.$success(this.$t("Copied to Clipboard."))}};function bn(e){return bn="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},bn(e)}function yn(e,t){for(var n=0;n1&&void 0!==arguments[1]&&arguments[1],n=arguments.length>2&&void 0!==arguments[2]&&arguments[2];e.addClass("active").siblings().removeClass("active"),e.hasClass("has_sub_menu")&&(n?e.find(".ff_list_submenu").show():(e.toggleClass("is-submenu"),e.find(".ff_list_submenu").slideToggle()));var i=e.find("ul.ff_list_submenu li:first");if(i.length&&i.addClass("active").siblings().removeClass("active"),t){var r=e.closest("li.ff_list_button_item");r.length&&r.hasClass("has_sub_menu")&&(n?(r.addClass("active"),r.find(".ff_list_submenu").show()):(r.find(".ff_list_submenu").slideToggle(),r.addClass("is-submenu active")))}e.siblings().hasClass("has_sub_menu")&&(e.siblings().removeClass("is-submenu"),e.siblings().find(".ff_list_submenu").slideUp())};function wn(e,t,n,i,r,o,a,s){var l,c="function"==typeof e?e.options:e;if(t&&(c.render=t,c.staticRenderFns=n,c._compiled=!0),i&&(c.functional=!0),o&&(c._scopeId="data-v-"+o),a?(l=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),r&&r.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(a)},c._ssrRegister=l):r&&(l=s?function(){r.call(this,(c.functional?this.parent:this).$root.$options.shadowRoot)}:r),l)if(c.functional){c._injectStyles=l;var u=c.render;c.render=function(e,t){return l.call(t),u(e,t)}}else{var d=c.beforeCreate;c.beforeCreate=d?[].concat(d,l):[l]}return{exports:e,options:c}}const Cn=wn({name:"photo_widget",props:["value","design_mode","enable_clear"],data:function(){return{app_ready:!1,image_url:this.value,design_mode_name:this.design_mode||"small",enable_clear_name:this.enable_clear,image_name:"",image_size:""}},watch:{image_url:function(){this.$emit("input",this.image_url)}},methods:{initUploader:function(e){var t=this,n=wp.media.editor.send.attachment;return wp.media.editor.send.attachment=function(e,i){t.image_url=i.url,t.image_name=i.filename,t.image_size=i.filesizeHumanReadable,wp.media.editor.send.attachment=n},wp.media.editor.open(),!1}},mounted:function(){window.wpActiveEditor||(window.wpActiveEditor=null),this.app_ready=!0}},(function(){var e=this,t=e._self._c;return e.app_ready?t("div",{staticClass:"ff_file_upload_wrap",class:"ff_photo_"+e.design_mode_name},[t("div",{staticClass:"el-button el-button--upload el-button--default is-plain",on:{click:e.initUploader}},[t("i",{staticClass:"el-icon el-icon-upload"}),e._v(" "),t("span",[e._v(e._s(e.$t("Upload Media")))])]),e._v(" "),e.image_url.length>0?t("div",{staticClass:"mt-2"},[t("div",{staticClass:"ff_file_upload_result"},[t("div",{staticClass:"ff_file_upload_preview"},[t("img",{attrs:{src:e.image_url}})]),e._v(" "),t("div",{staticClass:"ff_file_upload_data"},[t("el-button",{staticClass:"el-button--icon",attrs:{type:"danger",icon:"el-icon-delete",size:"mini"},on:{click:function(t){e.image_url=""}}}),e._v(" "),e.image_name?t("div",{staticClass:"ff_file_upload_description"},[e._v("\n "+e._s(e.image_name)+"\n ")]):e._e(),e._v(" "),e.image_size?t("div",{staticClass:"ff_file_upload_size"},[e._v("\n "+e._s(e.image_size)+"\n ")]):e._e()],1)])]):e._e()]):e._e()}),[],!1,null,null,null).exports;var Sn=wn({name:"PageSettings",props:["settings"],data:function(){return{pages:[],loading_pages:!1}},methods:{fetchPages:function(){var e=this;this.loading_pages=!0,FluentFormsGlobal.$get({action:"fluentform_handle_payment_ajax_endpoint",route:"get_pages"}).then((function(t){e.pages=t.data.pages})).always((function(){e.loading_pages=!1}))}},mounted:function(){this.fetchPages()}},(function(){var e=this,t=e._self._c;return t("div",{staticClass:"ff_pay_page_settings"},[t("el-skeleton",{attrs:{loading:e.loading_pages,animated:"",rows:10}},[t("div",{staticClass:"sub_section_header"},[t("p",[e._v("\n "+e._s(e.$t("FluentForms uses the pages below for handling the display of payment history and payment receipt. Please select the pages and add the instructed shortcodes accordingly."))+" \n "),t("a",{attrs:{target:"_blank",rel:"noopener",href:"https://wpmanageninja.com/docs/fluent-form/payment-settings/payment-management-settings"}},[e._v(e._s(e.$t("Please read the documentation")))]),e._v(" "+e._s(e.$t("for advanced shorcode usage"))+"\n ")]),e._v(" "),t("p",[t("a",{attrs:{target:"_blank",rel:"noopener",href:"https://wpmanageninja.com/docs/fluent-form/payment-settings/accept-recurring-payments-with-wp-fluent-forms-wordpress-plugin/"}},[e._v("\n "+e._s(e.$t("Also please check the documentation")))]),e._v(" "+e._s(e.$t("to learn how to accept"))+" "),t("b",[e._v(" "+e._s(e.$t("Recurring Payments"))+" ")])]),e._v(" "),t("hr",{staticClass:"mt-4 mb-4"})]),e._v(" "),t("el-form-item",{staticClass:"ff-form-item"},[t("template",{slot:"label"},[e._v("\n "+e._s(e.$t("Payment Management Page"))+"\n "),t("el-tooltip",{staticClass:"item",attrs:{placement:"bottom-start","popper-class":"ff_tooltip_wrap"}},[t("div",{attrs:{slot:"content"},slot:"content"},[t("p",[e._v("\n "+e._s(e.$t("This is where user can view their single payments and subscriptions."))+"\n ")])]),e._v(" "),t("i",{staticClass:"ff-icon ff-icon-info-filled text-primary"})])],1),e._v(" "),t("el-select",{staticClass:"w-100",attrs:{clearable:"",filterable:"",placeholder:e.$t("Select Page")},model:{value:e.settings.all_payments_page_id,callback:function(t){e.$set(e.settings,"all_payments_page_id",t)},expression:"settings.all_payments_page_id"}},e._l(e.pages,(function(e){return t("el-option",{key:e.ID,attrs:{label:e.post_title+" ("+e.ID+")",value:e.ID}})})),1),e._v(" "),t("p",{staticClass:"mt-2 text-note"},[e._v("\n "+e._s(e.$t("Add shortcode"))+" "),t("b",[e._v("[fluentform_payments]")]),e._v(" \n "+e._s(e.$t("in the selected page. This shortcode will show single and subscriptions to the logged-in user"))+"\n ")])],2),e._v(" "),t("el-form-item",{staticClass:"ff-form-item"},[t("template",{slot:"label"},[e._v("\n "+e._s(e.$t("Payment Receipt Page"))+"\n "),t("el-tooltip",{staticClass:"item",attrs:{placement:"bottom-start","popper-class":"ff_tooltip_wrap"}},[t("div",{attrs:{slot:"content"},slot:"content"},[t("p",[e._v("\n "+e._s(e.$t("This is where user can view their payment receipt and manage single subscription payment."))+"\n ")])]),e._v(" "),t("i",{staticClass:"ff-icon ff-icon-info-filled text-primary"})])],1),e._v(" "),t("el-select",{staticClass:"w-100",attrs:{clearable:"",filterable:"",placeholder:e.$t("Select Page")},model:{value:e.settings.receipt_page_id,callback:function(t){e.$set(e.settings,"receipt_page_id",t)},expression:"settings.receipt_page_id"}},e._l(e.pages,(function(e){return t("el-option",{key:e.ID,attrs:{label:e.post_title+" ("+e.ID+")",value:e.ID}})})),1),e._v(" "),t("p",{staticClass:"mt-2 text-note"},[e._v(e._s(e.$t("Add shortcode"))+" "),t("b",[e._v("[fluentform_payment_view]")]),e._v(" "+e._s(e.$t("in the selected page.")))])],2),e._v(" "),t("el-form-item",{staticClass:"ff-form-item"},[t("template",{slot:"label"},[e._v("\n "+e._s(e.$t("Subscription Management"))+"\n "),t("el-tooltip",{staticClass:"item",attrs:{placement:"bottom-start","popper-class":"ff_tooltip_wrap"}},[t("div",{attrs:{slot:"content"},slot:"content"},[t("p",[e._v("\n "+e._s(e.$t("Please enable this if you enable users to manage their own subscriptions like cancel an active subscription."))+"\n ")])]),e._v(" "),t("i",{staticClass:"ff-icon ff-icon-info-filled text-primary"})])],1),e._v(" "),t("el-checkbox",{attrs:{"true-label":"yes","false-label":"no"},model:{value:e.settings.user_can_manage_subscription,callback:function(t){e.$set(e.settings,"user_can_manage_subscription",t)},expression:"settings.user_can_manage_subscription"}},[e._v("\n "+e._s(e.$t("Users can manage their own payment subscriptions (only available on Stripe)"))+"\n ")])],2)],1)],1)}),[],!1,null,null,null);const kn=wn({name:"general_payment_settings",props:["settings"],components:{PhotoUploader:Cn,PageSettings:Sn.exports},data:function(){return{currencies:window.ff_payment_settings.currencies,currency_sign_positions:{left:"Left ($100)",right:"Right (100$)",left_space:"Left Space ($ 100)",right_space:"Right Space 100 $"},general_settings:this.settings.general,current_page:"general"}},methods:{saveSettings:function(){var e=this;FluentFormsGlobal.$post({action:"fluentform_handle_payment_ajax_endpoint",route:"update_global_settings",settings:this.general_settings}).then((function(t){e.$success(t.data.message)}))}}},(function(){var e=this,t=e._self._c;return t("div",{staticClass:"ff_payment_general_settings"},[t("ul",{staticClass:"ff_pay_navigation"},[t("li",{class:{ff_active:"general"==e.current_page},on:{click:function(t){e.current_page="general"}}},[e._v("\n "+e._s(e.$t("General"))+"\n ")]),e._v(" "),t("li",{class:{ff_active:"currency"==e.current_page},on:{click:function(t){e.current_page="currency"}}},[e._v("\n "+e._s(e.$t("Currency"))+"\n ")]),e._v(" "),t("li",{class:{ff_active:"pages"==e.current_page},on:{click:function(t){e.current_page="pages"}}},[e._v("\n "+e._s(e.$t("Pages & Subscription Management"))+"\n ")])]),e._v(" "),t("el-form",{attrs:{rel:"currency_settings","label-position":"top",model:e.general_settings}},[t("div",{staticClass:"wpf_settings_section"},["general"==e.current_page?t("div",{staticClass:"ff_pay_section"},[t("el-form-item",{staticClass:"ff-form-item"},[t("template",{slot:"label"},[e._v("\n "+e._s(e.$t("Status"))+"\n "),t("el-tooltip",{staticClass:"item",attrs:{placement:"bottom-start","popper-class":"ff_tooltip_wrap"}},[t("div",{attrs:{slot:"content"},slot:"content"},[t("p",[e._v("\n "+e._s(e.$t("If you disable this then all the payment related functions will be disabled. If you want to process/accept payment using fluent forms. You should enable this."))+"\n ")])]),e._v(" "),t("i",{staticClass:"ff-icon ff-icon-info-filled text-primary"})])],1),e._v(" "),t("el-checkbox",{attrs:{"true-label":"yes","false-label":"no"},model:{value:e.general_settings.status,callback:function(t){e.$set(e.general_settings,"status",t)},expression:"general_settings.status"}},[e._v("\n "+e._s(e.$t("Enable Payment Module"))+"\n ")])],2),e._v(" "),t("el-form-item",{staticClass:"ff-form-item"},[t("template",{slot:"label"},[e._v("\n "+e._s(e.$t("Business Name"))+"\n "),t("el-tooltip",{staticClass:"item",attrs:{placement:"bottom-start","popper-class":"ff_tooltip_wrap"}},[t("div",{attrs:{slot:"content"},slot:"content"},[t("p",[e._v("\n "+e._s(e.$t("Please provide your business name. It will be used to paypal's business name when redirect to checkout."))+"\n ")])]),e._v(" "),t("i",{staticClass:"ff-icon ff-icon-info-filled text-primary"})])],1),e._v(" "),t("el-input",{attrs:{placeholder:e.$t("Business Name")},model:{value:e.general_settings.business_name,callback:function(t){e.$set(e.general_settings,"business_name",t)},expression:"general_settings.business_name"}})],2),e._v(" "),t("el-form-item",{staticClass:"ff-form-item"},[t("template",{slot:"label"},[e._v("\n "+e._s(e.$t("Business Address"))+"\n "),t("el-tooltip",{staticClass:"item",attrs:{placement:"bottom-start","popper-class":"ff_tooltip_wrap"}},[t("div",{attrs:{slot:"content"},slot:"content"},[t("p",[e._v("\n "+e._s(e.$t("Please provide your full business address including street, city, zip, state and country."))+"\n ")])]),e._v(" "),t("i",{staticClass:"ff-icon ff-icon-info-filled text-primary"})])],1),e._v(" "),t("el-input",{attrs:{placeholder:e.$t("Full Business Address")},model:{value:e.general_settings.business_address,callback:function(t){e.$set(e.general_settings,"business_address",t)},expression:"general_settings.business_address"}})],2),e._v(" "),t("el-form-item",{staticClass:"ff-form-item",attrs:{label:e.$t("Business Logo")}},[t("photo-uploader",{attrs:{enable_clear:"yes",design_mode:"horizontal"},model:{value:e.general_settings.business_logo,callback:function(t){e.$set(e.general_settings,"business_logo",t)},expression:"general_settings.business_logo"}})],1),e._v(" "),t("el-form-item",{staticClass:"ff-form-item"},[t("template",{slot:"label"},[e._v("\n "+e._s(e.$t("Debug Log"))+"\n "),t("el-tooltip",{staticClass:"item",attrs:{placement:"bottom-start","popper-class":"ff_tooltip_wrap"}},[t("div",{attrs:{slot:"content"},slot:"content"},[t("p",[e._v("\n "+e._s(e.$t("Enable this only for test purpose, then FluentForm will log IPN and Payment errors in the log"))+"\n ")])]),e._v(" "),t("i",{staticClass:"ff-icon ff-icon-info-filled text-primary"})])],1),e._v(" "),t("el-checkbox",{attrs:{"true-label":"yes","false-label":"no"},model:{value:e.general_settings.debug_log,callback:function(t){e.$set(e.general_settings,"debug_log",t)},expression:"general_settings.debug_log"}},[e._v("\n "+e._s(e.$t("Enable Debug Log (Recommended for debug purpose only)"))+"\n ")])],2)],1):"currency"==e.current_page?t("div",{staticClass:"ff_pay_section"},[t("div",{staticClass:"sub_section_body"},[t("el-form-item",{staticClass:"ff-form-item"},[t("template",{slot:"label"},[e._v("\n "+e._s(e.$t("Default Currency"))+"\n "),t("el-tooltip",{staticClass:"item",attrs:{placement:"bottom-start","popper-class":"ff_tooltip_wrap"}},[t("div",{attrs:{slot:"content"},slot:"content"},[t("p",[e._v("\n "+e._s(e.$t("Provide your default currency. You can also change your currency to each form in form's payment settings"))+"\n ")])]),e._v(" "),t("i",{staticClass:"ff-icon ff-icon-info-filled text-primary"})])],1),e._v(" "),t("el-select",{staticClass:"w-100",attrs:{filterable:"",placeholder:e.$t("Select Currency")},model:{value:e.general_settings.currency,callback:function(t){e.$set(e.general_settings,"currency",t)},expression:"general_settings.currency"}},e._l(e.currencies,(function(e,n){return t("el-option",{key:n,attrs:{label:e,value:n}})})),1)],2),e._v(" "),t("el-form-item",{staticClass:"ff-form-item",attrs:{label:e.$t("Currency Sign Position")}},[t("el-radio-group",{model:{value:e.general_settings.currency_sign_position,callback:function(t){e.$set(e.general_settings,"currency_sign_position",t)},expression:"general_settings.currency_sign_position"}},e._l(e.currency_sign_positions,(function(n,i){return t("el-radio",{key:i,attrs:{label:i}},[e._v(e._s(n)+"\n ")])})),1)],1),e._v(" "),t("el-form-item",{staticClass:"ff-form-item",attrs:{label:e.$t("Currency Separators")}},[t("el-select",{staticClass:"w-100",model:{value:e.general_settings.currency_separator,callback:function(t){e.$set(e.general_settings,"currency_separator",t)},expression:"general_settings.currency_separator"}},[t("el-option",{attrs:{value:"dot_comma",label:e.$t("Comma as Thousand and Dot as Decimal (EG: 12,000.00)")}}),e._v(" "),t("el-option",{attrs:{value:"comma_dot",label:e.$t("Dot as Thousand and Comma as Decimal ( EG: 12.000,00 )")}})],1)],1),e._v(" "),t("el-form-item",{staticClass:"ff-form-item",attrs:{label:""}},[t("el-checkbox",{attrs:{"true-label":"0","false-label":"2"},model:{value:e.general_settings.decimal_points,callback:function(t){e.$set(e.general_settings,"decimal_points",t)},expression:"general_settings.decimal_points"}},[e._v("\n "+e._s(e.$t("Hide decimal points for rounded numbers"))+"\n ")])],1)],1)]):"pages"==e.current_page?t("div",{staticClass:"ff_pay_section"},[t("page-settings",{attrs:{settings:e.general_settings}})],1):e._e()])]),e._v(" "),"no"==e.general_settings.status?t("div",{staticClass:"ff_tips_error"},[t("p",[e._v("\n "+e._s(e.$t("Payment Module has been disabled currently. No Payments will be processed and associated functions will be disabled"))+"\n ")])]):e._e(),e._v(" "),t("div",{staticClass:"mt-4"},[t("el-button",{attrs:{type:"primary",size:"medium",icon:"el-icon-success"},on:{click:function(t){return e.saveSettings()}}},[e._v("\n "+e._s(e.$t("Save Settings"))+"\n ")])],1)],1)}),[],!1,null,null,null).exports;const On={name:"Pagination",props:{pagination:{required:!0,type:Object},storePerPageAs:{required:!1,type:String}},computed:{page_sizes:function(){var e=[];this.pagination.per_page<10&&e.push(this.pagination.per_page);return[].concat(e,[10,20,50,80,100,120,150])}},methods:{changePage:function(e){this.pagination.current_page=e,this.fetch()},changeSize:function(e){this.pagination.per_page=e,this.storePerPageAs&&localStorage.setItem(this.storePerPageAs,e),this.fetch()},fetch:function(){var e=this;(function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:300;return jQuery(arguments.length>2&&void 0!==arguments[2]?arguments[2]:"html, body").animate({scrollTop:e},t).promise()})().then((function(t){e.$emit("fetch")}))}}};const $n=wn(On,(function(){var e=this;return(0,e._self._c)("el-pagination",{staticClass:"ff_pagination",attrs:{background:"",layout:"total, sizes, prev, pager, next","current-page":e.pagination.current_page,"page-sizes":e.page_sizes,"page-size":parseInt(e.pagination.per_page),total:e.pagination.total},on:{"current-change":e.changePage,"size-change":e.changeSize,"update:currentPage":function(t){return e.$set(e.pagination,"current_page",t)},"update:current-page":function(t){return e.$set(e.pagination,"current_page",t)}}})}),[],!1,null,null,null).exports;const jn=wn({name:"errorView",props:["field","errors"]},(function(){var e=this,t=e._self._c;return e.errors.has(e.field)?t("div",{staticClass:"el-form-item__error"},[t("p",[e._v(e._s(e.errors.first(e.field)))])]):e._e()}),[],!1,null,null,null).exports;const Mn=wn({name:"confirmRemove",props:["text"],data:function(){return{visible:!1}},methods:{confirmAction:function(){this.visible=!1,this.$emit("on-confirm")}}},(function(){var e=this,t=e._self._c;return t("span",[t("el-popover",{ref:"popover",attrs:{placement:"top",width:190},model:{value:e.visible,callback:function(t){e.visible=t},expression:"visible"}},[t("p",{staticClass:"text-right"},[e._v(e._s(e.$t("Are you sure to delete this?")))]),e._v(" "),t("div",{staticClass:"text-right"},[t("el-button",{staticClass:"el-button--soft",attrs:{size:"mini",type:"info"},on:{click:function(t){e.visible=!1}}},[e._v("\n "+e._s(e.$t("Cancel"))+"\n ")]),e._v(" "),t("el-button",{attrs:{type:"danger",size:"mini"},on:{click:e.confirmAction}},[e._v("\n "+e._s(e.$t("Confirm"))+"\n ")])],1)]),e._v(" "),t("span",{directives:[{name:"popover",rawName:"v-popover:popover",arg:"popover"}]},[e._t("default",(function(){return[t("i",{staticClass:"el-icon el-icon-delete",staticStyle:{cursor:"pointer"}})]}))],2)],1)}),[],!1,null,null,null).exports;const Tn=wn({name:"CardHead"},(function(){return(0,this._self._c)("div",{staticClass:"ff_card_head"},[this._t("default")],2)}),[],!1,null,null,null).exports;var Dn=wn({name:"CardHeadGroup"},(function(){return(0,this._self._c)("div",{staticClass:"ff_card_head_group"},[this._t("default")],2)}),[],!1,null,null,null);const En=wn({name:"CouponSettings",components:{Pagination:$n,Confirm:Mn,ErrorView:jn,CardHead:Tn,CardHeadGroup:Dn.exports},data:function(){return{loading:!1,saving:!1,coupons:[],coupon_status:!0,pagination:{total:0,current_page:1,last_page:1,per_page:localStorage.getItem("couponsPerPage")||10},editing_coupon:{},show_modal:!1,available_forms:{},errors:new Errors,failure_type:"Inactive"}},methods:{getCoupons:function(){var e=this;this.loading=!0,FluentFormsGlobal.$get({action:"fluentform_handle_payment_ajax_endpoint",route:"get_coupons",page:this.pagination.current_page,per_page:this.pagination.per_page}).then((function(t){e.coupon_status=t.coupon_status,t.coupon_status&&(e.coupons=t.coupons.data,e.pagination.total=t.coupons.total,e.pagination.last_page=t.coupons.last_page,e.pagination.per_page=t.coupons.per_page||localStorage.getItem("couponsPerPage")||10,t.available_forms&&(e.available_forms=t.available_forms))})).fail((function(t){e.$fail(t.responseJSON.message)})).always((function(){e.loading=!1}))},enableCouponModule:function(){var e=this;this.loading=!0,FluentFormsGlobal.$post({action:"fluentform_handle_payment_ajax_endpoint",route:"enable_coupons"}).then((function(t){e.coupon_status=t.coupon_status,e.getCoupons()})).fail((function(t){e.$fail(t.responseJSON.message)})).always((function(){e.loading=!1}))},showAddCoupon:function(){this.errors.clear(),this.editing_coupon={title:"",code:"",amount:"",coupon_type:"percent",status:"active",stackable:"no",settings:{allowed_form_ids:[],coupon_limit:0,success_message:"{coupon.code} - {coupon.amount}",failed_message:{inactive:"The provided coupon is not valid",min_amount:"The provided coupon does not meet the requirements",stackable:"Sorry, you can not apply this coupon with other coupon code",date_expire:"The provided coupon is not valid",allowed_form:"The provided coupon is not valid",limit:"The provided coupon is not valid"}},min_amount:"",max_use:"",start_date:"",expire_date:""},this.show_modal=!0},saveCoupon:function(){var e=this;this.saving=!0,FluentFormsGlobal.$post({action:"fluentform_handle_payment_ajax_endpoint",route:"save_coupon",coupon:this.editing_coupon}).then((function(t){e.getCoupons(),e.show_modal=!1,e.editing_coupon={},e.$success(t.message)})).fail((function(t){e.$fail(t.responseJSON.message),e.errors.record(t.responseJSON.errors)})).always((function(){e.saving=!1}))},editCoupon:function(e){var t=this;this.errors.clear();var n=JSON.parse(JSON.stringify(e));n.settings=n.settings||{},n.settings.allowed_form_ids=n.settings.allowed_form_ids||[],n.settings.failed_message=n.settings.failed_message||{inactive:"The provided coupon is not valid",min_amount:"The provided coupon does not meet the requirements",stackable:"Sorry, you can not apply this coupon with other coupon code",date_expire:"The provided coupon is not valid",allowed_form:"The provided coupon is not valid",limit:"The provided coupon is not valid"},n.settings.success_message=n.settings.success_message||"{coupon.code} - {coupon.amount}",this.$set(this,"editing_coupon",n),this.$nextTick((function(){t.show_modal=!0}))},deleteCoupon:function(e){var t=this;this.loading=!0,FluentFormsGlobal.$post({action:"fluentform_handle_payment_ajax_endpoint",route:"delete_coupon",coupon_id:e.id}).then((function(e){t.getCoupons(),t.$success(e.message)})).fail((function(e){})).always((function(){t.loading=!1}))}},mounted:function(){this.getCoupons()}},(function(){var e=this,t=e._self._c;return t("div",{staticClass:"ff_method_settings"},[t("el-skeleton",{attrs:{loading:e.loading,animated:"",rows:10}},[e.coupon_status?t("div",[t("card-head",[t("card-head-group",{staticClass:"justify-between"},[t("h5",{staticClass:"title"},[e._v(e._s(e.$t("Available Coupons")))]),e._v(" "),t("el-button",{attrs:{type:"info",size:"medium",icon:"ff-icon ff-icon-plus"},on:{click:function(t){return e.showAddCoupon()}}},[e._v("\n "+e._s(e.$t("Add New Coupon"))+"\n ")])],1)],1),e._v(" "),t("el-table",{staticClass:"ff_table_s2",attrs:{data:e.coupons}},[t("el-table-column",{attrs:{width:"100",label:e.$t("ID"),prop:"id"}}),e._v(" "),t("el-table-column",{attrs:{label:e.$t("Title"),prop:"title"}}),e._v(" "),t("el-table-column",{attrs:{label:e.$t("Code"),prop:"code"}}),e._v(" "),t("el-table-column",{attrs:{width:"140",label:e.$t("Amount")},scopedSlots:e._u([{key:"default",fn:function(n){return[e._v("\n "+e._s(n.row.amount)),"percent"==n.row.coupon_type?t("span",[e._v("%")]):e._e()]}}])}),e._v(" "),t("el-table-column",{attrs:{width:"90",label:e.$t("Actions")},scopedSlots:e._u([{key:"default",fn:function(n){return[t("el-button",{staticClass:"el-button--icon",attrs:{size:"mini",type:"info",icon:"ff-icon-edit"},on:{click:function(t){return e.editCoupon(n.row)}}}),e._v(" "),t("confirm",{on:{"on-confirm":function(t){return e.deleteCoupon(n.row)}}},[t("el-button",{staticClass:"el-button--icon",attrs:{size:"mini",type:"danger",icon:"ff-icon-trash"}})],1)]}}])})],1),e._v(" "),t("div",{staticClass:"ff_pagination_wrap text-right mt-4"},[t("pagination",{attrs:{pagination:e.pagination,storePerPageAs:"couponsPerPage"},on:{fetch:e.getCoupons}})],1)],1):t("div",{staticClass:"ff_pre_settings_wrapper"},[t("h2",{staticClass:"mb-3"},[e._v("\n "+e._s(e.$t("Fluent Forms Coupon Module"))+"\n ")]),e._v(" "),t("p",[e._v("\n "+e._s(e.$t("Enable your users to apply coupon/discount code while purchasing something using Fluent Forms Payment Module. Just activate this module and setup your coupons."))+"\n ")]),e._v(" "),t("el-button",{attrs:{type:"primary",icon:"el-icon-success"},on:{click:function(t){return e.enableCouponModule()}}},[e._v("\n "+e._s(e.$t("Enable Coupon Module"))+"\n ")])],1),e._v(" "),t("el-dialog",{attrs:{top:"40px",visible:e.show_modal,"append-to-body":!0,width:"60%"},on:{"update:visible":function(t){e.show_modal=t}}},[t("template",{slot:"title"},[t("h4",[e._v(e._s(e.editing_coupon.id?e.$t("Edit Coupon"):e.$t("Add a new Coupon")))])]),e._v(" "),e.show_modal?t("div",{staticClass:"ff_coupon_form mt-4"},[t("el-form",{attrs:{data:e.editing_coupon,"label-position":"top"}},[t("el-form-item",{staticClass:"ff-form-item",attrs:{label:e.$t("Coupon Title")}},[t("el-input",{attrs:{type:"text",placeholder:e.$t("Coupon Title")},model:{value:e.editing_coupon.title,callback:function(t){e.$set(e.editing_coupon,"title",t)},expression:"editing_coupon.title"}}),e._v(" "),t("p",{staticClass:"mt-1 text-note"},[e._v(e._s(e.$t("The name of this discount")))]),e._v(" "),t("error-view",{attrs:{field:"title",errors:e.errors}})],1),e._v(" "),t("el-form-item",{staticClass:"ff-form-item",attrs:{label:e.$t("Coupon Code")}},[t("el-input",{attrs:{type:"text",placeholder:e.$t("Coupon Code")},model:{value:e.editing_coupon.code,callback:function(t){e.$set(e.editing_coupon,"code",t)},expression:"editing_coupon.code"}}),e._v(" "),t("p",{staticClass:"mt-1 text-note"},[e._v(e._s(e.$t("Enter a code for this discount, such as 10PERCENT. Only alphanumeric characters are allowed.")))]),e._v(" "),t("error-view",{attrs:{field:"code",errors:e.errors}})],1),e._v(" "),t("el-row",{attrs:{gutter:30}},[t("el-col",{attrs:{span:12}},[t("el-form-item",{staticClass:"ff-form-item",attrs:{label:e.$t("Discount Amount / Percent")}},[t("el-input",{attrs:{placeholder:e.$t("Discount Amount / Percent"),type:"number",min:0},model:{value:e.editing_coupon.amount,callback:function(t){e.$set(e.editing_coupon,"amount",t)},expression:"editing_coupon.amount"}}),e._v(" "),"percent"==e.editing_coupon.coupon_type?t("p",{staticClass:"mt-1 text-note"},[e._v(e._s(e.$t("Enter the discount percentage. 10 = 10%")))]):e._e(),e._v(" "),t("error-view",{attrs:{field:"amount",errors:e.errors}})],1)],1),e._v(" "),t("el-col",{attrs:{span:12}},[t("el-form-item",{staticClass:"ff-form-item",attrs:{label:e.$t("Discount Type")}},[t("el-radio-group",{model:{value:e.editing_coupon.coupon_type,callback:function(t){e.$set(e.editing_coupon,"coupon_type",t)},expression:"editing_coupon.coupon_type"}},[t("el-radio",{attrs:{label:"percent"}},[e._v(e._s(e.$t("Percent based discount")))]),e._v(" "),t("el-radio",{attrs:{label:"fixed"}},[e._v(e._s(e.$t("Fixed Discount")))])],1),e._v(" "),t("p",{staticClass:"mt-4 text-note"},[e._v(e._s(e.$t("The kind of discount to apply for this discount.")))]),e._v(" "),t("error-view",{attrs:{field:"coupon_type",errors:e.errors}})],1)],1)],1),e._v(" "),t("el-row",{attrs:{gutter:30}},[t("el-col",{attrs:{span:12}},[t("el-form-item",{staticClass:"ff-form-item",attrs:{label:e.$t("Min Purchase Amount")}},[t("el-input",{attrs:{placeholder:e.$t("Min Purchase Amount"),type:"number",min:0},model:{value:e.editing_coupon.min_amount,callback:function(t){e.$set(e.editing_coupon,"min_amount",t)},expression:"editing_coupon.min_amount"}}),e._v(" "),t("p",{staticClass:"mt-1 text-note"},[e._v(e._s(e.$t("The minimum amount that must be purchased before this discount can be used. Leave blank for no minimum.")))])],1)],1),e._v(" "),t("el-col",{attrs:{span:12}},[t("el-form-item",{staticClass:"ff-form-item",attrs:{label:e.$t("Stackable")}},[t("el-radio-group",{model:{value:e.editing_coupon.stackable,callback:function(t){e.$set(e.editing_coupon,"stackable",t)},expression:"editing_coupon.stackable"}},[t("el-radio",{attrs:{label:"yes"}},[e._v(e._s(e.$t("Yes")))]),e._v(" "),t("el-radio",{attrs:{label:"no"}},[e._v(e._s(e.$t("No")))])],1),e._v(" "),t("p",{staticClass:"mt-4 text-note"},[e._v(e._s(e.$t("Can this coupon code can be used with other coupon code")))])],1)],1)],1),e._v(" "),t("el-row",{attrs:{gutter:30}},[t("el-col",{attrs:{span:12}},[t("el-form-item",{staticClass:"ff-form-item",attrs:{label:e.$t("Start Date")}},[t("el-date-picker",{staticClass:"w-100",attrs:{"value-format":"yyyy-MM-dd",format:"yyyy-MM-dd",placeholder:e.$t("Start Date")},model:{value:e.editing_coupon.start_date,callback:function(t){e.$set(e.editing_coupon,"start_date",t)},expression:"editing_coupon.start_date"}}),e._v(" "),t("p",{staticClass:"mt-1 text-note"},[e._v("\n "+e._s(e.$t("Enter the start date for this discount code in the format of yyyy-mm-dd. For no start date, leave blank."))+"\n ")])],1)],1),e._v(" "),t("el-col",{attrs:{span:12}},[t("el-form-item",{staticClass:"ff-form-item",attrs:{label:e.$t("End Date")}},[t("el-date-picker",{staticClass:"w-100",attrs:{"value-format":"yyyy-MM-dd",format:"yyyy-MM-dd",placeholder:e.$t("End Date")},model:{value:e.editing_coupon.expire_date,callback:function(t){e.$set(e.editing_coupon,"expire_date",t)},expression:"editing_coupon.expire_date"}}),e._v(" "),t("p",{staticClass:"mt-1 text-note"},[e._v("\n "+e._s(e.$t("Enter the expiration date for this discount code in the format of yyyy-mm-dd. For no expiration, leave blank"))+"\n ")])],1)],1)],1),e._v(" "),t("el-form-item",{staticClass:"ff-form-item",attrs:{label:e.$t("Applicable Forms")}},[t("el-select",{staticStyle:{width:"100%"},attrs:{placeholer:"Select Forms",multiple:""},model:{value:e.editing_coupon.settings.allowed_form_ids,callback:function(t){e.$set(e.editing_coupon.settings,"allowed_form_ids",t)},expression:"editing_coupon.settings.allowed_form_ids"}},e._l(e.available_forms,(function(e,n){return t("el-option",{key:n,attrs:{label:e,value:n}})})),1),e._v(" "),t("p",{staticClass:"mt-1 text-note"},[e._v(e._s(e.$t("Leave blank for applicable for all payment forms")))])],1),e._v(" "),t("el-form-item",{staticClass:"ff-form-item",attrs:{label:e.$t("Coupon Limit")}},[t("el-input",{attrs:{placeholder:e.$t("Coupon Limit"),type:"number",min:0},model:{value:e.editing_coupon.settings.coupon_limit,callback:function(t){e.$set(e.editing_coupon.settings,"coupon_limit",t)},expression:"editing_coupon.settings.coupon_limit"}}),e._v(" "),t("p",{staticClass:"mt-1 text-note"},[e._v("\n "+e._s(e.$t("Set the limit for how many times a logged-in user can apply this coupon. Keep this empty or put zero for no limit."))+"\n ")])],1),e._v(" "),t("el-form-item",{staticClass:"ff-form-item",attrs:{label:e.$t("Success Message")}},[t("el-input",{attrs:{placeholder:e.$t("Success Message")},model:{value:e.editing_coupon.settings.success_message,callback:function(t){e.$set(e.editing_coupon.settings,"success_message",t)},expression:"editing_coupon.settings.success_message"}}),e._v(" "),t("p",{staticClass:"mt-1 text-note"},[e._v("\n "+e._s(e.$t("Set the success message for coupon. You can use {coupon.code}, {coupon.amount}, {total_amount}, {discount_amount} and {remain_amount} smartcodes."))+"\n ")])],1),e._v(" "),t("el-form-item",{staticClass:"ff-form-item",attrs:{label:e.$t("Failed Message")}},[t("el-radio-group",{staticClass:"mb-3",model:{value:e.failure_type,callback:function(t){e.failure_type=t},expression:"failure_type"}},[t("el-radio",{attrs:{label:"Inactive"}},[e._v(e._s(e.$t("Inactive Coupon")))]),e._v(" "),t("el-radio",{attrs:{label:"Minimum Amount"}},[e._v(e._s(e.$t("Minimum Amount")))]),e._v(" "),t("el-radio",{attrs:{label:"Stackable"}},[e._v(e._s(e.$t("Stackable")))]),e._v(" "),t("el-radio",{attrs:{label:"Limit"}},[e._v(e._s(e.$t("Limit Crossed")))]),e._v(" "),t("el-radio",{attrs:{label:"Date Expire"}},[e._v(e._s(e.$t("Date Expired")))]),e._v(" "),t("el-radio",{attrs:{label:"Allowed Form"}},[e._v(e._s(e.$t("Allowed Form")))])],1),e._v(" "),"Inactive"===e.failure_type?t("el-input",{attrs:{placeholder:e.$t("Inactive Coupon Failure Message")},model:{value:e.editing_coupon.settings.failed_message.inactive,callback:function(t){e.$set(e.editing_coupon.settings.failed_message,"inactive",t)},expression:"editing_coupon.settings.failed_message.inactive"}}):e._e(),e._v(" "),"Minimum Amount"===e.failure_type?t("el-input",{attrs:{placeholder:e.$t("Minimum Amount Failure Message")},model:{value:e.editing_coupon.settings.failed_message.min_amount,callback:function(t){e.$set(e.editing_coupon.settings.failed_message,"min_amount",t)},expression:"editing_coupon.settings.failed_message.min_amount"}}):e._e(),e._v(" "),"Stackable"===e.failure_type?t("el-input",{attrs:{placeholder:e.$t("Stackable Failure Message")},model:{value:e.editing_coupon.settings.failed_message.stackable,callback:function(t){e.$set(e.editing_coupon.settings.failed_message,"stackable",t)},expression:"editing_coupon.settings.failed_message.stackable"}}):e._e(),e._v(" "),"Limit"===e.failure_type?t("el-input",{attrs:{placeholder:e.$t("Limit Failure Message")},model:{value:e.editing_coupon.settings.failed_message.limit,callback:function(t){e.$set(e.editing_coupon.settings.failed_message,"limit",t)},expression:"editing_coupon.settings.failed_message.limit"}}):e._e(),e._v(" "),"Date Expire"===e.failure_type?t("el-input",{attrs:{placeholder:e.$t("Date Expired Message")},model:{value:e.editing_coupon.settings.failed_message.date_expire,callback:function(t){e.$set(e.editing_coupon.settings.failed_message,"date_expire",t)},expression:"editing_coupon.settings.failed_message.date_expire"}}):e._e(),e._v(" "),"Allowed Form"===e.failure_type?t("el-input",{attrs:{placeholder:e.$t("Allowed Form")},model:{value:e.editing_coupon.settings.failed_message.allowed_form,callback:function(t){e.$set(e.editing_coupon.settings.failed_message,"allowed_form",t)},expression:"editing_coupon.settings.failed_message.allowed_form"}}):e._e(),e._v(" "),t("p",{staticClass:"mt-1 text-note"},[e._v("\n "+e._s(e.$t("Set different failed message for coupon."))+"\n ")])],1),e._v(" "),t("el-form-item",{staticClass:"ff-form-item",attrs:{label:e.$t("Status")}},[t("el-radio-group",{staticClass:"el-radio-group-info",model:{value:e.editing_coupon.status,callback:function(t){e.$set(e.editing_coupon,"status",t)},expression:"editing_coupon.status"}},[t("el-radio-button",{attrs:{label:"active"}},[e._v(e._s(e.$t("Active")))]),e._v(" "),t("el-radio-button",{attrs:{label:"inactive"}},[e._v(e._s(e.$t("Inactive")))])],1),e._v(" "),t("error-view",{attrs:{field:"status",errors:e.errors}})],1)],1)],1):e._e(),e._v(" "),t("div",{staticClass:"dialog-footer has-separator",attrs:{slot:"footer"},slot:"footer"},[t("el-button",{staticClass:"el-button--soft",attrs:{type:"info"},on:{click:function(t){e.show_modal=!1}}},[e._v("\n "+e._s(e.$t("Cancel"))+"\n ")]),e._v(" "),t("el-button",{directives:[{name:"loading",rawName:"v-loading",value:e.saving,expression:"saving"}],attrs:{type:"primary"},on:{click:function(t){return e.saveCoupon()}}},[e._v("\n "+e._s(e.$t("Save Coupon"))+"\n ")])],1)],2)],1)],1)}),[],!1,null,null,null).exports;function Pn(e){return function(e){if(Array.isArray(e))return An(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(!e)return;if("string"==typeof e)return An(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return An(e,t)}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function An(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,i=new Array(t);n`Missing ${e} property in key`,Qn=e=>`Property 'weight' in key '${e}' must be a positive integer`,ei=Object.prototype.hasOwnProperty;class ti{constructor(e){this._keys=[],this._keyMap={};let t=0;e.forEach((e=>{let n=ni(e);t+=n.weight,this._keys.push(n),this._keyMap[n.id]=n,t+=n.weight})),this._keys.forEach((e=>{e.weight/=t}))}get(e){return this._keyMap[e]}keys(){return this._keys}toJSON(){return JSON.stringify(this._keys)}}function ni(e){let t=null,n=null,i=null,r=1,o=null;if(qn(e)||Bn(e))i=e,t=ii(e),n=ri(e);else{if(!ei.call(e,"name"))throw new Error(Zn("name"));const a=e.name;if(i=a,ei.call(e,"weight")&&(r=e.weight,r<=0))throw new Error(Qn(a));t=ii(a),n=ri(a),o=e.getFn}return{path:t,id:n,weight:r,src:i,getFn:o}}function ii(e){return Bn(e)?e:e.split(".")}function ri(e){return Bn(e)?e.join("."):e}var oi={isCaseSensitive:!1,includeScore:!1,keys:[],shouldSort:!0,sortFn:(e,t)=>e.score===t.score?e.idx{if(Gn(e))if(t[o]){const a=e[t[o]];if(!Gn(a))return;if(o===t.length-1&&(qn(a)||Un(a)||Yn(a)))n.push(Wn(a));else if(Bn(a)){i=!0;for(let e=0,n=a.length;e{this._keysMap[e.id]=t}))}create(){!this.isCreated&&this.docs.length&&(this.isCreated=!0,qn(this.docs[0])?this.docs.forEach(((e,t)=>{this._addString(e,t)})):this.docs.forEach(((e,t)=>{this._addObject(e,t)})),this.norm.clear())}add(e){const t=this.size();qn(e)?this._addString(e,t):this._addObject(e,t)}removeAt(e){this.records.splice(e,1);for(let t=e,n=this.size();t{let r=t.getFn?t.getFn(e):this.getFn(e,t.path);if(Gn(r))if(Bn(r)){let e=[];const t=[{nestedArrIndex:-1,value:r}];for(;t.length;){const{nestedArrIndex:n,value:i}=t.pop();if(Gn(i))if(qn(i)&&!Xn(i)){let t={v:i,i:n,n:this.norm.get(i)};e.push(t)}else Bn(i)&&i.forEach(((e,n)=>{t.push({nestedArrIndex:n,value:e})}))}n.$[i]=e}else if(qn(r)&&!Xn(r)){let e={v:r,n:this.norm.get(r)};n.$[i]=e}})),this.records.push(n)}toJSON(){return{keys:this.keys,records:this.records}}}function li(e,t,{getFn:n=oi.getFn,fieldNormWeight:i=oi.fieldNormWeight}={}){const r=new si({getFn:n,fieldNormWeight:i});return r.setKeys(e.map(ni)),r.setSources(t),r.create(),r}function ci(e,{errors:t=0,currentLocation:n=0,expectedLocation:i=0,distance:r=oi.distance,ignoreLocation:o=oi.ignoreLocation}={}){const a=t/e.length;if(o)return a;const s=Math.abs(i-n);return r?a+s/r:s?1:a}const ui=32;function di(e,t,n,{location:i=oi.location,distance:r=oi.distance,threshold:o=oi.threshold,findAllMatches:a=oi.findAllMatches,minMatchCharLength:s=oi.minMatchCharLength,includeMatches:l=oi.includeMatches,ignoreLocation:c=oi.ignoreLocation}={}){if(t.length>ui)throw new Error(`Pattern length exceeds max of ${ui}.`);const u=t.length,d=e.length,f=Math.max(0,Math.min(i,d));let h=o,p=f;const m=s>1||l,v=m?Array(d):[];let g;for(;(g=e.indexOf(t,p))>-1;){let e=ci(t,{currentLocation:g,expectedLocation:f,distance:r,ignoreLocation:c});if(h=Math.min(e,h),p=g+u,m){let e=0;for(;e=l;o-=1){let a=o-1,s=n[e.charAt(a)];if(m&&(v[a]=+!!s),w[o]=(w[o+1]<<1|1)&s,i&&(w[o]|=(b[o+1]|b[o])<<1|1|b[o+1]),w[o]&x&&(y=ci(t,{errors:i,currentLocation:a,expectedLocation:f,distance:r,ignoreLocation:c}),y<=h)){if(h=y,p=a,p<=f)break;l=Math.max(1,2*f-p)}}if(ci(t,{errors:i+1,currentLocation:f,expectedLocation:f,distance:r,ignoreLocation:c})>h)break;b=w}const w={isMatch:p>=0,score:Math.max(.001,y)};if(m){const e=function(e=[],t=oi.minMatchCharLength){let n=[],i=-1,r=-1,o=0;for(let a=e.length;o=t&&n.push([i,r]),i=-1)}return e[o-1]&&o-i>=t&&n.push([i,o-1]),n}(v,s);e.length?l&&(w.indices=e):w.isMatch=!1}return w}function fi(e){let t={};for(let n=0,i=e.length;n{this.chunks.push({pattern:e,alphabet:fi(e),startIndex:t})},u=this.pattern.length;if(u>ui){let e=0;const t=u%ui,n=u-t;for(;e{const{isMatch:p,score:m,indices:v}=di(e,t,f,{location:i+h,distance:r,threshold:o,findAllMatches:a,minMatchCharLength:s,includeMatches:n,ignoreLocation:l});p&&(d=!0),u+=m,p&&v&&(c=[...c,...v])}));let f={isMatch:d,score:d?u/this.chunks.length:1};return d&&n&&(f.indices=c),f}}class pi{constructor(e){this.pattern=e}static isMultiMatch(e){return mi(e,this.multiRegex)}static isSingleMatch(e){return mi(e,this.singleRegex)}search(){}}function mi(e,t){const n=e.match(t);return n?n[1]:null}class vi extends pi{constructor(e,{location:t=oi.location,threshold:n=oi.threshold,distance:i=oi.distance,includeMatches:r=oi.includeMatches,findAllMatches:o=oi.findAllMatches,minMatchCharLength:a=oi.minMatchCharLength,isCaseSensitive:s=oi.isCaseSensitive,ignoreLocation:l=oi.ignoreLocation}={}){super(e),this._bitapSearch=new hi(e,{location:t,threshold:n,distance:i,includeMatches:r,findAllMatches:o,minMatchCharLength:a,isCaseSensitive:s,ignoreLocation:l})}static get type(){return"fuzzy"}static get multiRegex(){return/^"(.*)"$/}static get singleRegex(){return/^(.*)$/}search(e){return this._bitapSearch.searchIn(e)}}class gi extends pi{constructor(e){super(e)}static get type(){return"include"}static get multiRegex(){return/^'"(.*)"$/}static get singleRegex(){return/^'(.*)$/}search(e){let t,n=0;const i=[],r=this.pattern.length;for(;(t=e.indexOf(this.pattern,n))>-1;)n=t+r,i.push([t,n-1]);const o=!!i.length;return{isMatch:o,score:o?0:1,indices:i}}}const bi=[class extends pi{constructor(e){super(e)}static get type(){return"exact"}static get multiRegex(){return/^="(.*)"$/}static get singleRegex(){return/^=(.*)$/}search(e){const t=e===this.pattern;return{isMatch:t,score:t?0:1,indices:[0,this.pattern.length-1]}}},gi,class extends pi{constructor(e){super(e)}static get type(){return"prefix-exact"}static get multiRegex(){return/^\^"(.*)"$/}static get singleRegex(){return/^\^(.*)$/}search(e){const t=e.startsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,this.pattern.length-1]}}},class extends pi{constructor(e){super(e)}static get type(){return"inverse-prefix-exact"}static get multiRegex(){return/^!\^"(.*)"$/}static get singleRegex(){return/^!\^(.*)$/}search(e){const t=!e.startsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}},class extends pi{constructor(e){super(e)}static get type(){return"inverse-suffix-exact"}static get multiRegex(){return/^!"(.*)"\$$/}static get singleRegex(){return/^!(.*)\$$/}search(e){const t=!e.endsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}},class extends pi{constructor(e){super(e)}static get type(){return"suffix-exact"}static get multiRegex(){return/^"(.*)"\$$/}static get singleRegex(){return/^(.*)\$$/}search(e){const t=e.endsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[e.length-this.pattern.length,e.length-1]}}},class extends pi{constructor(e){super(e)}static get type(){return"inverse-exact"}static get multiRegex(){return/^!"(.*)"$/}static get singleRegex(){return/^!(.*)$/}search(e){const t=-1===e.indexOf(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}},vi],yi=bi.length,_i=/ +(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/;const xi=new Set([vi.type,gi.type]);class wi{constructor(e,{isCaseSensitive:t=oi.isCaseSensitive,includeMatches:n=oi.includeMatches,minMatchCharLength:i=oi.minMatchCharLength,ignoreLocation:r=oi.ignoreLocation,findAllMatches:o=oi.findAllMatches,location:a=oi.location,threshold:s=oi.threshold,distance:l=oi.distance}={}){this.query=null,this.options={isCaseSensitive:t,includeMatches:n,minMatchCharLength:i,findAllMatches:o,ignoreLocation:r,location:a,threshold:s,distance:l},this.pattern=t?e:e.toLowerCase(),this.query=function(e,t={}){return e.split("|").map((e=>{let n=e.trim().split(_i).filter((e=>e&&!!e.trim())),i=[];for(let e=0,r=n.length;e!(!e[ki]&&!e[Oi]),Ti=e=>({[ki]:Object.keys(e).map((t=>({[t]:e[t]})))});function Di(e,t,{auto:n=!0}={}){const i=e=>{let r=Object.keys(e);const o=(e=>!!e[$i])(e);if(!o&&r.length>1&&!Mi(e))return i(Ti(e));if((e=>!Bn(e)&&Kn(e)&&!Mi(e))(e)){const i=o?e[$i]:r[0],a=o?e[ji]:e[i];if(!qn(a))throw new Error((e=>`Invalid value for key ${e}`)(i));const s={keyId:ri(i),pattern:a};return n&&(s.searcher=Si(a,t)),s}let a={children:[],operator:r[0]};return r.forEach((t=>{const n=e[t];Bn(n)&&n.forEach((e=>{a.children.push(i(e))}))})),a};return Mi(e)||(e=Ti(e)),i(e)}function Ei(e,t){const n=e.matches;t.matches=[],Gn(n)&&n.forEach((e=>{if(!Gn(e.indices)||!e.indices.length)return;const{indices:n,value:i}=e;let r={indices:n,value:i};e.key&&(r.key=e.key.src),e.idx>-1&&(r.refIndex=e.idx),t.matches.push(r)}))}function Pi(e,t){t.score=e.score}class Ai{constructor(e,t={},n){this.options={...oi,...t},this.options.useExtendedSearch,this._keyStore=new ti(this.options.keys),this.setCollection(e,n)}setCollection(e,t){if(this._docs=e,t&&!(t instanceof si))throw new Error("Incorrect 'index' type");this._myIndex=t||li(this.options.keys,this._docs,{getFn:this.options.getFn,fieldNormWeight:this.options.fieldNormWeight})}add(e){Gn(e)&&(this._docs.push(e),this._myIndex.add(e))}remove(e=(()=>!1)){const t=[];for(let n=0,i=this._docs.length;n{let n=1;e.matches.forEach((({key:e,norm:i,score:r})=>{const o=e?e.weight:null;n*=Math.pow(0===r&&o?Number.EPSILON:r,(o||1)*(t?1:i))})),e.score=n}))}(s,{ignoreFieldNorm:a}),r&&s.sort(o),Un(t)&&t>-1&&(s=s.slice(0,t)),function(e,t,{includeMatches:n=oi.includeMatches,includeScore:i=oi.includeScore}={}){const r=[];return n&&r.push(Ei),i&&r.push(Pi),e.map((e=>{const{idx:n}=e,i={item:t[n],refIndex:n};return r.length&&r.forEach((t=>{t(e,i)})),i}))}(s,this._docs,{includeMatches:n,includeScore:i})}_searchStringList(e){const t=Si(e,this.options),{records:n}=this._myIndex,i=[];return n.forEach((({v:e,i:n,n:r})=>{if(!Gn(e))return;const{isMatch:o,score:a,indices:s}=t.searchIn(e);o&&i.push({item:e,idx:n,matches:[{score:a,value:e,norm:r,indices:s}]})})),i}_searchLogical(e){const t=Di(e,this.options),n=(e,t,i)=>{if(!e.children){const{keyId:n,searcher:r}=e,o=this._findMatches({key:this._keyStore.get(n),value:this._myIndex.getValueForItemAtKeyId(t,n),searcher:r});return o&&o.length?[{idx:i,item:t,matches:o}]:[]}const r=[];for(let o=0,a=e.children.length;o{if(Gn(e)){let a=n(t,e,i);a.length&&(r[i]||(r[i]={idx:i,item:e,matches:[]},o.push(r[i])),a.forEach((({matches:e})=>{r[i].matches.push(...e)})))}})),o}_searchObjectList(e){const t=Si(e,this.options),{keys:n,records:i}=this._myIndex,r=[];return i.forEach((({$:e,i})=>{if(!Gn(e))return;let o=[];n.forEach(((n,i)=>{o.push(...this._findMatches({key:n,value:e[i],searcher:t}))})),o.length&&r.push({idx:i,item:e,matches:o})})),r}_findMatches({key:e,value:t,searcher:n}){if(!Gn(t))return[];let i=[];if(Bn(t))t.forEach((({v:t,i:r,n:o})=>{if(!Gn(t))return;const{isMatch:a,score:s,indices:l}=n.searchIn(t);a&&i.push({score:s,key:e,value:t,idx:r,norm:o,indices:l})}));else{const{v:r,n:o}=t,{isMatch:a,score:s,indices:l}=n.searchIn(r);a&&i.push({score:s,key:e,value:r,norm:o,indices:l})}return i}}Ai.version="6.6.2",Ai.createIndex=li,Ai.parseIndex=function(e,{getFn:t=oi.getFn,fieldNormWeight:n=oi.fieldNormWeight}={}){const{keys:i,records:r}=e,o=new si({getFn:t,fieldNormWeight:n});return o.setKeys(i),o.setIndexRecords(r),o},Ai.config=oi,Ai.parseQuery=Di,function(...e){Ci.push(...e)}(wi);var Ni=wn({name:"global-search",data:function(){return{showSearch:!1,placeholder:"Search anything",links:[],filteredLinks:[],adminUrl:"",siteUrl:"",linkFocusIndex:0,loading:!0,fuse:{}}},methods:{getSearchData:function(){var e=this,t=FluentFormsGlobal.$rest.route("globalSearch");FluentFormsGlobal.$rest.get(t).then((function(t){e.adminUrl=t.admin_url,e.siteUrl=t.site_url,e.links=t.links,e.fuse=new Ai(e.links,{minMatchCharLength:2,threshold:.4,keys:["title","tags"]}),e.filteredLinks=e.links.slice(0,7)})).catch((function(e){console.log(e)})).finally((function(){e.loading=!1}))},search:function(e){var t,n;this.linkFocusIndex=0,this.filteredLinks=e&&(null===(t=(n=this.fuse).search)||void 0===t?void 0:t.call(n,e,{limit:50}))||this.links.slice(0,7)},reset:function(){this.showSearch&&(this.showSearch=!1),this.linkFocusIndex=0},goToSlug:function(e,t){var n=new URL(window.location);t.type&&"preview"===t.type?window.location.href=this.siteUrl+"/"+t.path:(window.location.href=this.adminUrl+t.path,this.shouldReload(t,n)&&window.location.reload())},shouldReload:function(e,t){var n=new URL(e.path,this.adminUrl),i=t.searchParams.get("page"),r=n.searchParams.get("page"),o=t.searchParams.get("component"),a=n.searchParams.get("component"),s=t.searchParams.get("form_id"),l=n.searchParams.get("form_id"),c=t.searchParams.get("route"),u=n.searchParams.get("route"),d=t.hash,f=n.hash;return r===i&&((!s&&!l||s===l)&&(!(!c&&!u||c!==u)||(!(!o&&!a||o!==a)||!(o||a||!d&&!f||d===f))))},listener:function(e){var t,n=this;if(((null===(t=window)||void 0===t||null===(t=t.navigator.userAgent)||void 0===t?void 0:t.toUpperCase().includes("MAC"))?e.metaKey:e.ctrlKey)&&75===e.keyCode){if(e.preventDefault&&e.preventDefault(),this.showSearch)return void this.reset();this.showSearch=!0,setTimeout((function(){var e;null===(e=n.$refs.searchInput)||void 0===e||e.focus()}),500),this.links.length||this.getSearchData()}if(this.showSearch)if(27===e.keyCode)e.preventDefault(),this.reset();else if(38===e.keyCode||40===e.keyCode)e.preventDefault(),this.handleUpDownArrow(e);else if(9===e.keyCode){var i;e.preventDefault(),null===(i=this.$refs.searchInput)||void 0===i||i.focus(),this.linkFocusIndex=0}else if(13===e.keyCode&&this.filteredLinks.length){var r=this.filteredLinks[this.linkFocusIndex];r&&this.goToSlug(void 0,r.item||r)}},handleUpDownArrow:function(e){if(this.$refs.links&&Array.isArray(this.$refs.links)){var t,n,i;if(38===e.keyCode?this.linkFocusIndex-=1:this.linkFocusIndex+=1,this.linkFocusIndex>=this.filteredLinks.length||this.linkFocusIndex<=0)return null===(t=this.$refs.searchInput)||void 0===t||t.focus(),null===(n=this.$refs.searchBody)||void 0===n||null===(i=n.scroll)||void 0===i||i.call(n,{top:0}),void(this.linkFocusIndex=0);var r=this.$refs.links[this.linkFocusIndex-1];r&&this.$nextTick((function(){r.focus()}))}}},created:function(){var e,t=this;"yes"===(null===(e=window.fluent_forms_global_var)||void 0===e?void 0:e.global_search_active)&&(document.addEventListener("keydown",this.listener),document.addEventListener("global-search-menu-button-click",(function(e){t.listener({ctrlKey:!0,metaKey:!0,keyCode:75})})))},beforeDestroy:function(){document.removeEventListener("keydown",this.listener)}},(function(){var e=this,t=e._self._c;return e.showSearch?t("div",{staticClass:"global-search-wrapper",on:{click:e.reset}},[t("div",{directives:[{name:"loading",rawName:"v-loading",value:e.loading,expression:"loading"}],staticClass:"global-search-container",on:{click:function(e){e.stopPropagation()}}},[t("div",{ref:"searchBody",staticClass:"global-search-body"},[t("div",{staticClass:"el-input el-input--prefix"},[t("input",{ref:"searchInput",attrs:{"prefix-icon":"el-icon-search",type:"text",name:"search",placeholder:e.$t(e.placeholder),autocomplete:"off"},on:{input:function(t){return e.search(t.target.value)}}}),e._v(" "),e._m(0)]),e._v(" "),t("ul",{staticClass:"search-result"},[this.filteredLinks.length?e._l(e.filteredLinks,(function(n,i){var r;return t("li",{key:"link_"+i,ref:"links",refInFor:!0,class:{"active-search-link":e.linkFocusIndex===i},attrs:{tabindex:"1"},on:{click:function(t){return e.goToSlug(t,n.item||n)}}},[t("span",[e._v(e._s((null===(r=n.item)||void 0===r?void 0:r.title)||n.title))])])})):t("li",[t("span",[e._v(e._s(e.$t("Search not match. Try a different query.")))])])],2)]),e._v(" "),t("div",[t("ul",{staticClass:"search-commands"},[t("li",[e._v(e._s(e.$t("Esc to close")))]),e._v(" "),t("li",[e._v("\n "+e._s(e.$t("Navigate"))+"\n "),t("i",{staticClass:"el-icon-bottom"}),e._v(" "),t("i",{staticClass:"el-icon-top"})]),e._v(" "),t("li",[e._v(e._s(e.$t("Tab to focus search")))]),e._v(" "),t("li",[e._v(e._s(e.$t("Enter to Select")))])])])])]):e._e()}),[function(){var e=this._self._c;return e("span",{staticClass:"el-input__prefix"},[e("i",{staticClass:"el-input__icon el-icon-search"})])}],!1,null,null,null);const Ii=wn({name:"payment-settings",props:["settings"],components:{globalSearch:Ni.exports,Card:zn},data:function(){return{loading:!1,selectedRoute:this.$route.name}},methods:{enablePaymentModule:function(){var e=this;FluentFormsGlobal.$post({action:"fluentform_handle_payment_ajax_endpoint",route:"enable_payment"}).then((function(t){e.$success(t.data.message),t.data.reload&&location.reload()}))}}},(function(){var e=this,t=e._self._c;return t("div",{staticClass:"ff_payment_wrapper"},[e.app_vars.is_setup?t("div",{staticClass:"ff_payment_settings_wrapper"},[t("card",[t("div",{staticClass:"ff_payment_settings"},[t("router-view",{attrs:{settings:e.app_vars}})],1)])],1):t("div",{staticClass:"ff_pre_settings_wrapper"},[t("h2",[e._v("\n "+e._s(e.$t("Fluent Forms Payment Module"))+"\n ")]),e._v(" "),t("p",[e._v("\n "+e._s(e.$t("Enable your users to pay online as part of the Forms submission process. With Fluent Forms Powerful payment integration, you can easily accept and process payments in your Fluent Forms. Just activate this module and setup your payment methods."))+"\n ")]),e._v(" "),t("el-button",{attrs:{type:"primary",icon:"el-icon-success"},on:{click:function(t){return e.enablePaymentModule()}}},[e._v("\n "+e._s(e.$t("Enable Payment Module"))+"\n ")])],1),e._v(" "),t("global-search")],1)}),[],!1,null,null,null).exports;function Fi(e){return Fi="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Fi(e)}function Ri(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function Li(e){for(var t=1;t{e.exports={default:n(56981),__esModule:!0}},93516:(e,t,n)=>{e.exports={default:n(80025),__esModule:!0}},64275:(e,t,n)=>{e.exports={default:n(52392),__esModule:!0}},88239:(e,t,n)=>{"use strict";var i,r=n(52945),o=(i=r)&&i.__esModule?i:{default:i};t.Z=o.default||function(e){for(var t=1;t{"use strict";var i=a(n(64275)),r=a(n(93516)),o="function"==typeof r.default&&"symbol"==typeof i.default?function(e){return typeof e}:function(e){return e&&"function"==typeof r.default&&e.constructor===r.default&&e!==r.default.prototype?"symbol":typeof e};function a(e){return e&&e.__esModule?e:{default:e}}t.Z="function"==typeof r.default&&"symbol"===o(i.default)?function(e){return void 0===e?"undefined":o(e)}:function(e){return e&&"function"==typeof r.default&&e.constructor===r.default&&e!==r.default.prototype?"symbol":void 0===e?"undefined":o(e)}},56981:(e,t,n)=>{n(72699),e.exports=n(34579).Object.assign},80025:(e,t,n)=>{n(46840),n(94058),n(8174),n(36461),e.exports=n(34579).Symbol},52392:(e,t,n)=>{n(91867),n(73871),e.exports=n(25103).f("iterator")},85663:e=>{e.exports=function(e){if("function"!=typeof e)throw TypeError(e+" is not a function!");return e}},79003:e=>{e.exports=function(){}},12159:(e,t,n)=>{var i=n(36727);e.exports=function(e){if(!i(e))throw TypeError(e+" is not an object!");return e}},57428:(e,t,n)=>{var i=n(7932),r=n(78728),o=n(16531);e.exports=function(e){return function(t,n,a){var s,l=i(t),c=r(l.length),u=o(a,c);if(e&&n!=n){for(;c>u;)if((s=l[u++])!=s)return!0}else for(;c>u;u++)if((e||u in l)&&l[u]===n)return e||u||0;return!e&&-1}}},32894:e=>{var t={}.toString;e.exports=function(e){return t.call(e).slice(8,-1)}},34579:e=>{var t=e.exports={version:"2.6.12"};"number"==typeof __e&&(__e=t)},19216:(e,t,n)=>{var i=n(85663);e.exports=function(e,t,n){if(i(e),void 0===t)return e;switch(n){case 1:return function(n){return e.call(t,n)};case 2:return function(n,i){return e.call(t,n,i)};case 3:return function(n,i,r){return e.call(t,n,i,r)}}return function(){return e.apply(t,arguments)}}},8333:e=>{e.exports=function(e){if(null==e)throw TypeError("Can't call method on "+e);return e}},89666:(e,t,n)=>{e.exports=!n(7929)((function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a}))},97467:(e,t,n)=>{var i=n(36727),r=n(33938).document,o=i(r)&&i(r.createElement);e.exports=function(e){return o?r.createElement(e):{}}},73338:e=>{e.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},70337:(e,t,n)=>{var i=n(46162),r=n(48195),o=n(86274);e.exports=function(e){var t=i(e),n=r.f;if(n)for(var a,s=n(e),l=o.f,c=0;s.length>c;)l.call(e,a=s[c++])&&t.push(a);return t}},83856:(e,t,n)=>{var i=n(33938),r=n(34579),o=n(19216),a=n(41818),s=n(27069),l="prototype",c=function(e,t,n){var u,d,f,h=e&c.F,p=e&c.G,m=e&c.S,v=e&c.P,g=e&c.B,b=e&c.W,y=p?r:r[t]||(r[t]={}),_=y[l],x=p?i:m?i[t]:(i[t]||{})[l];for(u in p&&(n=t),n)(d=!h&&x&&void 0!==x[u])&&s(y,u)||(f=d?x[u]:n[u],y[u]=p&&"function"!=typeof x[u]?n[u]:g&&d?o(f,i):b&&x[u]==f?function(e){var t=function(t,n,i){if(this instanceof e){switch(arguments.length){case 0:return new e;case 1:return new e(t);case 2:return new e(t,n)}return new e(t,n,i)}return e.apply(this,arguments)};return t[l]=e[l],t}(f):v&&"function"==typeof f?o(Function.call,f):f,v&&((y.virtual||(y.virtual={}))[u]=f,e&c.R&&_&&!_[u]&&a(_,u,f)))};c.F=1,c.G=2,c.S=4,c.P=8,c.B=16,c.W=32,c.U=64,c.R=128,e.exports=c},7929:e=>{e.exports=function(e){try{return!!e()}catch(e){return!0}}},33938:e=>{var t=e.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=t)},27069:e=>{var t={}.hasOwnProperty;e.exports=function(e,n){return t.call(e,n)}},41818:(e,t,n)=>{var i=n(4743),r=n(83101);e.exports=n(89666)?function(e,t,n){return i.f(e,t,r(1,n))}:function(e,t,n){return e[t]=n,e}},54881:(e,t,n)=>{var i=n(33938).document;e.exports=i&&i.documentElement},33758:(e,t,n)=>{e.exports=!n(89666)&&!n(7929)((function(){return 7!=Object.defineProperty(n(97467)("div"),"a",{get:function(){return 7}}).a}))},50799:(e,t,n)=>{var i=n(32894);e.exports=Object("z").propertyIsEnumerable(0)?Object:function(e){return"String"==i(e)?e.split(""):Object(e)}},71421:(e,t,n)=>{var i=n(32894);e.exports=Array.isArray||function(e){return"Array"==i(e)}},36727:e=>{e.exports=function(e){return"object"==typeof e?null!==e:"function"==typeof e}},33945:(e,t,n)=>{"use strict";var i=n(98989),r=n(83101),o=n(25378),a={};n(41818)(a,n(22939)("iterator"),(function(){return this})),e.exports=function(e,t,n){e.prototype=i(a,{next:r(1,n)}),o(e,t+" Iterator")}},45700:(e,t,n)=>{"use strict";var i=n(16227),r=n(83856),o=n(57470),a=n(41818),s=n(15449),l=n(33945),c=n(25378),u=n(95089),d=n(22939)("iterator"),f=!([].keys&&"next"in[].keys()),h="keys",p="values",m=function(){return this};e.exports=function(e,t,n,v,g,b,y){l(n,t,v);var _,x,w,C=function(e){if(!f&&e in $)return $[e];switch(e){case h:case p:return function(){return new n(this,e)}}return function(){return new n(this,e)}},S=t+" Iterator",k=g==p,O=!1,$=e.prototype,j=$[d]||$["@@iterator"]||g&&$[g],M=j||C(g),T=g?k?C("entries"):M:void 0,D="Array"==t&&$.entries||j;if(D&&(w=u(D.call(new e)))!==Object.prototype&&w.next&&(c(w,S,!0),i||"function"==typeof w[d]||a(w,d,m)),k&&j&&j.name!==p&&(O=!0,M=function(){return j.call(this)}),i&&!y||!f&&!O&&$[d]||a($,d,M),s[t]=M,s[S]=m,g)if(_={values:k?M:C(p),keys:b?M:C(h),entries:T},y)for(x in _)x in $||o($,x,_[x]);else r(r.P+r.F*(f||O),t,_);return _}},85084:e=>{e.exports=function(e,t){return{value:t,done:!!e}}},15449:e=>{e.exports={}},16227:e=>{e.exports=!0},77177:(e,t,n)=>{var i=n(65730)("meta"),r=n(36727),o=n(27069),a=n(4743).f,s=0,l=Object.isExtensible||function(){return!0},c=!n(7929)((function(){return l(Object.preventExtensions({}))})),u=function(e){a(e,i,{value:{i:"O"+ ++s,w:{}}})},d=e.exports={KEY:i,NEED:!1,fastKey:function(e,t){if(!r(e))return"symbol"==typeof e?e:("string"==typeof e?"S":"P")+e;if(!o(e,i)){if(!l(e))return"F";if(!t)return"E";u(e)}return e[i].i},getWeak:function(e,t){if(!o(e,i)){if(!l(e))return!0;if(!t)return!1;u(e)}return e[i].w},onFreeze:function(e){return c&&d.NEED&&l(e)&&!o(e,i)&&u(e),e}}},88082:(e,t,n)=>{"use strict";var i=n(89666),r=n(46162),o=n(48195),a=n(86274),s=n(66530),l=n(50799),c=Object.assign;e.exports=!c||n(7929)((function(){var e={},t={},n=Symbol(),i="abcdefghijklmnopqrst";return e[n]=7,i.split("").forEach((function(e){t[e]=e})),7!=c({},e)[n]||Object.keys(c({},t)).join("")!=i}))?function(e,t){for(var n=s(e),c=arguments.length,u=1,d=o.f,f=a.f;c>u;)for(var h,p=l(arguments[u++]),m=d?r(p).concat(d(p)):r(p),v=m.length,g=0;v>g;)h=m[g++],i&&!f.call(p,h)||(n[h]=p[h]);return n}:c},98989:(e,t,n)=>{var i=n(12159),r=n(57856),o=n(73338),a=n(58989)("IE_PROTO"),s=function(){},l="prototype",c=function(){var e,t=n(97467)("iframe"),i=o.length;for(t.style.display="none",n(54881).appendChild(t),t.src="javascript:",(e=t.contentWindow.document).open(),e.write("
  • " . implode('
  • ', $data['settings']['step_titles']) . "
  • "; }elseif ($data['settings']['progress_indicator'] == 'steps_with_nav') { $nav = "
    • " . implode('
    • ', $data['settings']['step_titles']) . "
    "; } elseif ($data['settings']['progress_indicator'] == 'progress-bar') { $nav = "
    "; } else { $nav = ''; } $data['attributes']['data-disable_auto_focus'] = ArrayHelper::get($data, 'settings.disable_auto_focus', 'no'); $data['attributes']['data-enable_auto_slider'] = ArrayHelper::get($data, 'settings.enable_auto_slider', 'no'); $data['attributes']['data-enable_step_data_persistency'] = ArrayHelper::get($data, 'settings.enable_step_data_persistency', 'no'); $data['attributes']['data-enable_step_page_resume'] = ArrayHelper::get($data, 'settings.enable_step_page_resume', 'no'); $data['attributes']['data-animation_type'] = ArrayHelper::get($data, 'settings.step_animation', 'slide'); $atts = $this->buildAttributes( \FluentForm\Framework\Helpers\ArrayHelper::except($data['attributes'], 'name') ); echo "
    "; if ($nav) { echo "
    {$nav}
    "; } echo "
    "; $data['attributes']['class'] .= ' fluentform-step'; $data['attributes']['class'] = trim($data['attributes']['class']) . ' active'; $atts = $this->buildAttributes( \FluentForm\Framework\Helpers\ArrayHelper::except($data['attributes'], 'name') ); echo "
    "; } /** * Compile and echo the html element * @param array $data [element data] * @param stdClass $form [Form Object] * @return void */ public function compile($data, $form) { echo $this->compileButtons($data['settings']); $data['attributes']['class'] .= ' fluentform-step'; $atts = $this->buildAttributes( \FluentForm\Framework\Helpers\ArrayHelper::except($data['attributes'], 'name') ); echo "
    "; } /** * Compile and echo step footer * @param array $data [element data] * @param stdClass $form [Form Object] * @return void */ public function stepEnd($data, $form) { $btnPrev = $this->compileButtons($data['settings']); ?>
    fields['submitButton'], $form); ?>
    " . $prev['text'] . ""; } else { $alt = esc_attr(ArrayHelper::get($next,'img_alt')); $btnPrev = "{$alt}"; } } if ($next) { if ($next['type'] == 'default') { $tabIndex = \FluentForm\App\Helpers\Helper::getNextTabIndex(); $tabIndexHtml = ''; if($tabIndex) { $tabIndexHtml = "tabindex='".$tabIndex."' "; } $btnClass = apply_filters('fluentform/step_next_button_class', 'ff-float-right ff-btn ff-btn-next ff-btn-secondary', $data); $btnNext = ""; } else { $alt = esc_attr(ArrayHelper::get($next,'img_alt')); $btnNext = "{$alt}"; } } return "
    {$btnPrev}{$btnNext}
    "; } } PK! ɢ33%src/Components/SaveProgressButton.phpnu[updateExistingFields(); add_action('wp_enqueue_scripts', function () { $vars = apply_filters('fluentform/save_progress_vars', [ 'source_url' => home_url($_SERVER['REQUEST_URI']), 'nonce' => wp_create_nonce(), 'copy_button' => sprintf("", fluentformMix('img/copy.svg')), 'copy_success_button' => sprintf("", fluentformMix('img/check.svg')), 'email_button' => sprintf("", fluentformMix('img/email.svg')), 'email_placeholder_str' => __('Your Email Here', 'fluentformpro'), ]); wp_localize_script('form-save-progress', 'form_state_save_vars', $vars); }); } public function pushFormInputType($types) { return $types; } function getComponent() { return [ 'index' => 15, 'element' => $this->key, 'attributes' => [ 'class' => '', ], 'settings' => [ 'button_style' => 'default', 'button_size' => 'md', 'align' => 'left', 'container_class' => '', 'current_state' => 'normal_styles', 'background_color' => 'rgb(64, 158, 255)', 'color' => 'rgb(255, 255, 255)', 'hover_styles' => (object)[ 'backgroundColor' => '#ffffff', 'borderColor' => '#1a7efb', 'color' => '#1a7efb', 'borderRadius' => '', 'minWidth' => '100%' ], 'normal_styles' => (object)[ 'backgroundColor' => '#1a7efb', 'borderColor' => '#1a7efb', 'color' => '#ffffff', 'borderRadius' => '', 'minWidth' => '' ], 'button_ui' => (object)[ 'text' => __('Save & Resume', 'fluentformpro'), 'type' => 'default', 'img_url' => '' ], 'conditional_logics' => [], 'email_resume_link_enabled' => false, 'save_success_message' => __('Your progress has been successfully saved. Resume anytime using the link below.','fluentformpro'), 'email_subject' => sprintf(__('Resume Form Submission : %s','fluentformpro'), '{form_name}'), 'email_body' => __(self::getEmailBody(), 'fluentformpro') ], 'editor_options' => [ 'title' => $this->title, 'icon_class' => 'dashicons dashicons-arrow-right-alt', 'template' => 'customButton' ], ]; } public function pushConditionalSupport($conditonalItems) { return $conditonalItems; } public function getGeneralEditorElements() { return [ 'btn_text', 'button_ui', 'button_style', 'button_size', 'align', 'save_success_message', 'email_resume_link_enabled', 'email_subject', 'email_body', ]; } public function getAdvancedEditorElements() { return [ 'container_class', 'class', 'conditional_logics', ]; } public function generalEditorElement() { return [ 'save_success_message' => [ 'template' => 'inputTextarea', 'label' => __('Success Message', 'fluentform'), 'help_text' => __('Message to show after saving form state.', 'fluentformpro'), ], 'email_resume_link_enabled' => [ 'template' => 'radioButton', 'label' => __('Enable Email Link', 'fluentform'), 'help_text' => __('Allow User to Email Resume Link', 'fluentform'), 'options' => [ [ 'value' => true, 'label' => __('Yes', 'fluentform'), ], [ 'value' => false, 'label' => __('No', 'fluentform'), ], ], ], 'email_subject' => [ 'template' => 'inputText', 'label' => __('Email Subject', 'fluentform'), 'help_text' => sprintf(__('Use %s placeholder to get the Form Name.', 'fluentformpro'),'{form_name}'), 'dependency' => [ 'depends_on' => 'settings/email_resume_link_enabled', 'value' => true, 'operator' => '==', ], ], 'email_body' => [ 'template' => 'inputHTML', 'label' => __('Email Body', 'fluentform'), 'hide_extra' => 'yes', 'inline_help_text' => sprintf(__('Use %s placeholder to get the email resume link.', 'fluentformpro'),'{email_resume_link}'), 'dependency' => [ 'depends_on' => 'settings/email_resume_link_enabled', 'value' => true, 'operator' => '==', ], ], ]; } public function render($data, $form) { $elementName = $data['element']; $data = apply_filters_deprecated( 'fluentform_rendering_field_data_' . $elementName, [ $data, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/rendering_field_data_' . $elementName, 'Use fluentform/rendering_field_data_' . $elementName . ' instead of fluentform_rendering_field_data_' . $elementName ); $data = apply_filters('fluentform/rendering_field_data_' . $elementName, $data, $form); wp_enqueue_script('form-save-progress'); add_filter('fluentform/form_class', function ($formClass){ return $formClass .= ' ff-form-has-save-progress'; }); $btnStyle = Arr::get($data['settings'], 'button_style'); $btnSize = 'ff-btn-'; $btnSize .= isset($data['settings']['button_size']) ? $data['settings']['button_size'] : 'md'; $oldBtnType = isset($data['settings']['button_style']) ? '' : ' ff-btn-primary '; $align = 'ff-el-group ff-text-' . @$data['settings']['align']; $btnClasses = [ 'ff-btn ff-btn-save-progress', $oldBtnType, $btnSize, $data['attributes']['class'] ]; if($btnStyle == 'no_style') { $btnClasses[] = 'ff_btn_no_style'; } else { $btnClasses[] = 'ff_btn_style'; } $data['attributes']['class'] = trim(implode(' ', array_filter($btnClasses))); if($tabIndex = \FluentForm\App\Helpers\Helper::getNextTabIndex()) { $data['attributes']['tabindex'] = $tabIndex; } $styles = ''; if (Arr::get($data, 'settings.button_style') == '') { $data['attributes']['class'] .= ' wpf_has_custom_css'; // it's a custom button $buttonActiveStyles = Arr::get($data, 'settings.normal_styles', []); $buttonHoverStyles = Arr::get($data, 'settings.hover_styles', []); $activeStates = ''; foreach ($buttonActiveStyles as $styleAtr => $styleValue) { if (!$styleValue) { continue; } if ($styleAtr == 'borderRadius') { $styleValue .= 'px'; } $activeStates .= ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '-$0', $styleAtr)), '_') . ':' . $styleValue . ';'; } if ($activeStates) { $styles .= 'form.fluent_form_' . $form->id . ' .wpf_has_custom_css.ff-btn-save-progress { ' . $activeStates . ' }'; } $hoverStates = ''; foreach ($buttonHoverStyles as $styleAtr => $styleValue) { if (!$styleValue) { continue; } if ($styleAtr == 'borderRadius') { $styleValue .= 'px'; } $hoverStates .= ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '-$0', $styleAtr)), '-') . ':' . $styleValue . ';'; } if ($hoverStates) { $styles .= 'form.fluent_form_' . $form->id . ' .wpf_has_custom_css.ff-btn-save-progress:hover { ' . $hoverStates . ' } '; } } else if($btnStyle != 'no_style') { $styles .= 'form.fluent_form_' . $form->id . ' .ff-btn-save-progress { background-color: ' . Arr::get($data, 'settings.background_color') . '; color: ' . Arr::get($data, 'settings.color') . '; }'; } if (Arr::get($data, 'settings.email_resume_link_enabled')) { $data['attributes']['class'] .= ' ff_resume_email_enabled'; } $atts = $this->buildAttributes($data['attributes']); $hasConditions = $this->hasConditions($data) ? 'has-conditions ' : ''; $cls = trim($align . ' ' . $data['settings']['container_class'] . ' ' . $hasConditions); $html = "
    "; // ADDED IN v1.2.6 - updated in 1.4.4 if (isset($data['settings']['button_ui'])) { if ($data['settings']['button_ui']['type'] == 'default') { $html .= ''; } else { $html .= ""; } } else { $html .= ''; } if ($styles) { $html .= ''; } $html .= '
    '; $html = apply_filters_deprecated( 'fluentform_rendering_field_html_' . $elementName, [ $html, $data, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/rendering_field_html_' . $elementName, 'Use fluentform/rendering_field_html_' . $elementName . ' instead of fluentform_rendering_field_html_' . $elementName ); echo apply_filters('fluentform/rendering_field_html_' . $elementName, $html, $data, $form); } private function getEmailBody() { return '

    Hello,

    Your Progress has been saved as you have not completed filling out the {form_name}. Continue where you left off using the link below.

    Resume Form

    Thank you

    '; } private function updateExistingFields() { add_filter('fluentform/editor_init_element_save_progress_button', function ($element) { if (!isset($element['settings']['email_resume_link_enabled'])) { $element['settings']['email_resume_link_enabled'] = false; } if (!isset($element['settings']['save_success_message'])) { $element['settings']['save_success_message'] = __('Your progress has been successfully saved. Resume anytime using the link below.', 'fluentformpro'); } if (!isset($element['settings']['email_subject'])) { $element['settings']['email_subject'] = sprintf(__('Resume Form Submission : %s', 'fluentformpro'), '{form_name}'); } if (!isset($element['settings']['email_body'])) { $element['settings']['email_body'] = $this->getEmailBody(); } return $element; }); } } PK!x$ $ src/Components/Uploader.phpnu[makeElementId($data, $form).'_'.Helper::$formInstance; $data['attributes']['multiple'] = true; if($tabIndex = \FluentForm\App\Helpers\Helper::getNextTabIndex()) { $data['attributes']['tabindex'] = $tabIndex; } $btnText = ArrayHelper::get($data, 'settings.btn_text'); if(!$btnText) { $btnText = __('Choose File', 'fluentformpro'); } $ariaRequired = 'false'; if (ArrayHelper::get($data, 'settings.validation_rules.required.value')) { $ariaRequired = 'true'; } $elMarkup = ""; $elMarkup = sprintf($elMarkup, $this->buildAttributes($data['attributes'], $form)); $html = $this->buildElementMarkup($elMarkup, $data, $form); $html = apply_filters_deprecated( 'fluentform_rendering_field_html_' . $elementName, [ $html, $data, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/rendering_field_html_' . $elementName, 'Use fluentform/rendering_field_html_' . $elementName . ' instead of fluentform_rendering_field_html_' . $elementName ); echo apply_filters('fluentform/rendering_field_html_' . $elementName, $html, $data, $form); $this->enqueueProScripts(); } /** * Enqueue required scripts * @return void */ public function enqueueProScripts() { wp_enqueue_script('fluentform-uploader-jquery-ui-widget'); wp_enqueue_script('fluentform-uploader-iframe-transport'); wp_enqueue_script('fluentform-uploader'); } } PK!)Nsrc/Components/ShortCode.phpnu[hasConditions($data) ? 'has-conditions ' : ''; $data['attributes']['class'] = trim( $this->getDefaultContainerClass() .' '. @$data['attributes']['class'] .' '. $hasConditions ); $atts = $this->buildAttributes( \FluentForm\Framework\Helpers\ArrayHelper::except($data['attributes'], 'name') ); $html = "
    ".do_shortcode($data['settings']['shortcode'])."
    "; $html = apply_filters_deprecated( 'fluentform_rendering_field_html_' . $elementName, [ $html, $data, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/rendering_field_html_' . $elementName, 'Use fluentform/rendering_field_html_' . $elementName . ' instead of fluentform_rendering_field_html_' . $elementName ); echo apply_filters('fluentform/rendering_field_html_' . $elementName, $html, $data, $form); } } PK!Y&&src/Components/Repeater.phpnu[hasConditions($data) ? 'has-conditions ' : ''; @$data['attributes']['class'] .= ' ' . $this->wrapperClass . ' ' . $hasConditions.' '.ArrayHelper::get($data, 'settings.container_class'); $data['attributes']['class'] = trim($data['attributes']['class']); $data['attributes']['data-max_repeat'] = ArrayHelper::get($data, 'settings.max_repeat_field'); if($labelPlacement = ArrayHelper::get($data, 'settings.label_placement')) { $data['attributes']['class'] .= ' ff-el-form-'.$labelPlacement; } $atts = $this->buildAttributes( \FluentForm\Framework\Helpers\ArrayHelper::except($data['attributes'], 'name') ); ob_start(); echo "
    "; $first = $data['fields'][0]['settings']; if (count($data['fields']) == 1 && $first['validation_rules']['required']['value']) { echo "
    "; } else { echo "
    "; } echo ""; echo "
    "; echo "
    "; foreach ($data['fields'] as $key => $item) { if (count($data['fields']) == 1) { $item['settings']['label'] = ''; } $item['attributes']['name'] = $rootName.'['.$key.'][]'; $item = apply_filters_deprecated( 'fluentform_before_render_item', [ $item, $form ], 'fluentform/before_render_item', 'Use fluentform/before_render_item instead of fluentform_before_render_item.' ); $item = $this->app->applyFilters('fluentform/before_render_item', $item, $form); echo "
    "; do_action_deprecated( 'fluentform_render_item_' . $item['element'], [ $item, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/render_item_' . $item['element'], 'Use fluentform/render_item_' . $item['element'] . ' instead of fluentform_render_item_' . $item['element'] ); $this->app->doAction('fluentform/render_item_' . $item['element'], $item, $form); echo "
    "; } echo "
    "; echo $this->getRepeater($data['element']); echo "
    "; echo "
    "; $html = ob_get_clean(); $html = apply_filters_deprecated( 'fluentform_rendering_field_html_' . $elementName, [ $html, $data, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/rendering_field_html_' . $elementName, 'Use fluentform/rendering_field_html_' . $elementName . ' instead of fluentform_rendering_field_html_' . $elementName ); echo apply_filters('fluentform/rendering_field_html_'.$elementName, $html, $data, $form); \FluentForm\App\Helpers\Helper::getNextTabIndex(50); } /** * Compile repeater buttons * @param string $el [element name] * @return string */ protected function getRepeater($el) { if ($el == 'input_repeat') { $div = '
    '; $div .= '
    '; $div .= ''; $div .= ''; $div .= '
    '; $div .= '
    '; return $div; } return ''; } } PK!M99src/Components/PhoneField.phpnu[ 'all', 'visible_list' => array(), 'hidden_list' => array(), ); $element['settings']['default_country'] = ''; } // todo:: remove the 'with_extended_validation' check in future. $enabled = ArrayHelper::get($element, 'settings.int_tel_number') == 'with_extended_validation'; if ($enabled) { ArrayHelper::set($element, 'settings.validation_rules.valid_phone_number.value', true); ArrayHelper::forget($element, 'settings.int_tel_number'); } return $element; }); } function getComponent() { return [ 'index' => 18, 'element' => $this->key, 'attributes' => [ 'name' => $this->key, 'class' => '', 'value' => '', 'type' => 'tel', 'placeholder' => __('Mobile Number', 'fluentformpro') ], 'settings' => [ 'container_class' => '', 'placeholder' => '', 'auto_select_country' => 'no', 'label' => $this->title, 'label_placement' => '', 'help_message' => '', 'admin_field_label' => '', 'phone_country_list' => array( 'active_list' => 'all', 'visible_list' => array(), 'hidden_list' => array(), ), 'default_country' => '', 'validation_rules' => [ 'required' => [ 'value' => false, 'global' => true, 'message' => Helper::getGlobalDefaultMessage('required'), 'global_message' => Helper::getGlobalDefaultMessage('required'), ], 'valid_phone_number' => [ 'value' => false, 'global' => true, 'message' => Helper::getGlobalDefaultMessage('valid_phone_number'), 'global_message' => Helper::getGlobalDefaultMessage('valid_phone_number'), ] ], 'conditional_logics' => [] ], 'editor_options' => [ 'title' => $this->title, 'icon_class' => 'el-icon-phone-outline', 'template' => 'inputText' ], ]; } public function getGeneralEditorElements() { return [ 'label', 'label_placement', 'admin_field_label', 'placeholder', 'value', 'auto_select_country', 'phone_country_list', 'validation_rules', ]; } public function generalEditorElement() { return [ 'auto_select_country' => [ 'template' => 'radio', 'label' => __('Enable Auto Country Select', 'fluentformpro'), 'help_text' => __('If you enable this, The country will be selected based on user\'s ip address. ipinfo.io service will be used here', 'fluentformpro'), 'options' => [ [ 'label' => __('No', 'fluentformpro'), 'value' => 'no' ], [ 'label' => __('Yes', 'fluentformpro'), 'value' => 'yes' ] ], 'dependency' => array( 'depends_on' => 'settings/validation_rules/valid_phone_number/value', 'value' => false, 'operator' => '!=' ) ], 'phone_country_list' => array( 'template' => 'customCountryList', 'label' => __('Available Countries', 'fluentformpro'), 'disable_labels' => true, 'key' => 'phone_country_list', 'dependency' => array( 'depends_on' => 'settings/validation_rules/valid_phone_number/value', 'value' => false, 'operator' => '!=' ) ) ]; } public function render($data, $form) { $elementName = $data['element']; $data = apply_filters_deprecated( 'fluentform_rendering_field_data_' . $elementName, [ $data, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/rendering_field_data_' . $elementName, 'Use fluentform/rendering_field_data_' . $elementName . ' instead of fluentform_rendering_field_data_' . $elementName ); $data = apply_filters('fluentform/rendering_field_data_' . $elementName, $data, $form); $data['attributes']['class'] = @trim( 'ff-el-form-control ff-el-phone ' . $data['attributes']['class'] ); $data['attributes']['id'] = $this->makeElementId($data, $form); if ($tabIndex = \FluentForm\App\Helpers\Helper::getNextTabIndex()) { $data['attributes']['tabindex'] = $tabIndex; } $data['attributes']['inputmode'] = 'tel'; // todo:: remove the 'with_extended_validation' check in future. $enabled = ArrayHelper::get($data, 'settings.validation_rules.valid_phone_number.value'); if (!$enabled) { $enabled = ArrayHelper::get($data, 'settings.int_tel_number') == 'with_extended_validation'; } if ($enabled) { // $data['attributes']['placeholder'] = ''; $data['attributes']['class'] .= ' ff_el_with_extended_validation'; $this->pushScripts($data, $form); } $ariaRequired = 'false'; if (ArrayHelper::get($data, 'settings.validation_rules.required.value')) { $ariaRequired = 'true'; } $elMarkup = "buildAttributes($data['attributes'], $form) . " aria-invalid='false' aria-required={$ariaRequired}>"; $html = $this->buildElementMarkup($elMarkup, $data, $form); $html = apply_filters_deprecated( 'fluentform_rendering_field_html_' . $elementName, [ $html, $data, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/rendering_field_html_' . $elementName, 'Use fluentform/rendering_field_html_' . $elementName . ' instead of fluentform_rendering_field_html_' . $elementName ); echo apply_filters('fluentform/rendering_field_html_' . $elementName, $html, $data, $form); } private function pushScripts($data, $form) { // We can add assets for this field wp_enqueue_style('intlTelInput'); wp_enqueue_script('intlTelInput'); wp_enqueue_script('intlTelInputUtils'); add_action('wp_footer', function () use ($data, $form) { $geoLocate = ArrayHelper::get($data, 'settings.auto_select_country') == 'yes'; $itlOptions = [ 'separateDialCode' => false, 'nationalMode' => true, 'autoPlaceholder' => 'polite', 'formatOnDisplay' => true ]; if ($geoLocate) { $itlOptions['initialCountry'] = 'auto'; } else { $itlOptions['initialCountry'] = ArrayHelper::get($data, 'settings.default_country', ''); } $activeList = ArrayHelper::get($data, 'settings.phone_country_list.active_list'); if ($activeList == 'priority_based') { $selectCountries = ArrayHelper::get($data, 'settings.phone_country_list.priority_based', []); $priorityCountries = $this->getSelectedCountries($selectCountries); $itlOptions['preferredCountries'] = array_keys($priorityCountries); } else if ($activeList == 'visible_list') { $onlyCountries = ArrayHelper::get($data, 'settings.phone_country_list.visible_list', []); $itlOptions['onlyCountries'] = $onlyCountries; } else if ($activeList == 'hidden_list') { $countries = $this->loadCountries($data); $itlOptions['onlyCountries'] = array_keys($countries); } $itlOptions = apply_filters_deprecated( 'fluentform_itl_options', [ $itlOptions, $data, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/itl_options', 'Use fluentform/itl_options instead of fluentform_itl_options' ); $itlOptions = apply_filters('fluentform/itl_options', $itlOptions, $data, $form); $itlOptions = json_encode($itlOptions); $settings = get_option('_fluentform_global_form_settings'); $token = ArrayHelper::get($settings, 'misc.geo_provider_token'); $url = 'https://ipinfo.io'; if ($token) { $url = 'https://ipinfo.io/?token=' . $token; } $url = apply_filters_deprecated( 'fluentform_ip_provider', [ $url ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/ip_provider', 'Use fluentform/ip_provider instead of fluentform_ip_provider' ); $ipProviderUrl = apply_filters('fluentform/ip_provider', $url); ?> 16, 'element' => 'repeater_field', 'attributes' => array( 'name' => 'repeater_field', 'data-type' => 'repeater_field' ), 'settings' => array( 'label' => __('Repeater Field', 'fluentformpro'), 'admin_field_label' => '', 'container_class' => '', 'label_placement' => '', 'validation_rules' => array(), 'conditional_logics' => array(), 'max_repeat_field' => '' ), 'fields' => array( array( 'element' => 'input_text', 'attributes' => array( 'type' => 'text', 'value' => '', 'placeholder' => '', ), 'settings' => array( 'label' => __('Column 1', 'fluentformpro'), 'help_message' => '', 'validation_rules' => array( 'required' => array( 'value' => false, 'global' => true, 'message' => Helper::getGlobalDefaultMessage('required'), 'global_message' => Helper::getGlobalDefaultMessage('required'), ) ) ), 'editor_options' => array(), ) ), 'editor_options' => array( 'title' => __('Repeat Field', 'fluentformpro'), 'icon_class' => 'ff-edit-repeat', 'template' => 'fieldsRepeatSettings' ), ]; } public function getGeneralEditorElements() { return [ 'label', 'label_placement', 'admin_field_label', 'fields_repeat_settings', ]; } public function getAdvancedEditorElements() { return [ 'container_class', 'name', 'conditional_logics', 'max_repeat_field' ]; } public function getEditorCustomizationSettings() { return [ 'fields_repeat_settings' => array( 'template' => 'fieldsRepeatSettings', 'label' => __('Repeat Field Columns', 'fluentformpro'), 'help_text' => __('Field Columns which a user will be able to repeat.', 'fluentformpro'), ) ]; } /** * Compile and echo the html element * @param array $data [element data] * @param stdClass $form [Form Object] * @return void */ public function render($data, $form) { $elementName = $data['element']; $data = apply_filters_deprecated( 'fluentform_rendering_field_data_' . $elementName, [ $data, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/rendering_field_data_' . $elementName, 'Use fluentform/rendering_field_data_' . $elementName . ' instead of fluentform_rendering_field_data_' . $elementName ); $data = apply_filters('fluentform/rendering_field_data_' . $elementName, $data, $form); // Test implementation using address component $rootName = $data['attributes']['name']; $hasConditions = $this->hasConditions($data) ? 'has-conditions ' : ''; @$data['attributes']['class'] .= ' ff-el-group ' . $this->wrapperClass . ' ' . $hasConditions . ' ' . ArrayHelper::get($data, 'settings.container_class'); $data['attributes']['class'] = trim($data['attributes']['class']); $maxRepeat = ArrayHelper::get($data, 'settings.max_repeat_field'); $data['attributes']['data-max_repeat'] = $maxRepeat; $data['attributes']['data-root_name'] = $rootName; if ($labelPlacement = ArrayHelper::get($data, 'settings.label_placement')) { $data['attributes']['class'] .= ' ff-el-form-' . $labelPlacement; } $atts = $this->buildAttributes( \FluentForm\Framework\Helpers\ArrayHelper::except($data['attributes'], 'name') ); $fields = $data['fields']; ob_start(); ?>
    > buildElementLabel($data, $form); ?>
    $item): $itemLabel = $item['settings']['label']; $item['settings']['label'] = ''; $item['attributes']['aria-label'] = 'repeater level 1 and field ' . $itemLabel; $item['attributes']['name'] = $rootName . '[0][]'; $item['attributes']['id'] = $this->makeElementId($data, $form) . '_' . $key; $item['attributes']['data-repeater_index'] = $key; $item['attributes']['data-type'] = 'repeater_item'; $item['attributes']['data-name'] = $rootName.'_'.$key.'_0'; $item['attributes']['data-error_index'] = $rootName.'['.$key.']'; $item['attributes']['data-default'] = ArrayHelper::get($item, 'attributes.value'); ?>
    buildElementLabel($field, $form); ?>
    getRepeater($data['element']); ?>
    '; $div .= ''; $div .= ''; $div .= '
    '; return $div; } return ''; } public function renderResponse($response, $field, $form_id) { if (defined('FLUENTFORM_RENDERING_ENTRIES')) { return __('....', 'fluentformpro'); } if (is_string($response) || empty($response) || !is_array($response)) { return ''; } $fields = ArrayHelper::get($field, 'raw.fields'); $columnCount = (count($fields) > count((array)$response[0])) ? count($fields) : count((array)$response[0]); $columns = array_fill(0, $columnCount, 'column'); if (defined('FLUENTFORM_DOING_CSV_EXPORT')) { return self::getResponseAsText($response, $fields, $columns); } return $this->getResponseHtml($response, $fields, $columns); } protected function getResponseHtml($response, $fields, $columns) { ob_start(); ?>
    $count): ?> $item): ?> $count): ?>
    count((array)ArrayHelper::get($response, 0))) ? count($fields) : count((array)ArrayHelper::get($response, 0)); $columns = array_fill(0, $columnCount, 'column'); } $totalColumns = count($columns); $text = ''; foreach ($columns as $index => $count) { $text .= trim(ArrayHelper::get($fields, $index . '.settings.label', ' ')); if( $index+1 != $totalColumns ) { $text .= " | "; } } $text .= "\n"; foreach ($response as $responseIndex => $item): foreach ($columns as $index => $count): $text .= ArrayHelper::get($item, $index); if( $index+1 != $totalColumns ) { $text .= " | "; } endforeach; $text .= "\n"; endforeach; return $text; } } PK!6]X**#src/Components/RangeSliderField.phpnu[ $userValue) { $error = __('Value is not within range', 'fluentformpro'); } } return $error; }, 10, 3); } function getComponent() { return [ 'index' => 15, 'element' => $this->key, 'attributes' => [ 'name' => $this->key, 'class' => '', 'value' => '', 'min' => 0, 'max' => 10, 'type' => 'range' ], 'settings' => [ 'number_step' => '', 'container_class' => '', 'placeholder' => '', 'label' => $this->title, 'label_placement' => '', 'help_message' => '', 'admin_field_label' => '', 'enable_target_product' => 'no', 'target_product' => '', 'validation_rules' => [ 'required' => [ 'value' => false, 'global' => true, 'message' => Helper::getGlobalDefaultMessage('required'), 'global_message' => Helper::getGlobalDefaultMessage('required'), ], ], 'conditional_logics' => [], ], 'editor_options' => [ 'title' => $this->title, 'icon_class' => 'dashicons dashicons-leftright', 'template' => 'inputSlider' ], ]; } public function getGeneralEditorElements() { return [ 'label', 'label_placement', 'admin_field_label', 'value', 'min', 'max', 'number_step', 'validation_rules', 'enable_target_product', 'target_product', ]; } public function generalEditorElement() { return [ 'enable_target_product' => [ 'template' => 'radio', 'options' => [ [ 'value' => 'yes', 'label' => __('Yes', 'fluentformpro'), ], [ 'value' => 'no', 'label' => __('No', 'fluentformpro'), ], ], 'label' => __('Enable Quantity Mapping', 'fluentformpro'), ], 'target_product' => [ 'template' => 'targetProduct', 'label' => __('Target Product Field', 'fluentformpro'), 'dependency' => [ 'depends_on' => 'settings/enable_target_product', 'value' => 'yes', 'operator' => '==', ], ], ]; } public function render($data, $form) { $elementName = $data['element']; $data = apply_filters_deprecated( 'fluentform_rendering_field_data_' . $elementName, [ $data, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/rendering_field_data_' . $elementName, 'Use fluentform/rendering_field_data_' . $elementName . ' instead of fluentform_rendering_field_data_' . $elementName ); $data = apply_filters('fluentform/rendering_field_data_' . $elementName, $data, $form); if ($tabIndex = \FluentForm\App\Helpers\Helper::getNextTabIndex()) { $data['attributes']['tabindex'] = $tabIndex; } $data['attributes']['class'] = @trim('ff-el-form-control ' . $data['attributes']['class']); $data['attributes']['id'] = $this->makeElementId($data, $form); $this->registerScripts($form, $data['attributes']['id']); $data['attributes']['data-default_value'] = $data['attributes']['value']; if ($data['attributes']['value'] == '') { $data['attributes']['value'] = 0; } if ($step = ArrayHelper::get($data, 'settings.number_step')) { $data['attributes']['step'] = $step; } $data['attributes']['type'] = 'range'; $data['attributes']['data-calc_value'] = $data['attributes']['value']; if (is_rtl()) { $data['attributes']['data-direction'] = 'rtl'; } if(ArrayHelper::get($data,'settings.enable_target_product') == 'yes' && ArrayHelper::get($data,'settings.target_product') != '' ){ $data['attributes']['class'] .= ' ff_quantity_item'; $data['attributes']['data-target_product'] = ArrayHelper::get($data, 'settings.target_product'); } $ariaRequired = 'false'; if (ArrayHelper::get($data, 'settings.validation_rules.required.value')) { $ariaRequired = 'true'; } $elMarkup = "
    buildAttributes($data['attributes'], $form) . " aria-invalid='false' aria-required={$ariaRequired}/>
    " . $data['attributes']['value'] . "
    "; $html = $this->buildElementMarkup($elMarkup, $data, $form); $html = apply_filters_deprecated( 'fluentform_rendering_field_html_' . $elementName, [ $html, $data, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/rendering_field_html_' . $elementName, 'Use fluentform/rendering_field_html_' . $elementName . ' instead of fluentform_rendering_field_html_' . $elementName ); echo apply_filters('fluentform/rendering_field_html_' . $elementName, $html, $data, $form); } private function registerScripts($form, $elementId) { wp_enqueue_script( 'rangeslider', FLUENTFORMPRO_DIR_URL . 'public/libs/rangeslider/rangeslider.js', array('jquery'), '2.3.0', true ); wp_enqueue_style( 'rangeslider', FLUENTFORMPRO_DIR_URL . 'public/libs/rangeslider/rangeslider.css', array(), '2.3.0', 'all' ); if (did_action('wp_footer')) { $this->printJS($form, $elementId); } else { add_action('wp_footer', function () use ($form, $elementId) { $this->printJS($form, $elementId); }, 99); } } private function printJS($form, $elementId) { ?> hasConditions($data) ? 'has-conditions ' : ''; $data['attributes']['class'] = trim( $this->getDefaultContainerClass() .' '. @$data['attributes']['class'] .' '. $hasConditions ); $atts = $this->buildAttributes( \FluentForm\Framework\Helpers\ArrayHelper::except($data['attributes'], 'name') ); ob_start(); echo "
    "; do_action($data['settings']['hook_name'], $form); echo"
    "; $html = ob_get_clean(); $html = apply_filters_deprecated( 'fluentform_rendering_field_html_' . $elementName, [ $html, $data, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/rendering_field_html_' . $elementName, 'Use fluentform/rendering_field_html_' . $elementName . ' instead of fluentform_rendering_field_html_'.$elementName ); echo apply_filters('fluentform/rendering_field_html_' . $elementName, $html, $data, $form); } } PK!-T::#src/Components/NetPromoterScore.phpnu[ 19, 'element' => $this->key, 'attributes' => array( 'name' => $this->key, 'type' => 'radio', 'value' => '', 'id' => '', 'class' => '' ), 'settings' => array( 'label' => __('Net Promoter Score', 'fluentformpro'), 'start_text' => __('Not at all Likely', 'fluentformpro'), 'end_text' => __('Extremely Likely', 'fluentformpro'), 'start_number' => 0, 'end_number' => 10, 'help_message' => '', 'label_placement' => '', 'admin_field_label' => '', 'container_class' => '', 'conditional_logics' => array(), 'validation_rules' => array( 'required' => array( 'value' => false, 'global' => true, 'message' => Helper::getGlobalDefaultMessage('required'), 'global_message' => Helper::getGlobalDefaultMessage('required'), ), ), ), 'options' => array ( '0' => __('0', 'fluentformpro'), '1' => __('1', 'fluentformpro'), '2' => __('2', 'fluentformpro'), '3' => __('3', 'fluentformpro'), '4' => __('4', 'fluentformpro'), '5' => __('5', 'fluentformpro'), '6' => __('6', 'fluentformpro'), '7' => __('7', 'fluentformpro'), '8' => __('8', 'fluentformpro'), '9' => __('9', 'fluentformpro'), '10'=> __('10', 'fluentformpro') ), 'editor_options' => array( 'title' => __('Net Promoter Score', 'fluentformpro'), 'icon_class' => 'ff-edit-rating', 'template' => 'net_promoter', ) ); } public function getGeneralEditorElements() { return [ 'label', 'admin_field_label', 'start_text', 'end_text', 'label_placement', 'validation_rules', ]; } public function getAdvancedEditorElements() { return [ 'name', 'help_message', 'container_class', 'class', 'value', 'conditional_logics', ]; } public function generalEditorElement() { return [ 'start_text' => [ 'template' => 'inputText', 'label' => __('Promoter Start Text', 'fluentformpro'), 'help_text' => __('Start Indicator Text for Promoter Scale', 'fluentformpro'), ], 'end_text' => [ 'template' => 'inputText', 'label' => __('Promoter End Text', 'fluentformpro'), 'help_text' => __('End Indicator Text for Promoter Scale', 'fluentformpro'), ] ]; } public function advancedEditorElement() { return []; } public function render($data, $form) { $elementName = $data['element']; $data = apply_filters_deprecated( 'fluentform_rendering_field_data_' . $elementName, [ $data, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/rendering_field_data_' . $elementName, 'Use fluentform/rendering_field_data_' . $elementName . ' instead of fluentform_rendering_field_data_' . $elementName ); $data = apply_filters('fluentform/rendering_field_data_' . $elementName, $data, $form); $options = range(0,10,1); $elMarkup = ''; $elMarkup .= $this->getThead( $options, ArrayHelper::get($data, 'settings.start_text'), ArrayHelper::get($data, 'settings.end_text') ); $elMarkup .= $this->getTbody($data, $options); $elMarkup .= '
    '; $html = $this->buildElementMarkup($elMarkup, $data, $form); $html = apply_filters_deprecated( 'fluentform_rendering_field_html_' . $elementName, [ $html, $data, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/rendering_field_html_' . $elementName, 'Use fluentform/rendering_field_html_' . $elementName . ' instead of fluentform_rendering_field_html_' . $elementName ); echo apply_filters('fluentform/rendering_field_html_' . $elementName, $html, $data, $form); } private function getThead($options, $textStart, $textEnd) { ob_start(); ?> getUniqueid(str_replace(['[', ']'], ['', ''], $data['attributes']['name'].'_'.$option)); $ariaRequired = 'false'; if (ArrayHelper::get($data, 'settings.validation_rules.required.value')) { $ariaRequired = 'true'; } $atts = [ 'type' => 'radio', 'class' => 'ff-screen-reader-element', 'value' => $option, 'data-calc_value' => $option, 'id' => $id, 'name' => $data['attributes']['name'], 'aria-invalid' => 'false', 'aria-required' => $ariaRequired ]; $atts = $this->buildAttributes($atts); ?> > logo = fluentFormMix('img/integrations/activecampaign.png'); $this->description = __('Create signup forms in WordPress and connect ActiveCampaign to grow your list easily.', 'fluentformpro'); $this->registerAdminHooks(); // add_filter('fluentform/notifying_async_activecampaign', '__return_false'); } public function getGlobalFields($fields) { return [ 'logo' => $this->logo, 'menu_title' => __('ActiveCampaign API Settings', 'fluentformpro'), 'menu_description' => __('ActiveCampaign is an integrated email marketing, marketing automation, and small business CRM. Save time while growing your business with sales automation. Use Fluent Forms to collect customer information and automatically add it to your ActiveCampaign list. If you don\'t have an ActiveCampaign account, you can sign up for one here.', 'fluentformpro'), 'valid_message' => __('Your ActiveCampaign configuration is valid', 'fluentformpro'), 'invalid_message' => __('Your ActiveCampaign configuration is invalid', 'fluentformpro'), 'save_button_text' => __('Save Settings', 'fluentformpro'), 'fields' => [ 'apiUrl' => [ 'type' => 'text', 'placeholder' => 'API URL', 'label_tips' => __("Please Provide your ActiveCampaign API URL", 'fluentformpro'), 'label' => __('ActiveCampaign API URL', 'fluentformpro'), ], 'apiKey' => [ 'type' => 'password', 'placeholder' => 'API Key', 'label_tips' => __("Enter your ActiveCampaign API Key, if you do not have
    Please log in to your ActiveCampaign account and find the api key", 'fluentformpro'), 'label' => __('ActiveCampaign API Key', 'fluentformpro'), ] ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your ActiveCampaign API integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect ActiveCampaign', 'fluentformpro'), 'data' => [ 'apiKey' => '' ], 'show_verify' => true ] ]; } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'apiKey' => '', 'apiUrl' => '', 'status' => '' ]; return wp_parse_args($globalSettings, $defaults); } public function saveGlobalSettings($settings) { if (!$settings['apiKey']) { $integrationSettings = [ 'apiKey' => '', 'apiUrl' => '', 'status' => false ]; // Update the reCaptcha details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your settings has been updated and discarded', 'fluentformpro'), 'status' => false ], 200); } try { $settings['status'] = false; update_option($this->optionKey, $settings, 'no'); $api = new ActiveCampaignApi($settings['apiUrl'], $settings['apiKey']); if ($api->auth_test()) { $settings['status'] = true; update_option($this->optionKey, $settings, 'no'); wp_send_json_success([ 'status' => true, 'message' => __('Your settings has been updated!', 'fluentformpro') ], 200); } throw new \Exception(__('Invalid Credentials', 'fluentformpro'), 400); } catch (\Exception $e) { wp_send_json_error([ 'status' => false, 'message' => $e->getMessage() ], $e->getCode()); } } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => $this->title . ' Integration', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-activecampaign-settings'), 'configure_message' => __('ActiveCampaign is not configured yet! Please configure your ActiveCampaign API first', 'fluentformpro'), 'configure_button_text' => __('Set ActiveCampaign API', 'fluentformpro'), ]; return $integrations; } public function getIntegrationDefaults($settings, $formId) { return [ 'name' => '', 'list_id' => '', 'fieldEmailAddress' => '', 'custom_field_mappings' => (object)[], 'default_fields' => (object)[], 'note' => '', 'tags' => '', 'tag_routers' => [], 'tag_ids_selection_type' => 'simple', 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'instant_responders' => false, 'last_broadcast_campaign' => false, 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { return [ 'fields' => [ [ 'key' => 'name', 'label' => __('Name','fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name','fluentformpro'), 'component' => 'text' ], [ 'key' => 'list_id', 'label' => __('ActiveCampaign List','fluentformpro'), 'placeholder' => __('Select ActiveCampaign Mailing List','fluentformpro'), 'tips' => __('Select the ActiveCampaign Mailing List you would like to add your contacts to.','fluentformpro'), 'component' => 'list_ajax_options', 'options' => $this->getLists(), ], [ 'key' => 'custom_field_mappings', 'require_list' => true, 'label' => __('Map Fields','fluentformpro'), 'tips' => __('Select which Fluent Forms fields pair with their
    respective ActiveCampaign fields.','fluentformpro'), 'component' => 'map_fields', 'field_label_remote' => __('ActiveCampaign Field','fluentformpro'), 'field_label_local' => __('Form Field','fluentformpro'), 'primary_fileds' => [ [ 'key' => 'fieldEmailAddress', 'label' => __('Email Address','fluentformpro'), 'required' => true, 'input_options' => 'emails' ] ], 'default_fields' => [ array( 'name' => 'first_name', 'label' => esc_html__('First Name', 'fluentformpro'), 'required' => false ), array( 'name' => 'last_name', 'label' => esc_html__('Last Name', 'fluentformpro'), 'required' => false ), array( 'name' => 'phone', 'label' => esc_html__('Phone Number', 'fluentformpro'), 'required' => false ), array( 'name' => 'orgname', 'label' => esc_html__('Organization Name', 'fluentformpro'), 'required' => false ) ] ], [ 'key' => 'tags', 'require_list' => true, 'label' => __('Tags','fluentformpro'), 'tips' => __('Associate tags to your ActiveCampaign contacts with a comma separated list (e.g. new lead, FluentForms, web source). Commas within a merge tag value will be created as a single tag.','fluentformpro'), 'component' => 'selection_routing', 'simple_component' => 'value_text', 'routing_input_type' => 'text', 'routing_key' => 'tag_ids_selection_type', 'settings_key' => 'tag_routers', 'labels' => [ 'choice_label' => __('Enable Dynamic Tag Input','fluentformpro'), 'input_label' => '', 'input_placeholder' => 'Tag' ], 'inline_tip' => __('Please provide each tag by comma separated value, You can use dynamic smart codes','fluentformpro'), ], [ 'key' => 'note', 'require_list' => true, 'label' => __('Note','fluentformpro'), 'tips' => __('You can write a note for this contact','fluentformpro'), 'component' => 'value_textarea' ], [ 'key' => 'double_optin_form', 'require_list' => true, 'label' => __('Double Opt-In Form','fluentformpro'), 'tips' => __('Select which ActiveCampaign form will be used when exporting to ActiveCampaign to send the opt-in email.','fluentformpro'), 'component' => 'list_select_filter', 'filter_by' => 'list_id', 'parsedType' => 'number', 'placeholder' => __('Select Double Opt-in Form','fluentformpro'), 'options' => $this->getAcForms(), ], [ 'key' => 'instant_responders', 'require_list' => true, 'label' => __('Instant Responders','fluentformpro'), 'tips' => __('When the instant responders option is enabled, ActiveCampaign will
    send any instant responders setup when the contact is added to the
    list. This option is not available to users on a free trial.','fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable Instant Responder','fluentformpro') ], [ 'key' => 'last_broadcast_campaign', 'require_list' => true, 'label' => __('Last Broadcast Campaign','fluentformpro'), 'tips' => __('When send the last broadcast campaign option is enabled,
    ActiveCampaign will send the last campaign sent out to the list
    to the contact being added. This option is not available to users
    on a free trial.','fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable Send the last broadcast campaign','fluentformpro') ], [ 'require_list' => true, 'key' => 'conditionals', 'label' => __('Conditional Logics','fluentformpro'), 'tips' => __('Allow ActiveCampaign integration conditionally based on your submission values','fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => true, 'key' => 'enabled', 'label' => __('Status','fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable This feed','fluentformpro') ] ], 'button_require_list' => true, 'integration_title' => $this->title ]; } protected function getLists() { $api = $this->getApiClient(); if (!$api) { return []; } $lists = $api->get_lists(); $formattedLists = []; foreach ($lists as $list) { if (is_array($list)) { $formattedLists[strval($list['id'])] = $list['name']; } } return $formattedLists; } public function getMergeFields($list, $listId, $formId) { $fields = []; $api = $this->getApiClient(); $response = $api->get_custom_fields(); if ($response['result_code']) { $fields = array_filter($response, function ($item) { return is_array($item); }); $formattedFileds = []; foreach ($fields as $field) { $formattedFileds[$field['id']] = $field['title']; } return $formattedFileds; } return $fields; } /** * Prepare ActiveCampaign forms for feed field. * * @return array */ public function getAcForms() { $forms = array(); $api = $this->getApiClient(); // Get available ActiveCampaign forms. $ac_forms = $api->get_forms(); // Add ActiveCampaign forms to array and return it. if (!empty($ac_forms)) { foreach ($ac_forms as $form) { if (!is_array($form)) { continue; } if ($form['sendoptin'] == 0 || !is_array($form['lists'])) { continue; } $forms[] = [ 'label' => $form['name'], 'value' => 'item_' . $form['id'], 'lists' => $form['lists'] ]; } } return $forms; } /* * Submission Broadcast Handler */ public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; if (!is_email($feedData['fieldEmailAddress'])) { $feedData['fieldEmailAddress'] = ArrayHelper::get($formData, $feedData['fieldEmailAddress']); } if (!is_email($feedData['fieldEmailAddress'])) { do_action('fluentform/integration_action_result', $feed, 'failed', __('Active Campaign API call has been skipped because no valid email available', 'fluentformpro')); return; } $addData = [ 'email' => $feedData['fieldEmailAddress'], 'first_name' => ArrayHelper::get($feedData, 'default_fields.first_name'), 'last_name' => ArrayHelper::get($feedData, 'default_fields.last_name'), 'phone' => ArrayHelper::get($feedData, 'default_fields.phone'), 'orgname' => ArrayHelper::get($feedData, 'default_fields.orgname'), ]; $tags = $this->getSelectedTagIds($feedData, $formData, 'tags'); if(!is_array($tags)) { $tags = explode(',', $tags); } $tags = array_map('trim', $tags); $tags = array_filter($tags); if ($tags) { $addData['tags'] = implode(',', $tags); } $list_id = $feedData['list_id']; $addData['p[' . $list_id . ']'] = $list_id; $addData['status[' . $list_id . ']'] = '1'; foreach (ArrayHelper::get($feedData, 'custom_field_mappings', []) as $key => $value) { if (!$value) { continue; } $contact_key = 'field[' . $key . ',0]'; $addData[$contact_key] = $value; } if (ArrayHelper::isTrue($feedData, 'instant_responders')) { $addData['instantresponders[' . $list_id . ']'] = 1; } if (ArrayHelper::isTrue($feedData, 'last_broadcast_campaign')) { $addData['lastmessage[' . $list_id . ']'] = 1; } if (!empty($feedData['double_optin_form'])) { $formId = str_replace('item_', '', $feedData['double_optin_form']); if ($formId) { $addData['form'] = $formId; } } $addData = array_filter($addData); $addData = apply_filters_deprecated( 'fluentform_integration_data_' . $this->integrationKey, [ $addData, $feed, $entry ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/integration_data_' . $this->integrationKey, 'Use fluentform/integration_data_' . $this->integrationKey . ' instead of fluentform_integration_data_' . $this->integrationKey ); $addData = apply_filters('fluentform/integration_data_' . $this->integrationKey, $addData, $feed, $entry); // Now let's prepare the data and push to hubspot $api = $this->getApiClient(); $response = $api->sync_contact($addData); if (is_wp_error($response)) { do_action('fluentform/integration_action_result', $feed, 'failed', $response->get_error_message()); return false; } else if ($response['result_code'] == 1) { do_action('fluentform/integration_action_result', $feed, 'success', __('Active Campaign has been successfully initialed and pushed data', 'fluentformpro')); if (ArrayHelper::get($feedData, 'note')) { // Contact Added $api->add_note($response['subscriber_id'], $list_id, ArrayHelper::get($feedData, 'note')); } return true; } do_action('fluentform/integration_action_result', $feed, 'failed', $response['result_message']); return false; } protected function getApiClient() { $settings = get_option($this->optionKey); return new ActiveCampaignApi( $settings['apiUrl'], $settings['apiKey'] ); } } PK!iT""5src/Integrations/ActiveCampaign/ActiveCampaignApi.phpnu[apiUrl = $apiUrl; $this->apiKey = $apiKey; } public function default_options() { return array( 'api_key' => $this->apiKey, 'api_output' => 'json' ); } public function make_request( $action, $options = array(), $method = 'GET' ) { /* Build request options string. */ $request_options = $this->default_options(); $request_options['api_action'] = $action; if ( $request_options['api_action'] == 'contact_edit' ) $request_options['overwrite'] = '0'; $request_options = http_build_query( $request_options ); $request_options .= ( $method == 'GET' ) ? '&' . http_build_query( $options ) : null; /* Build request URL. */ $request_url = untrailingslashit( $this->apiUrl ) . '/admin/api.php?' . $request_options; /* Execute request based on method. */ switch ( $method ) { case 'POST': $args = array( 'body' => $options ); $response = wp_remote_post( $request_url, $args ); break; case 'GET': $response = wp_remote_get( $request_url ); break; } /* If WP_Error, die. Otherwise, return decoded JSON. */ if ( is_wp_error( $response ) ) { return $response; } else { return json_decode( $response['body'], true ); } } /** * Test the provided API credentials. * * @access public * @return bool */ public function auth_test() { /* Build options string. */ $request_options = $this->default_options(); $request_options['api_action'] = 'list_paginator'; $request_options = http_build_query( $request_options ); /* Setup request URL. */ $request_url = untrailingslashit( $this->apiUrl ) . '/admin/api.php?' . $request_options; /* Execute request. */ $response = wp_remote_get( $request_url ); /* If invalid content type, API URL is invalid. */ if ( is_wp_error( $response ) || strpos( $response['headers']['content-type'], 'application/json' ) != 0 && strpos( $response['headers']['content-type'], 'application/json' ) > 0 ) throw new \Exception( 'Invalid API URL.' ); /* If result code is false, API key is invalid. */ $response['body'] = json_decode( $response['body'], true ); if ( $response['body']['result_code'] == 0 ) { throw new \Exception( 'Invalid API Key.' ); } return true; } /** * Add a new custom list field. * * @access public * @param array $custom_field * @return array */ public function add_custom_field( $custom_field ) { return $this->make_request( 'list_field_add', $custom_field, 'POST' ); } /** * Get all custom list fields. * * @access public * @return array */ public function get_custom_fields() { return $this->make_request( 'list_field_view', array( 'ids' => 'all' ) ); } /** * Get all forms in the system. * * @access public * @return array */ public function get_forms() { return $this->make_request( 'form_getforms' ); } /** * Get specific list. * * @access public * @param int $list_id * @return array */ public function get_list( $list_id ) { return $this->make_request( 'list_view', array( 'id' => $list_id ) ); } /** * Get all lists in the system. * * @access public * @return array */ public function get_lists() { return $this->make_request( 'list_list', array( 'ids' => 'all' ) ); } /** * Add or edit a contact. * * @access public * @param mixed $contact * @return array */ public function sync_contact( $contact ) { return $this->make_request( 'contact_sync', $contact, 'POST' ); } /** * Add note to contact. */ function add_note( $contact_id, $list_id, $note ) { $request = array( 'id' => $contact_id, 'listid' => $list_id, 'note' => $note ); return $this->make_request( 'contact_note_add', $request, 'POST' ); } } PK!c11.src/Integrations/AffiliateWP/AffiliateWPFF.phpnu[isModuleEnabled(); add_filter('fluentform/global_addons', function ($addOns) use ($enabled) { $addOns['affiliateWp'] = [ 'title' => __('AffiliateWP', 'fluentformpro'), 'description' => __('Generate AffiliateWP referrals automatically when a customer is referred to your site via an affiliate link.', 'fluentformpro'), 'logo' => fluentFormMix('img/integrations/affiliatewp.png'), 'enabled' => ($enabled) ? 'yes' : 'no', 'config_url' => '', 'category' => 'crm' ]; return $addOns; }, 99); if (!$enabled) { return; } $this->initFormSettings(); /* Regular Payments */ add_action('fluentform/submission_inserted', [$this, 'addPendingReferral'], 99, 3); add_action('fluentform/process_payment', [$this, 'onProcesPayment'], 99, 6); add_action('fluentform/after_transaction_status_change', [$this, 'markReferralComplete'], 10, 3); add_action('fluentform/payment_refunded', [$this, 'revokeReferralOnRefund'], 10, 3); /* Subscription Payments */ add_action('fluentform/subscription_payment_canceled', [$this, 'revokeReferralOnRefund'], 10, 3); add_action('fluentform/subscription_payment_received', function ($subscription, $submission) { $this->markReferralComplete('paid', $submission, ''); }, 10, 2); add_action('fluentform/subscription_payment_active', function ($subscription, $submission) { $this->markReferralComplete('paid', $submission, ''); }, 10, 2); } public function onProcesPayment($submissionId, $submissionData, $form, $methodSettings, $subscriptionItems, $totalPayable) { $this->addPendingReferral($submissionId, $submissionData, $form, $totalPayable); } public function addPendingReferral($insertId, $formData, $form, $totalPayable = 0) { if (!self::isEnabledInForm($form->id)) { return; } if (!$this->was_referred() && empty($this->affiliate_id)) { return; } $settings = $this->getAffiliateWpSettings($form->id); $referralType = Arr::get($settings, 'selected_type', 'sale'); $this->referral_type = $referralType; $isAffiliateEmail = $this->isAffiliateEmail($formData, $form); if ($isAffiliateEmail) { $this->log('Referral not created because affiliate\'s own account was used.'); return; } $description = $form->title; $submission = $this->getSubmission($insertId); if ($totalPayable) { $amountInCents = $totalPayable; } else { $amountInCents = $submission->payment_total; } $totalPayment = number_format($amountInCents / 100); $referral_total = $this->calculate_referral_amount($totalPayment, $insertId); $formattedProducts = $this->getFormattedProducts($insertId); $this->insert_pending_referral($referral_total, $insertId, $description, $formattedProducts); if (empty($amountInCents) || $submission->payment_status == 'paid') { $referral = affiliate_wp()->referrals->get_by('reference', $insertId, $this->context); if (is_object($referral) && $referral->status != 'pending' && $referral->status != 'rejected') { // This referral has already been completed, or paid return false; } $this->complete_referral($insertId); $amount = affwp_currency_filter(affwp_format_amount($referral->amount)); $name = affiliate_wp()->affiliates->get_affiliate_name($referral->affiliate_id); $logData = [ 'parent_source_id' => $form->id, 'source_type' => 'submission_item', 'source_id' => $insertId, 'component' => 'AffiliateWP', 'status' => 'success', 'title' => __('Pushed Data to AffiliateWP', 'fluentformpro'), 'description' => sprintf( __('Referral #%1$d for %2$s recorded for %3$s (ID: %4$d).', 'fluentformpro'), $referral->referral_id, $amount, $name, $referral->affiliate_id ) ]; do_action('fluentform/log_data', $logData); } } public function markReferralComplete($newStatus, $submission, $transactionId) { if ($newStatus != 'paid') { return; } $referral = affiliate_wp()->referrals->get_by('reference', $submission->id, $this->context); if (!$referral) { return; } if (is_object($referral) && $referral->status != 'pending' && $referral->status != 'rejected') { // This referral has already been completed, or paid return false; } $this->complete_referral($submission->id); $amount = affwp_currency_filter(affwp_format_amount($referral->amount)); $name = affiliate_wp()->affiliates->get_affiliate_name($referral->affiliate_id); $logData = [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Affiliate Wp', 'status' => 'success', 'title' => __('Pushed Data to Affiliate WP', 'fluentformpro'), 'description' => sprintf( __('Referral #%1$d for %2$s recorded for %3$s (ID: %4$d).', 'fluentformpro'), $referral->referral_id, $amount, $name, $referral->affiliate_id ) ]; do_action('fluentform/log_data', $logData); } public function revokeReferralOnRefund($refund, $transaction, $submission) { $this->reject_referral($submission->id); $referral = affiliate_wp()->referrals->get_by('reference', $submission->id, $this->context); $amount = affwp_currency_filter(affwp_format_amount($referral->amount)); $name = affiliate_wp()->affiliates->get_affiliate_name($referral->affiliate_id); $note = sprintf( __('Referral #%d for %s for %s rejected', 'fluentformpro'), $referral->referral_id, $amount, $name ); $logData = [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Affiliate Wp', 'status' => 'success', 'title' => __('Pushed Data to Affiliate WP', 'fluentformpro'), 'description' => $note ]; do_action('fluentform/log_data', $logData); } public function referenceLink($reference, $referral) { if (empty($referral->context) || 'fluentforms' != $referral->context) { return $reference; } $submission = $this->getSubmission($reference); if (!$submission) { return; } $url = admin_url('admin.php?page=fluent_forms&route=entries&form_id=' . $submission->form_id . '#/entries/' . $submission->id); return '' . $reference . ''; } public function getSubmission($submissionId) { $submission = wpFluent()->table('fluentform_submissions') ->where('id', $submissionId) ->first(); if (!$submission) { return false; } $submission->response = json_decode($submission->response, true); return $submission; } public function getAffiliateWpSettings($formId) { $defaults = [ 'types' => affiliate_wp()->referrals->types_registry->get_types(), 'selected_type' => 'sale', 'status' => 'no', ]; $settings = Helper::getFormMeta($formId, 'affiliate_wp'); return wp_parse_args($settings, $defaults); } public static function isEnabledInForm($formId) { $settings = Helper::getFormMeta($formId, 'affiliate_wp'); return Arr::get($settings, 'status') == 'yes'; } public function isModuleEnabled() { $globalModules = get_option('fluentform_global_modules_status'); $affiliateWp = Arr::get($globalModules, 'affiliateWp'); if ($affiliateWp == 'yes') { return true; } return false; } public function getEmails($formData, $form) { $emailInput = FormFieldsParser::getInputsByElementTypes($form, ['input_email']); $formData = FormDataParser::parseData((object)$formData, $emailInput, $form->id); if (!empty($formData)) { array_values($formData); } return false; } public function getLastTransaction($submissionId) { return wpFluent()->table('fluentform_transactions') ->where('submission_id', $submissionId) ->orderBy('id', 'DESC') ->first(); } public function get_customer($entry_id = 0) { $lastTransaction = $this->getLastTransaction($entry_id); if (!$lastTransaction) { $fullName = ''; $email = ''; } else { $fullName = $lastTransaction->payer_name; $email = $lastTransaction->payer_email; } if (empty($fullName)) { $firstname = ''; $lastname = ''; } else { $nameArray = explode(' ', $fullName); $lastname = end($nameArray); $firstname = str_replace($lastname, '', $fullName); } return [ 'first_name' => $firstname, 'last_name' => $lastname, 'email' => $email, 'ip' => affiliate_wp()->tracking->get_ip(), ]; } public function isAffiliateEmail($formData, $form) { $emails = $this->getEmails($formData, $form); if (!$emails) { return false; } foreach ($emails as $customer_email) { if ($this->is_affiliate_email($customer_email, $this->affiliate_id)) { return true; } } return false; } /** * Get Formatted Products * * @param $insertId * @return array */ public function getFormattedProducts($insertId) { $submission = $this->getSubmission($insertId); $products = OrderData::getOrderItems($submission); $formattedProducts = []; foreach ($products as $product) { $formattedProducts[] = $product->item_name . ' - ' . $product->formatted_item_price . ' x ' . $product->quantity; } return $formattedProducts; } /** * Handle affiliate settings of the form */ public function initFormSettings() { add_action('fluentform/after_save_form_settings', function ($formId, $allSettings) { $settings = Arr::get($allSettings, 'affiliate_wp', []); if ($settings) { Helper::setFormMeta($formId, 'affiliate_wp', $settings); } }, 10, 2); add_filter('fluentform/form_settings_ajax', function ($settings, $formId) { if ($affiliateWPSettings = $this->getAffiliateWpSettings($formId)) { $settings['affiliate_wp'] = $affiliateWPSettings; } return $settings; }, 10, 2); } public function plugin_is_active() { return true; } } PK! CNN'src/Integrations/Airtable/Bootstrap.phpnu[logo = fluentFormMix('img/integrations/airtable.png'); $this->description = "Airtable is a low-code platform for building collaborative apps. Customize your workflow, collaborate, and achieve ambitious outcomes."; $this->registerAdminHooks(); add_filter( 'fluentform/get_integration_values_' . $this->integrationKey, [$this, 'resolveIntegrationSettings'], 10, 3 ); add_filter( 'fluentform/save_integration_value_' . $this->integrationKey, [$this, 'validate'], 10, 3 ); } public function resolveIntegrationSettings($settings, $feed, $formId) { $configs = $this->app->request->get('configs', ''); $baseId = ArrayHelper::get($configs, 'base_id'); $tableId = ArrayHelper::get($configs, 'table_id'); if ($baseId) { $settings['chained_config']['base_id'] = $baseId; } if ($tableId) { $settings['chained_config']['table_id'] = $tableId; } return $settings; } public function validate($settings, $integrationId, $formId) { $error = false; $errors = []; $baseId = ArrayHelper::get($settings, 'chained_config' . '.' . 'base_id'); $tableId = ArrayHelper::get($settings, 'chained_config' . '.' . 'table_id'); $fields = $this->getFields($baseId, $tableId); if (isset($fields['status']) && $fields['status'] === false) { wp_send_json_error([ 'message' => __($fields['message'], 'fluentformpro'), 'errors' => [] ], 423); } foreach ($fields as $field) { if ($field['required'] && empty($settings[$field['key']])) { $error = true; $errors[$field['key']] = [__($field['label'] . ' is required', 'fluentformpro')]; } } if ($error) { wp_send_json_error([ 'message' => __('Validation Failed', 'fluentformpro'), 'errors' => $errors ], 423); } return $settings; } public function getRemoteClient() { $settings = $this->getGlobalSettings([]); return new API( $settings ); } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'api_key' => '', 'base_id' => '', 'table_id' => '', 'status' => false, ]; return wp_parse_args($globalSettings, $defaults); } public function getGlobalFields($fields) { return [ 'logo' => $this->logo, 'menu_title' => __('Airtable Settings', 'fluentformpro'), 'menu_description' => __($this->description, 'fluentformpro'), 'valid_message' => __('Your Airtable API Key is valid', 'fluentformpro'), 'invalid_message' => __('Your Airtable API Key is not valid', 'fluentformpro'), 'save_button_text' => __('Save Settings', 'fluentformpro'), 'config_instruction' => __($this->getConfigInstructions(), 'fluentformpro'), 'fields' => [ 'api_key' => [ 'type' => 'password', 'placeholder' => __('Airtable API Key', 'fluentformpro'), 'label_tips' => __('Enter your Airtable API Key', 'fluentformpro'), 'label' => __('Airtable API Key', 'fluentformpro'), ], 'base_id' => [ 'type' => 'text', 'placeholder' => __('Airtable Base ID', 'fluentformpro'), 'label_tips' => __('Enter your Airtable Base ID', 'fluentformpro'), 'label' => __('Airtable Base ID', 'fluentformpro'), ], 'table_id' => [ 'type' => 'text', 'placeholder' => __('Airtable Table ID', 'fluentformpro'), 'label_tips' => __('Enter your Airtable Table ID', 'fluentformpro'), 'label' => __('Airtable Table ID', 'fluentformpro'), ], ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your Airtable API integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect Airtable', 'fluentformpro'), 'data' => [ 'api_key' => '', ], 'show_verify' => true ] ]; } protected function getConfigInstructions() { $newAirtableLink = admin_url('admin.php?page=fluent_forms_settings#general-airtable_v2-settings'); ob_start(); ?>

    Airtable announces Personal API keys will be deprecated by the end of January 2024. So we will close this Airtable integration after January 2024. Please use new airtable integration from here.

    1. Go Here and copy your API key and paste it.
    2. Go Here and select your desired Airtable base and then copy the ID of this base and paste it as Base ID. Then scroll to Table section and select your desired Airtable table under selected base and then copy the ID of this table and paste it as Table ID.
    3. If you want to implement multiple bases or tables, then just paste Base IDs or Table IDs on their respective fields by separating them with commas(,). Then select them your desired Base and Table combination from respected Fluent Form integration.
    4. You have to fill all of fields of any single row in Airtable to integrate with Fluent Form. If there is any blank column in the row, blank columns will be skipped. You must ensure that there is at least one row in the table that contains no blank column.
    '', 'base_id' => '', 'table_id' => '', 'status' => false ]; update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_error([ 'message' => __('Please provide all fields to integrate', 'fluentformpro'), 'status' => false ], 423); } $integrationSettings = [ 'api_key' => $settings['api_key'], 'base_id' => $settings['base_id'], 'table_id' => $settings['table_id'], 'status' => true ]; update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your Airtable API key has been verified and successfully set', 'fluentformpro'), 'status' => true ], 200); } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => $this->title . ' Integration', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-airtable-settings'), 'configure_message' => __('Airtable is not configured yet! Please configure your Airtable api first', 'fluentformpro'), 'configure_button_text' => __('Set Airtable API', 'fluentformpro') ]; return $integrations; } public function getIntegrationDefaults($settings, $formId) { $config = $this->app->request->get('configs'); $baseId = ArrayHelper::get($config, 'base_id'); $tableId = ArrayHelper::get($config, 'table_id'); return [ 'name' => '', 'chained_config' => [ 'base_id' => $baseId, 'table_id' => $tableId, ], 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { $fieldSettings = [ 'fields' => [ [ 'key' => 'name', 'label' => __('Feed Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'chained_config', 'label' => __('Airtable Configuration', 'fluentformpro'), 'required' => true, 'component' => 'chained-ajax-fields', 'options_labels' => [ 'base_id' => [ 'placeholder' => __('Select Base', 'fluentformpro'), 'options' => $this->getBases() ], 'table_id' => [ 'placeholder' => __('Select Table', 'fluentformpro'), 'options' => $this->getTables() ], ] ], ], 'button_require_list' => false, 'integration_title' => $this->title ]; $config = $this->app->request->get('configs', ArrayHelper::get($settings, 'chained_config')); $baseId = $config['base_id']; $tableId = $config['table_id']; $error = false; $message = ''; if ($baseId && $tableId) { $fields = $this->getFields($baseId, $tableId); if (isset($fields['status']) && $fields['status'] === false) { $error = true; $message = $fields['message']; } if (!$error) { $fields = array_merge($fieldSettings['fields'], $fields); $fieldSettings['fields'] = $fields; } } $fieldSettings['fields'] = array_merge($fieldSettings['fields'], [ [ 'require_list' => false, 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow this integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => false, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable this feed', 'fluentformpro') ] ]); if ($error) { wp_send_json_error([ 'settings_fields' => $fieldSettings, 'message' => __($message, 'fluentform'), 'status' => false ], 423); } return $fieldSettings; } public function getMergeFields($list, $listId, $formId) { return false; } protected function getFields($baseId, $tableId) { $fields = []; $client = $this->getRemoteClient(); if ( ! $this->isConfigured()) { return [ 'message' => __('Not configured.', 'fluentformpro'), 'status' => false ]; } try { $lists = $client->makeRequest('https://api.airtable.com/v0/' . $baseId . '/' . $tableId, null); if ( ! $lists) { return [ 'message' => __('No Record Found.', 'fluentformpro'), 'status' => false ]; } } catch (\Exception $exception) { return [ 'message' => $exception->getMessage(), 'status' => false ];; } if (is_wp_error($lists)) { return [ 'message' => __('Please select valid Base and Table field combination.', 'fluentformpro'), 'status' => false ]; } $empty = true; foreach ($lists['records'] as $index => $records) { if ( ! empty($lists['records'][$index]['fields'])) { $empty = false; break; } } if ($empty) { return [ 'message' => __('Your base table is empty. You must ensure that there is at least one row in the table that contains no blank column.', 'fluentformpro'), 'status' => false ]; } $customList = []; $maxKeyCount = 0; $desiredKey = 0; foreach ($lists['records'] as $fieldKey => $fieldValues) { if ($maxKeyCount < count($fieldValues['fields'])) { $maxKeyCount = count($fieldValues['fields']); $desiredKey = $fieldKey; } } foreach ($lists['records'][$desiredKey]['fields'] as $fieldKey => $fieldValues) { if (is_array($fieldValues)) { if (array_key_exists('name', $fieldValues) && array_key_exists('email', $fieldValues)) { $customList['key'] = 'collab_' . $fieldKey; $customList['label'] = __('Enter ' . $fieldKey, 'fluentformpro'); $customList['required'] = false; $customList['tips'] = __('Enter ' . $fieldKey . ' value or choose form input provided by shortcode.', 'fluentformpro'); $customList['component'] = 'value_text'; } else { foreach ($fieldValues as $value) { if ( ! empty(ArrayHelper::get($value, 'url'))) { $customList['key'] = 'url_' . $fieldKey; } else { $customList['key'] = 'array_' . $fieldKey; } $customList['label'] = __('Enter ' . $fieldKey, 'fluentformpro'); $customList['required'] = false; $customList['tips'] = __('Enter ' . $fieldKey . ' value or choose form input provided by shortcode.', 'fluentformpro'); $customList['component'] = 'value_text'; } } } else { if ($fieldValues == 'true' || $fieldValues == 'false') { $customList['key'] = 'boolean_' . $fieldKey; } else { $customList['key'] = 'normal_' . $fieldKey; } $customList['component'] = 'value_text'; $customList['label'] = __('Enter ' . $fieldKey, 'fluentformpro'); $customList['required'] = false; $customList['tips'] = __('Enter ' . $fieldKey . ' value or choose form input provided by shortcode.', 'fluentformpro'); } $fields[] = $customList; } return $fields; } protected function getBases() { $client = $this->getRemoteClient(); if ( ! $this->isConfigured()) { return false; } return $client->baseIdArray; } protected function getTables() { $client = $this->getRemoteClient(); if ( ! $this->isConfigured()) { return false; } return $client->tableIdArray; } public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; $subscriber = []; $records['records'] = []; $baseId = $feedData['chained_config']['base_id']; $tableId = $feedData['chained_config']['table_id']; $fields = $this->getFields($baseId, $tableId); foreach ($fields as $index => $field) { $key = ArrayHelper::get($field, 'key'); $value = ArrayHelper::get($feedData, $key); if (!empty($value)) { $fieldArray = explode('_', $key); $fieldType = $fieldArray[0]; $fieldName = $fieldArray[1]; if ($fieldType == 'normal') { $subscriber[$fieldName] = $value; } elseif ($fieldType == 'boolean') { if ($value == 'true' || $value == 'yes') { $value = true; } elseif ($value == 'false' || $value == 'no') { $value = false; } $subscriber[$fieldName] = $value; } elseif ($fieldType == 'url') { $arrayValues = array_map('trim', explode(',', $value)); $subscriber[$fieldName] = []; foreach ($arrayValues as $urlValue) { $subscriber[$fieldName][] = ['url' => $urlValue]; } } elseif ($fieldType == 'array') { $arrayValues = array_map('trim', explode(',', $value)); $subscriber[$fieldName] = $arrayValues; } elseif ($fieldType == 'collab') { if (is_email($value)) { $subscriber[$fieldName] = ['email' => $value]; } } } } $subscriber = Helper::replaceBrTag($subscriber); $records['records'][] = ['fields' => $subscriber]; $client = $this->getRemoteClient(); $response = $client->subscribe($records, $baseId, $tableId); if (!is_wp_error($response)) { do_action('fluentform/integration_action_result', $feed, 'success', 'Airtable feed has been successfully initialed and pushed data'); } else { $error = $response->get_error_message(); do_action('fluentform/integration_action_result', $feed, 'failed', $error); } } } PK!d*U U !src/Integrations/Airtable/API.phpnu[apiKey = $settings['api_key']; $tempBaseIds = explode(',', $settings['base_id']); foreach ($tempBaseIds as $value) { $this->baseIdArray[trim($value)] = trim($value); } $tempTableIds = explode(',', $settings['table_id']); foreach ($tempTableIds as $value) { $this->tableIdArray[trim($value)] = trim($value); } } public function getApiKey() { return [ 'api_key' => 'Bearer ' . $this->apiKey, ]; } public function makeRequest($url, $bodyArgs = [], $type = 'GET') { $apiKey = $this->getApiKey(); $request = []; if ($type == 'GET') { $request = wp_remote_get($url, [ 'headers' => [ 'Content-Type' => 'application/json', 'Accept' => 'application/json', 'Authorization' => $apiKey['api_key'], ] ]); } if ($type == 'POST') { $request = wp_remote_post($url, [ 'headers' => [ 'Content-Type' => 'application/json', 'Accept' => 'application/json', 'Authorization' => $apiKey['api_key'], ], 'body' => $bodyArgs ]); } if (is_wp_error($request)) { $code = $request->get_error_code(); $message = $request->get_error_message(); return new \WP_Error($code, $message); } $body = wp_remote_retrieve_body($request); $body = \json_decode($body, true); $code = wp_remote_retrieve_response_code($request); if ($code == 200 || $code == 201) { return $body; } else { if (is_string($body['error'])) { return new \WP_Error($code, __('Error: Please provide valid Airtable Base ID.', 'fluentformpro')); } return new \WP_Error($code, $body['error']['type'] .': '. $body['error']['message']); } } public function subscribe($subscriber, $baseId, $tableId) { $url = 'https://api.airtable.com/v0/'. $baseId .'/' . $tableId; $post = \json_encode($subscriber, JSON_NUMERIC_CHECK); return $this->makeRequest($url, $post, 'POST'); } } PK!!gg%src/Integrations/Amocrm/Bootstrap.phpnu[logo = fluentFormMix('img/integrations/amocrm.png'); $this->description = 'It can be a great way to manage your leads and tasks with amoCRM and Fluent Forms.'; $this->registerAdminHooks(); add_action('admin_init', function () { if (isset($_REQUEST['ff_amocrm_auth'])) { $client = $this->getRemoteClient(); if(isset($_REQUEST['code'])) { $code = sanitize_text_field($_REQUEST['code']); $referer = sanitize_text_field($_REQUEST['referer']); $settings = $this->getGlobalSettings([]); $settings = $client->generateAccessToken($code, $referer, $settings); if (!is_wp_error($settings)) { $settings['status'] = true; update_option($this->optionKey, $settings, 'no'); } wp_redirect(admin_url('admin.php?page=fluent_forms_settings#general-amocrm-settings')); exit(); } else { $client->redirectToAuthServer(); } die(); } }); add_filter( 'fluentform/get_integration_values_amocrm', [$this, 'resolveIntegrationSettings'], 10, 3 ); add_filter( 'fluentform/save_integration_value_' . $this->integrationKey, [$this, 'validate'], 10, 3 ); } public function resolveIntegrationSettings($settings, $feed, $formId) { $serviceName = $this->app->request->get('serviceName', ''); $serviceId = $this->app->request->get('serviceId', ''); if ($serviceName) { $settings['name'] = $serviceName; } if ($serviceId) { $settings['list_id'] = $serviceId; } return $settings; } public function validate($settings, $integrationId, $formId) { $error = false; $errors = []; foreach ($this->getFields($settings['list_id']) as $field) { if ($field['required'] && empty($settings[$field['key']])) { $error = true; $errors[$field['key']] = [__($field['label'] . ' is required', 'fluentformpro')]; } } if ($error) { wp_send_json_error([ 'message' => __('Validation Failed', 'fluentformpro'), 'errors' => $errors ], 423); } return $settings; } public function getRemoteClient() { $settings = $this->getGlobalSettings([]); return new API($settings); } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'client_id' => '', 'client_secret' => '', 'status' => false, 'access_token' => '', 'refresh_token' => '', 'referer_url' => '' ]; return wp_parse_args($globalSettings, $defaults); } public function getGlobalFields($fields) { return [ 'logo' => $this->logo, 'menu_title' => __('Amocrm Settings', 'fluentformpro'), 'menu_description' => __($this->description, 'fluentformpro'), 'valid_message' => __('Your Amocrm Secret Key is valid', 'fluentformpro'), 'invalid_message' => __('Your Amocrm Secret Key is not valid', 'fluentformpro'), 'save_button_text' => __('Save Settings', 'fluentformpro'), 'config_instruction' => $this->getConfigInstructions(), 'fields' => [ 'client_id' => [ 'type' => 'text', 'placeholder' => __('Amocrm Integration ID', 'fluentformpro'), 'label_tips' => __('Enter your Amocrm Integration ID', 'fluentformpro'), 'label' => __('Amocrm Integration ID', 'fluentformpro'), ], 'client_secret' => [ 'type' => 'password', 'placeholder' => __('Amocrm Integration Secret Key', 'fluentformpro'), 'label_tips' => __('Enter your Amocrm Integration Secret Key', 'fluentformpro'), 'label' => __('Amocrm Secret Key', 'fluentformpro'), ], ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your Amocrm API integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect Amocrm', 'fluentformpro'), 'data' => [ 'client_id' => '', 'client_secret' => '', 'access_token' => '', ], 'show_verify' => true ] ]; } protected function getConfigInstructions() { $authLink = admin_url('?ff_amocrm_auth=true'); ob_start(); ?>
    1. Open Settings -> Integrations -> Then from upper right side click on the button Create Integration.
    2. Set the redirect URL as then check the Allow access: All.
      Set your Integration Name and give a short description and save the settings.
    3. Under private integrations find your integration. Click on the integration and go to Keys and scopes. Here you will find Secret key and Integration ID.
    '', 'client_secret' => '', 'access_token' => '', 'status' => false ]; // Update the details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your settings has been updated', 'fluentformpro'), 'status' => false ], 200); } try { $oldSettings = $this->getGlobalSettings([]); $oldSettings['client_id'] = sanitize_text_field($settings['client_id']); $oldSettings['client_secret'] = sanitize_text_field($settings['client_secret']); $oldSettings['status'] = false; update_option($this->optionKey, $oldSettings, 'no'); wp_send_json_success([ 'message' => __('You are redirect to authenticate', 'fluentformpro'), 'redirect_url' => admin_url('?ff_amocrm_auth=true') ], 200); } catch (\Exception $exception) { wp_send_json_error([ 'message' => $exception->getMessage() ], 400); } } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => $this->title . ' Integration', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-amocrm-settings'), 'configure_message' => __('Amocrm is not configured yet! Please configure your Amocrm api first', 'fluentformpro'), 'configure_button_text' => __('Set Amocrm API', 'fluentformpro') ]; return $integrations; } public function getIntegrationDefaults($settings, $formId) { $listId = $this->app->request->get('serviceId'); return [ 'name' => '', 'list_id' => $listId, 'fields' => [ [ 'item_value' => '', 'label' => '' ] ], 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { $fieldSettings = [ 'fields' => [ [ 'key' => 'name', 'label' => __('Feed Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'list_id', 'label' => __('Amocrm Services', 'fluentformpro'), 'placeholder' => __('Select Amocrm Service', 'fluentformpro'), 'required' => true, 'component' => 'refresh', 'options' => $this->getLists() ], ], 'button_require_list' => false, 'integration_title' => $this->title ]; $listId = $this->app->request->get('serviceId', ArrayHelper::get($settings, 'list_id')); if ($listId) { $fields = $this->getFields($listId); if (empty($fields)) { wp_send_json_error([ 'message' => __("The selected service doesn't have any field settings.", 'fluentformpro'), ], 423); } $fields = array_merge($fieldSettings['fields'], $fields); $fieldSettings['fields'] = $fields; } $fieldSettings['fields'] = array_merge($fieldSettings['fields'], [ [ 'require_list' => false, 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow this integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => false, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable this feed', 'fluentformpro') ] ]); return $fieldSettings; } protected function getLists() { $lists = [ 'leads' => 'Lead', 'companies' => 'Company', 'contacts' => 'Contact', 'catalogs' => 'List', 'tasks' => 'Task' ]; $client = $this->getRemoteClient(); $settings = $this->getGlobalSettings([]); $url = 'https://' . $settings['referer_url'] . '/api/v4/catalogs'; try { $elements = $client->makeRequest($url, null); if (!$elements) { return $lists; } } catch (\Exception $exception) { return false; } if (is_wp_error($elements)) { $error = $elements->get_error_message(); $code = $elements->get_error_code(); wp_send_json_error([ 'message' => __($error, 'fluentformpro') ], $code); } foreach ($elements['_embedded']['catalogs'] as $catalog) { $lists['elements_' . $catalog['id']] = $catalog['name']; } return $lists; } public function getMergeFields($list, $listId, $formId) { return false; } public function getFields($listId) { $settings = $this->getGlobalSettings([]); $mergedFields = []; switch ($listId) { case 'leads': $mergedFields = [ [ 'key' => 'leads_name', 'placeholder' => __('Enter Lead Name', 'fluentformpro'), 'label' => __('Lead Name', 'fluentformpro'), 'required' => true, 'tips' => __('Lead name is a required string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'price', 'placeholder' => __('Lead Sale', 'fluentformpro'), 'label' => __('Lead Sale', 'fluentformpro'), 'required' => false, 'tips' => __('Lead Sale is a int type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'unix_created_at', 'placeholder' => __('Created at', 'fluentformpro'), 'label' => __('Created at', 'fluentformpro'), 'required' => false, 'tips' => __('Created at is a Date type field in Unix Timestamp format.', 'fluentformpro'), 'component' => 'datetime' ], [ 'key' => 'unix_closed_at', 'placeholder' => __('Closed at', 'fluentformpro'), 'label' => __('Closed at', 'fluentformpro'), 'required' => false, 'tips' => __('Closed at is a Date type field in Unix Timestamp format.', 'fluentformpro'), 'component' => 'datetime' ], ]; $url = 'https://' . $settings['referer_url'] . '/api/v4/leads/custom_fields'; $customFields = $this->getCustomFields($url); $mergedFields = array_merge($mergedFields, $customFields); break; case 'companies': $mergedFields = [ [ 'key' => 'companies_name', 'placeholder' => __('Enter Company Name', 'fluentformpro'), 'label' => __('Company Name', 'fluentformpro'), 'required' => true, 'tips' => __('Company name is a required string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'unix_created_at', 'placeholder' => __('Created at', 'fluentformpro'), 'label' => __('Created at', 'fluentformpro'), 'required' => false, 'tips' => __('Created at is a Date type field in Unix Timestamp format.', 'fluentformpro'), 'component' => 'datetime' ] ]; $url = 'https://' . $settings['referer_url'] . '/api/v4/companies/custom_fields'; $customFields = $this->getCustomFields($url); $mergedFields = array_merge($mergedFields, $customFields); break; case 'contacts': $mergedFields = [ [ 'key' => 'contacts_name', 'placeholder' => __('Enter Contacts Name', 'fluentformpro'), 'label' => __('Contacts Name', 'fluentformpro'), 'required' => true, 'tips' => __('Contacts name is a required string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'first_name', 'placeholder' => __('Enter First Name', 'fluentformpro'), 'label' => __('First Name', 'fluentformpro'), 'required' => false, 'tips' => __('First name is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'last_name', 'placeholder' => __('Enter Last Name', 'fluentformpro'), 'label' => __('Last Name', 'fluentformpro'), 'required' => false, 'tips' => __('Last name is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'unix_created_at', 'placeholder' => __('Created at', 'fluentformpro'), 'label' => __('Created at', 'fluentformpro'), 'required' => false, 'tips' => __('Created at is a Date type field in Unix Timestamp format.', 'fluentformpro'), 'component' => 'datetime' ] ]; $url = 'https://' . $settings['referer_url'] . '/api/v4/contacts/custom_fields'; $customFields = $this->getCustomFields($url); $mergedFields = array_merge($mergedFields, $customFields); break; case 'catalogs': $mergedFields = [ [ 'key' => 'catalogs_name', 'placeholder' => __('Enter List Name', 'fluentformpro'), 'label' => __('List Name', 'fluentformpro'), 'required' => true, 'tips' => __('List name is a required string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'can_add_elements', 'label' => __('Add elements to the list', 'fluentformpro'), 'required' => false, 'tips' => __('Add elements to the list is a bool type field.', 'fluentformpro'), 'component' => 'radio_choice', 'options' => [ 'true' => __('yes', 'fluentformpro'), 'false' => __('no', 'fluentformpro') ] ], [ 'key' => 'can_link_multiple', 'label' => __('Link elements to multiple list', 'fluentformpro'), 'required' => false, 'tips' => __('Link elements can to the multiple list is a bool type field.', 'fluentformpro'), 'component' => 'radio_choice', 'options' => [ 'true' => __('yes', 'fluentformpro'), 'false' => __('no', 'fluentformpro') ] ] ]; break; case 'tasks': $mergedFields = [ [ 'key' => 'tasks_name', 'placeholder' => __('Enter Task Name', 'fluentformpro'), 'label' => __('Task Name', 'fluentformpro'), 'required' => true, 'tips' => __('Task name is a required string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'tasks_entity_type', 'placeholder' => __('Enter Task Entity Type', 'fluentformpro'), 'label' => __('Task Entity Type', 'fluentformpro'), 'required' => false, 'tips' => __('Task Entity Type is a select type field.', 'fluentformpro'), 'component' => 'select', 'options' => [ 'leads' => 'Lead', 'contacts' => 'Contact', 'companies' => 'Company', 'customers' => 'Customer' ] ], [ 'key' => 'text', 'placeholder' => __('Enter Task Details', 'fluentformpro'), 'label' => __('Task Details', 'fluentformpro'), 'required' => true, 'tips' => __('Task Details is a required string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'tasks_duration', 'placeholder' => __('Enter Task Duration', 'fluentformpro'), 'label' => __('Task Duration', 'fluentformpro'), 'required' => false, 'tips' => __('Task Duration is a int type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'tasks_result[text]', 'placeholder' => __('Enter Task Result Details', 'fluentformpro'), 'label' => __('Task Result Details', 'fluentformpro'), 'required' => false, 'tips' => __('Task Details is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'is_completed', 'label' => __('Is Task Completed', 'fluentformpro'), 'required' => false, 'tips' => __('Is Task Completed is a bool type field.', 'fluentformpro'), 'component' => 'radio_choice', 'options' => [ 'true' => __('yes', 'fluentformpro'), 'false' => __('no', 'fluentformpro') ] ], [ 'key' => 'unix_complete_till', 'placeholder' => __('Complete At', 'fluentformpro'), 'label' => __('Complete at', 'fluentformpro'), 'required' => true, 'tips' => __('Complete at is a Required Date type field in Unix Timestamp format.', 'fluentformpro'), 'component' => 'datetime' ] ]; break; case 'customers': $mergedFields = [ [ 'key' => 'customers_name', 'placeholder' => __('Enter Customer Name', 'fluentformpro'), 'label' => __('Customer Name', 'fluentformpro'), 'required' => true, 'tips' => __('Customer name is a required string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'next_price', 'placeholder' => __('Enter Expected purchase value', 'fluentformpro'), 'label' => __('Enter Expected purchase value', 'fluentformpro'), 'required' => false, 'tips' => __('Expected purchase value is a required number type field.', 'fluentformpro'), 'component' => 'value_text' ], ]; $url = 'https://' . $settings['referer_url'] . '/api/v4/customers/custom_fields'; $customFields = $this->getCustomFields($url); $mergedFields = array_merge($mergedFields, $customFields); break; default: $mergedFields = [ [ 'key' => 'elements_name', 'placeholder' => __('Enter List element name' , 'fluentformpro'), 'label' => __('List element name', 'fluentformpro'), 'required' => true, 'tips' => __('List element name is a required string type field.', 'fluentformpro'), 'component' => 'value_text', ] ]; $listNumber = ''; if (strpos($listId, 'elements') !== false) { $listNumber = explode('_', $listId)[1]; } $url = 'https://' . $settings['referer_url'] . '/api/v4/catalogs/' . $listNumber . '/custom_fields'; $customFields = $this->getCustomFields($url); $mergedFields = array_merge($mergedFields, $customFields); } return $mergedFields; } protected function getCustomFields($url) { $client = $this->getRemoteClient(); try { $lists = $client->makeRequest($url, null); if (!$lists) { return []; } } catch (\Exception $exception) { return false; } if (is_wp_error($lists)) { $error = $lists->get_error_message(); $code = $lists->get_error_code(); wp_send_json_error([ 'message' => __($error, 'fluentformpro') ], $code); } $customFields = []; foreach ($lists['_embedded']['custom_fields'] as $field) { if($enums = ArrayHelper::get($field, 'enums')) { $data = [ 'key' => 'custom*' . $field['id'] . '*select*' . $field['name'], 'placeholder' => __($field['name'] . ' Type', 'fluentformpro'), 'label' => __($field['name'] . ' Type', 'fluentformpro'), 'required' => false, 'tips' => __($field['name'] . ' is a ' .$field['type']. ' type of field.', 'fluentformpro'), 'component' => 'select' ]; $options = []; foreach ($enums as $option) { $options[$option['value']] = $option['value']; } $data['options'] = $options; array_push($customFields, $data); if($field['code'] == 'PHONE' || $field['code'] == 'EMAIL') { $data = [ 'key' => 'custom*' . $field['id'] . '*text*' . $field['code'], 'placeholder' => __($field['name'], 'fluentformpro'), 'label' => __($field['name'], 'fluentformpro'), 'required' => false, 'tips' => __($field['name'] . ' is a string type of field.', 'fluentformpro'), 'component' => 'value_text' ]; array_push($customFields, $data); } } elseif ($field['type'] == 'checkbox') { $data = [ 'key' => 'custom*' . $field['id'] . '*checkbox*' . $field['name'], 'label' => __('Is Discussable', 'fluentformpro'), 'required' => false, 'tips' => __('Is discussable is a bool type field.', 'fluentformpro'), 'component' => 'radio_choice', 'options' => [ 'true' => __('yes', 'fluentformpro'), 'false' => __('no', 'fluentformpro') ] ]; array_push($customFields, $data); } else { $data = [ 'key' => 'custom*' . $field['id'] . '*normal*' . $field['name'], 'placeholder' => __($field['name'], 'fluentformpro'), 'label' => __($field['name'], 'fluentformpro'), 'required' => false, 'tips' => __($field['name'] . ' is a ' .$field['type']. ' type of field.', 'fluentformpro'), 'component' => 'value_text' ]; array_push($customFields, $data); } } return $customFields; } protected function getAllFields($listId) { $fields = $this->getFields($listId); $allFields = []; foreach ($fields as $field) { $keyData = []; $keyData['key'] = $field['key']; if ($field['required']) { $keyData['required'] = $field['required']; array_push($allFields, $keyData); } else { $keyData['required'] = 0; array_push($allFields, $keyData); } } return $allFields; } public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; $subscriber = []; $subscriber['list_id'] = $feedData['list_id']; if (strpos($feedData['list_id'], 'elements') !== false) { $listArray = explode('_', $feedData['list_id']); $subscriber['type'] = $listArray[0]; $subscriber['list_id'] = $listArray[1]; } if ($subscriber['list_id'] == 'tags') { $subscriber['entity_id'] = $feedData['entity_id']; unset($feedData['entity_id']); } $allFields = $this->getAllFields($feedData['list_id']); $subscriber['attributes']['custom_fields_values'] = []; $enumCode = ''; foreach ($allFields as $field) { $key = $field['key']; if (!empty($feedData[$key])) { if (strpos($key, 'name') !== false) { $subscriber['attributes']['name'] = ArrayHelper::get($feedData, $key); } elseif(strpos($key, 'can_') !== false) { if ($feedData[$key] == 'true') { $subscriber['attributes'][$key] = true; } else { $subscriber['attributes'][$key] = false; } } elseif(strpos($key, 'is_') !== false) { if ($feedData[$key] == 'true') { $subscriber['attributes'][$key] = true; } else { $subscriber['attributes'][$key] = false; } } elseif(strpos($key, 'unix_') !== false) { $dateField = explode('unix_', $key); $dateFieldKey = $dateField[1]; $subscriber['attributes'][$dateFieldKey] = strtotime(ArrayHelper::get($feedData, $key)); } elseif (strpos($key, 'custom*') !== false) { $customField = explode('*', $key); $fieldId = $customField[1]; $fieldType = $customField[2]; $fieldName = $customField[3]; if($fieldType == 'select') { if($fieldName == 'Unit') { $customFields = [ 'field_id' => $fieldId, 'values' => [ [ 'value' => ArrayHelper::get($feedData, $key) ] ] ]; } else { $enumCode = ArrayHelper::get($feedData, $key); continue; } } if($fieldType == 'text') { $customFields = [ 'field_code' => $fieldName, 'values' => [ [ 'enum_code' => $enumCode, 'value' => ArrayHelper::get($feedData, $key) ] ] ]; } if($fieldType == 'normal') { $customFields = [ 'field_id' => $fieldId, 'values' => [ [ 'value' => ArrayHelper::get($feedData, $key) ] ] ]; } if($fieldType == 'checkbox') { if ($feedData[$key] == 'true') { $checkboxValue = true; } else { $checkboxValue = false; } $customFields = [ 'field_id' => $fieldId, 'values' => [ [ 'value' => $checkboxValue ] ] ]; } array_push($subscriber['attributes']['custom_fields_values'], $customFields); } else { $subscriber['attributes'][$key] = ArrayHelper::get($feedData, $key); } } } if (empty($subscriber['attributes']['custom_fields_values'])) { unset($subscriber['attributes']['custom_fields_values']); } $client = $this->getRemoteClient(); $response = $client->subscribe($subscriber); if (!is_wp_error($response)) { do_action('fluentform/integration_action_result', $feed, 'success', __('Amocrm feed has been successfully initiated and pushed data', 'fluentformpro')); } else { $error = $response->get_error_message(); do_action('fluentform/integration_action_result', $feed, 'failed', $error); } } } PK!;,9src/Integrations/Amocrm/API.phpnu[clientId = $settings['client_id']; $this->clientSecret = $settings['client_secret']; $this->accessToken = $settings['access_token']; $this->redirectUrl = admin_url('?ff_amocrm_auth=true'); $this->settings = $settings; } public function redirectToAuthServer() { $url = 'https://www.amocrm.com/oauth?client_id='. $this->clientId .'&mode=post_message'; wp_redirect($url); exit(); } public function generateAccessToken($code, $referer, $settings) { $this->refererUrl = $referer; $response = wp_remote_post('https://'. $this->refererUrl . '/oauth2/access_token', [ 'body' => [ 'client_id' => $this->clientId, 'client_secret' => $this->clientSecret, 'grant_type' => 'authorization_code', 'redirect_uri' => $this->redirectUrl, 'code' => $code ] ] ); if (is_wp_error($response)) { return $response; } $body = wp_remote_retrieve_body($response); $body = \json_decode($body, true); $code = wp_remote_retrieve_response_code($response); if ($code >= 400 && $code <= 403) { return new \WP_Error($body['status'], $body['title'] . ': ' . $body['hint']); } $settings['access_token'] = $body['access_token']; $settings['refresh_token'] = $body['refresh_token']; $settings['referer_url'] = $referer; $settings['expire_at'] = time() + intval($body['expires_in']); return $settings; } protected function getApiSettings() { $refresh = $this->maybeRefreshToken(); if(is_wp_error($refresh)) { $code = $refresh->get_error_code(); $message = $refresh->get_error_message(); return new \WP_Error($code, $message); } $apiSettings = $this->settings; if (!$apiSettings['status'] || !$apiSettings['expire_at']) { return new \WP_Error('Invalid', __('API key is invalid', 'fluentformpro')); } return [ 'client_id' => $this->clientId, 'client_secret' => $this->clientSecret, 'redirect_url' => $this->redirectUrl, 'access_token' => $this->settings['access_token'], 'refresh_token' => $this->settings['refresh_token'], 'referer_url' => $this->settings['referer_url'] ]; } protected function maybeRefreshToken() { $settings = $this->settings; $expireAt = $settings['expire_at']; if ($expireAt && $expireAt <= (time() - 30)) { $response = wp_remote_post('https://'. $settings['referer_url'] . '/oauth2/access_token', [ 'body' => [ 'client_id' => $this->clientId, 'client_secret' => $this->clientSecret, 'grant_type' => 'refresh_token', 'refresh_token' => $this->settings['refresh_token'], 'redirect_uri' => $this->redirectUrl ] ]); if (is_wp_error($response)) { return $response; } $body = wp_remote_retrieve_body($response); $body = \json_decode($body, true); $code = wp_remote_retrieve_response_code($response); if ($code >= 400 && $code <= 403) { return new \WP_Error($body['status'], $body['title'] . ': ' . $body['detail']); } $this->settings['access_token'] = $body['access_token']; $this->settings['refresh_token'] = $body['refresh_token']; } } public function makeRequest($url, $bodyArgs, $type = 'GET') { $apiSettings = $this->getApiSettings(); if (is_wp_error($apiSettings)) { $code = $apiSettings->get_error_code(); $message = $apiSettings->get_error_message(); return new \WP_Error($code, $message); } $this->accessToken = $apiSettings['access_token']; $request = []; if ($type == 'GET') { $request = wp_remote_get($url, [ 'headers' => [ 'Authorization' => " Bearer ". $this->accessToken, ] ]); } if ($type == 'POST') { $request = wp_remote_post($url, [ 'headers' => [ 'Authorization' => " Bearer ". $this->accessToken, 'Content-Type' => 'application/json' ], 'body' => $bodyArgs ]); } if (is_wp_error($request)) { $code = $request->get_error_code(); $message = $request->get_error_message(); return new \WP_Error($code, $message); } $body = wp_remote_retrieve_body($request); $body = \json_decode($body, true); $code = wp_remote_retrieve_response_code($request); if ($code >= 200 && $code <= 299) { return $body; } elseif ($code == 401 || $code == 403) { return new \WP_Error($code, $body['title'] . ': ' .$body['detail']); } else { $errors = $body['validation-errors'][0]['errors'][0]; return new \WP_Error($code, $errors['path'] . ' is ' .$errors['code']. '. Hint: ' .$errors['detail']); } } public function subscribe($subscriber) { $url = 'https://' . $this->settings['referer_url'] . '/api/v4/' . $subscriber['list_id']; if(ArrayHelper::get($subscriber, 'type')) { $url = 'https://' . $this->settings['referer_url'] . '/api/v4/catalogs/' . $subscriber['list_id'] . '/' .$subscriber['type']; } if(ArrayHelper::get($subscriber, 'entity_id')) { $url = 'https://' . $this->settings['referer_url'] . '/api/v4/' . $subscriber['entity_id'] . '/tags'; } $post = \json_encode([$subscriber['attributes']], JSON_NUMERIC_CHECK); return $this->makeRequest($url, $post, 'POST'); } } PK!TVS:S:'src/Integrations/Automizy/Bootstrap.phpnu[logo = fluentFormMix('img/integrations/automizy.png'); $this->description = 'Connect Automizy with Fluent Forms and subscribe a contact when a form is submitted.'; $this->registerAdminHooks(); // add_filter('fluentform/notifying_async_automizy', '__return_false'); } public function getGlobalFields($fields) { return [ 'logo' => $this->logo, 'menu_title' => __('Automizy API Settings', 'fluentformpro'), 'menu_description' => __('Automizy is email marketing software. Use Fluent Forms to collect customer information and automatically add it as Automizy subscriber list. Get API Token', 'fluentformpro'), 'valid_message' => __('Your Automizy API Key is valid', 'fluentformpro'), 'invalid_message' => __('Your Automizy API Key is not valid', 'fluentformpro'), 'save_button_text' => __('Save Settings', 'fluentformpro'), 'fields' => [ 'apiKey' => [ 'type' => 'text', 'placeholder' => __('API Token', 'fluentformpro'), 'label_tips' => __("Enter your Automizy API Key, if you do not have
    Please login to your Automizy account and go to
    Account -> Settings -> Api Token", 'fluentformpro'), 'label' => __('Automizy API Token', 'fluentformpro'), ] ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your Automizy API integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect Automizy', 'fluentformpro'), 'data' => [ 'apiKey' => '' ], 'show_verify' => true ] ]; } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'apiKey' => '', 'status' => '' ]; return wp_parse_args($globalSettings, $defaults); } public function saveGlobalSettings($settings) { if (!$settings['apiKey']) { $integrationSettings = [ 'apiKey' => '', 'status' => false ]; // Update the reCaptcha details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your settings has been updated', 'fluentformpro'), 'status' => false ], 200); } // Verify API key now try { $api = new API($settings['apiKey']); $result = $api->auth_test(); if (!empty($result['error'])) { throw new \Exception($result['message']); } } catch (\Exception $exception) { wp_send_json_error([ 'message' => $exception->getMessage(), 'status' => false ], 400); } // Integration key is verified now, Proceed now $integrationSettings = [ 'apiKey' => sanitize_text_field($settings['apiKey']), 'status' => true ]; // Update the reCaptcha details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your Automizy api key has been verified and successfully set', 'fluentformpro'), 'status' => true ], 200); } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => $this->title . ' Integration', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-automizy-settings'), 'configure_message' => __('Automizy is not configured yet! Please configure your Automizy api first', 'fluentformpro'), 'configure_button_text' => __('Set Automizy API', 'fluentformpro') ]; return $integrations; } public function getIntegrationDefaults($settings, $formId) { return [ 'name' => '', 'SubscriberFirstName' => '', 'SubscriberLastName' => '', 'Email' => '', 'CustomFields' => (object)[], 'other_fields_mapping' => [ [ 'item_value' => '', 'label' => '' ] ], 'list_id' => '', // Automizy 'tags' => '', 'tag_routers' => [], 'tag_ids_selection_type' => 'simple', 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { return [ 'fields' => [ [ 'key' => 'name', 'label' => __('Feed Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'list_id', 'required' => true, 'label' => __('Automizy Mailing Lists', 'fluentformpro'), 'placeholder' => __('Select Automizy Mailing List', 'fluentformpro'), 'tips' => __('Select the Automizy Mailing List you would like to add your contacts to.', 'fluentformpro'), 'component' => 'select', 'options' => $this->getLists(), ], [ 'key' => 'CustomFields', 'require_list' => false, 'label' => __('Primary Fields', 'fluentformpro'), 'tips' => __('Associate your Automizy merge tags to the appropriate Fluent Forms fields by selecting the appropriate form field from the list.', 'fluentformpro'), 'component' => 'map_fields', 'field_label_remote' => __('Automizy Field', 'fluentformpro'), 'field_label_local' => __('Form Field', 'fluentformpro'), 'primary_fileds' => [ [ 'key' => 'Email', 'label' => __('Email Address', 'fluentformpro'), 'required' => true, 'input_options' => 'emails' ], [ 'key' => 'SubscriberFirstName', 'label' => __('First Name', 'fluentformpro') ], [ 'key' => 'SubscriberLastName', 'label' => __('Last Name', 'fluentformpro') ] ] ], [ 'key' => 'other_fields_mapping', 'require_list' => false, 'label' => __('Custom Fields', 'fluentformpro'), 'remote_text' => __('Automizy Field', 'fluentformpro'), 'tips' => __('Select which Fluent Forms fields pair with their
    respective Automizy fields.', 'fluentformpro'), 'component' => 'dropdown_many_fields', 'local_text' => 'Form Field', 'options' => $this->getCustomFields() ], [ 'key' => 'tags', 'require_list' => true, 'label' => __('Tags', 'fluentformpro'), 'tips' => __('Associate tags to your Automizy contacts with a comma separated list (e.g. new lead, FluentForms, web source). Commas within a merge tag value will be created as a single tag.', 'fluentformpro'), 'component' => 'selection_routing', 'simple_component' => 'value_text', 'routing_input_type' => 'text', 'routing_key' => 'tag_ids_selection_type', 'settings_key' => 'tag_routers', 'labels' => [ 'choice_label' => __('Enable Dynamic Tag Input', 'fluentformpro'), 'input_label' => '', 'input_placeholder' => __('Tag', 'fluentformpro') ], 'inline_tip' => __('Please provide each tag by comma separated value', 'fluentformpro') ], [ 'require_list' => false, 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow Automizy integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => false, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable This feed', 'fluentformpro') ] ], 'button_require_list' => false, 'integration_title' => $this->title ]; } public function getMergeFields($list, $listId, $formId) { return []; } private function getCustomFields() { $api = $this->getApiInstance(); $fields = $api->getCustomFields(); $formattedFields = []; foreach ($fields as $field) { $formattedFields[$field['name']] = $field['label']; } unset($formattedFields['firstname']); unset($formattedFields['lastname']); return $formattedFields; } protected function getLists() { $api = $this->getApiInstance(); $lists = $api->getLists(); $formattedLists = []; foreach ($lists as $list) { $formattedLists[$list['id']] = $list['name']; } return $formattedLists; } /* * Form Submission Hooks Here */ public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; $listId = ArrayHelper::get($feedData, 'list_id'); if (!$listId) { do_action('fluentform/integration_action_result', $feed, 'failed', __('Automizy API call has been skipped because no valid List available', 'fluentformpro')); } if (!is_email($feedData['Email'])) { $feedData['Email'] = ArrayHelper::get($formData, $feedData['Email']); } if (!is_email($feedData['Email'])) { do_action('fluentform/integration_action_result', $feed, 'failed', 'Automizy API call has been skipped because no valid email available'); return; } $subscriber = [ 'email' => $feedData['Email'] ]; $customFields = [ 'firstname' => ArrayHelper::get($feedData, 'SubscriberFirstName'), 'lastname' => ArrayHelper::get($feedData, 'SubscriberLastName'), ]; foreach ($feedData['other_fields_mapping'] as $field) { if (!empty($field['item_value'])) { $customFields[$field['label']] = $field['item_value']; } } $customFields = array_filter($customFields); if ($customFields) { $subscriber['customFields'] = $customFields; } $tags = $this->getSelectedTagIds($feedData, $formData, 'tags'); if(!is_array($tags)) { $tags = explode(',', $tags); } $tags = array_map('trim', $tags); $tags = array_filter($tags); if ($tags) { $subscriber['tags'] = implode(',', $tags); } $subscriber = array_filter($subscriber); $subscriber = apply_filters_deprecated( 'fluentform_integration_data_' . $this->integrationKey, [ $subscriber, $feed, $entry ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/integration_data_' . $this->integrationKey, 'Use fluentform/integration_data_' . $this->integrationKey . ' instead of fluentform_integration_data_' . $this->integrationKey ); $subscriber = apply_filters('fluentform/integration_data_' . $this->integrationKey, $subscriber, $feed, $entry); $api = $this->getApiInstance(); $result = $api->subscribe($listId, $subscriber); if (!empty($result['error'])) { $message = !empty($result['message']) ? $result['message'] : 'Automizy API call has been failed'; do_action('fluentform/integration_action_result', $feed, 'failed', $message); } else { do_action('fluentform/integration_action_result', $feed, 'success', __('Automizy feed has been successfully initialed and pushed data', 'fluentformpro')); } } protected function getApiInstance() { $settings = $this->getApiSettings(); return new API($settings['apiKey']); } } PK!?[ !src/Integrations/Automizy/API.phpnu[apiKey = $apiKey; } public function default_options() { return array( 'apikey' => $this->apiKey ); } public function make_request($action, $options = array(), $method = 'GET') { /* Build request options string. */ $request_options = $this->default_options(); $request_options = wp_parse_args($options, $request_options); $options_string = http_build_query($request_options); /* Build request URL. */ $request_url = $this->apiUrl . $action; /* Execute request based on method. */ switch ($method) { case 'POST': $request_url = $this->apiUrl.$action; $args = []; $args['body'] = json_encode($options); $args['method'] = 'POST'; $args['headers'] = [ 'Content-Type' => 'application/json', 'Accept' => 'application/json', 'Authorization' => 'Bearer '.$this->apiKey ]; $response = wp_remote_post($request_url, $args); break; case 'GET': $args['headers'] = [ 'Content-Type' => 'application/json', 'Accept' => 'application/json', 'Authorization' => 'Bearer '.$this->apiKey ]; $response = wp_remote_get($request_url, $args); break; } /* If WP_Error, die. Otherwise, return decoded JSON. */ if (is_wp_error($response)) { return [ 'error' => 'API_Error', 'message' => $response->get_error_message() ]; } else if($response['response']['code'] < 300) { return json_decode($response['body'], true); } else { return [ 'error' => 'API_Error', 'message' => $response['response']['message'] ]; } } /** * Test the provided API credentials. * * @access public * @return bool */ public function auth_test() { return $this->make_request('smart-lists',[], 'GET'); } public function subscribe($listId, $data) { return $this->make_request('smart-lists/'.$listId.'/contacts', $data, 'POST'); } /** * Get all Forms in the system. * * @access public * @return array */ public function getLists() { $response = $this->make_request('smart-lists', [], 'GET'); if (!empty($response['error'])) { return []; } return $response['smartLists']; } public function getCustomFields() { $response = $this->make_request('custom-fields', [], 'GET'); if (!empty($response['error'])) { return []; } return $response['customFields']; } } PK!7@@%src/Integrations/Aweber/Bootstrap.phpnu[optionKey); $this->logo = fluentFormMix('img/integrations/aweber.png'); $this->description = 'Fluent Forms Aweber Module allows you to create Aweber list signup forms in WordPress, so you can grow your email list.'; $this->registerAdminHooks(); //add_filter('fluentform/notifying_async_aweber', '__return_false'); } public function getGlobalFields($fields) { return [ 'logo' => $this->logo, 'menu_title' => __('AWeber API Settings', 'fluentformpro'), 'menu_description' => __('AWeber is an integrated email marketing, marketing automation, and small business CRM. Save time while growing your business with sales automation. Use Fluent Forms to collect customer information and automatically add it to your Aweber list. If you don\'t have an Aweber account, you can sign up for one here.', 'fluentformpro'), 'valid_message' => __('Your Aweber configuration is valid', 'fluentformpro'), 'invalid_message' => __('Your Aweber configuration is invalid', 'fluentformpro'), 'save_button_text' => __('Save Settings', 'fluentformpro'), 'config_instruction' => $this->getConfigInstractions(), 'fields' => [ 'authorizeCode' => [ 'type' => 'password', 'placeholder' => __('Access token', 'fluentformpro'), 'label_tips' => __("Enter your Aweber Access token, if you do not have
    Please click on the get Access token", 'fluentformpro'), 'label' => __('Aweber Access Token', 'fluentformpro'), ] ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your Aweber API integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect Aweber', 'fluentformpro'), 'data' => [ 'authorizeCode' => '' ], 'show_verify' => true ] ]; } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'authorizeCode' => '', 'access_token' => '', 'refresh_token' => '', 'status' => '', 'expires_at' => null ]; return wp_parse_args($globalSettings, $defaults); } public function saveGlobalSettings($settings) { if (!$settings['authorizeCode']) { $integrationSettings = [ 'authorizeCode' => '', 'access_token' => '', 'refresh_token' => '', 'status' => false, 'expires_at' => null ]; // Update the details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your settings has been updated and discarted', 'fluentformpro'), 'status' => false ], 200); } try { $settings['status'] = false; update_option($this->optionKey, $settings, 'no'); $api = new AweberApi($settings); $auth = $api->auth_test(); if (isset($auth['refresh_token'])) { $settings['status'] = true; $settings['access_token'] = $auth['access_token']; $settings['refresh_token'] = $auth['refresh_token']; $settings['expires_at'] = time() + intval($auth['expires_in']);; update_option($this->optionKey, $settings, 'no'); wp_send_json_success([ 'status' => true, 'message' => __('Your settings has been updated!', 'fluentformpro') ], 200); } throw new \Exception(__('Invalid Credentials', 'fluentformpro'), 400); } catch (\Exception $e) { wp_send_json_error([ 'status' => false, 'message' => $e->getMessage() ], $e->getCode()); } } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => $this->title . ' Integration', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-aweber-settings'), 'configure_message' => __('Aweber is not configured yet! Please configure your Aweber API first', 'fluentformpro'), 'configure_button_text' => __('Set Aweber API', 'fluentformpro') ]; return $integrations; } protected function getConfigInstractions() { ob_start(); ?>

    To Authenticate AWeber you need an access token.

    1. Click here to Get Access Token.
    2. Then login and allow with your AWeber account.
    3. Copy your access token and paste bellow field then click Verify AWeber.
    '', 'list_id' => '', 'fieldEmailAddress' => '', 'custom_field_mappings' => (object)[], 'default_fields' => (object)[], 'other_fields_mapping' => [ [ 'item_value' => '', 'label' => '' ] ], 'ip_address' => '{ip}', 'tags' => [], 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { return [ 'fields' => [ [ 'key' => 'name', 'label' => __('Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], // [ // 'key' => 'list_id', // 'label' => 'Aweber Segment', // 'placeholder' => 'Select Aweber Segment', // 'tips' => 'Select the Aweber segment you would like to add your contacts to.', // 'component' => 'list_ajax_options', // 'options' => $this->getLists() // ], [ 'key' => 'custom_field_mappings', // 'require_list' => true, 'label' => __('Map Fields', 'fluentformpro'), 'tips' => __('Select which Fluent Forms fields pair with their
    respective Aweber fields.', 'fluentformpro'), 'component' => 'map_fields', 'field_label_remote' => __('Aweber Field', 'fluentformpro'), 'field_label_local' => __('Form Field', 'fluentformpro'), 'primary_fileds' => [ [ 'key' => 'fieldEmailAddress', 'label' => __('Email Address', 'fluentformpro'), 'required' => true, 'input_options' => 'emails' ] ], 'default_fields' => [ array( 'name' => 'first_name', 'label' => esc_html__('First Name', 'fluentformpro'), 'required' => false ), array( 'name' => 'last_name', 'label' => esc_html__('Last Name', 'fluentformpro'), 'required' => false ), array( 'name' => 'phone', 'label' => esc_html__('Phone Number', 'fluentformpro'), 'required' => false ) ] ], [ 'key' => 'other_fields_mapping', // 'require_list' => true, 'label' => __('Other Fields', 'fluentformpro'), 'tips' => __('Select which Fluent Forms fields pair with their
    respective Aweber fields.', 'fluentformpro'), 'component' => 'dropdown_many_fields', 'field_label_remote' => __('Aweber Field', 'fluentformpro'), 'field_label_local' => __('Form Field', 'fluentformpro'), 'options' => [ 'company' => __('Company Name', 'fluentformpro'), 'address' => __('Address Line 1', 'fluentformpro'), 'address2' => __('Address Line 2', 'fluentformpro'), 'city' => __('City', 'fluentformpro'), 'state' => __('State', 'fluentformpro'), 'zip' => __('ZIP code', 'fluentformpro'), 'country' => __('Country', 'fluentformpro'), 'fax' => __('Fax', 'fluentformpro'), 'sms_number' => __('SMS Number', 'fluentformpro'), 'phone' => __('Phone', 'fluentformpro'), 'birthday' => __('Birthday', 'fluentformpro'), 'website' => __('Website', 'fluentformpro'), ] ], [ 'key' => 'note', // 'require_list' => true, 'label' => __('Note', 'fluentformpro'), 'placeholder' => __('write a note for this contact', 'fluentformpro'), 'tips' => __('You can write a note for this contact', 'fluentformpro'), 'component' => 'value_textarea' ], [ // 'require_list' => true, 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow Aweber integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ // 'require_list' => true, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable This feed', 'fluentformpro'), ] ], // 'button_require_list' => true, 'integration_title' => $this->title ]; } protected function getLists() { // $api = $this->getApiClient(); // if (!$api) { // return []; // } // $lists = $api->getLists(); // $formattedLists = []; // foreach ($lists as $list) { // if (is_array($list)) { // $formattedLists[$list['id']] = $list['name']; // } // } return $formattedLists= ['list']; } // getting available tags public function getMergeFields($list, $listId, $formId) { $api = $this->getApiClient(); $fields = $api->getCustomFields(); $formattedFileds = []; foreach ($fields as $field) { $formattedFileds['cf_'.$field['alias'].'_'.$field['id']] = $field['name']; } return $formattedFileds; } public function getAuthenticateUri() { $api = $this->getApiClient(); return $api->makeAuthorizationUrl(); } /* * Submission Broadcast Handler */ public function notify($feed, $formData, $entry, $form) { $api = $this->getApiClient(); $response = $api->addContact($feed); // die $feedData = $feed['processedValues']; if (!is_email($feedData['fieldEmailAddress'])) { $feedData['fieldEmailAddress'] = ArrayHelper::get($formData, $feedData['fieldEmailAddress']); } if (!is_email($feedData['fieldEmailAddress'])) { return; } $addData = []; $addData = array_merge($addData, ArrayHelper::get($feedData, 'default_fields')); if(ArrayHelper::get($feedData, 'custom_field_mappings')){ $addData = array_merge($addData, ArrayHelper::get($feedData, 'custom_field_mappings')); } foreach (ArrayHelper::get($feedData, 'other_fields_mapping') as $item) { $addData[$item['label']] = $item['item_value']; } $tags = implode(",", $feedData['tags']); if ($tags) { $addData['tag'] = $tags; } $addData['segment'] = $feedData['list_id']; $addData['ip'] = $feedData['ip_address']; $addData = array_filter($addData); $addData['email'] = $feedData['fieldEmailAddress']; $addData['time'] = time(); // Now let's prepare the data and push to hubspot $api = $this->getApiClient(); $response = $api->addContact($addData); $logData = [ 'parent_source_id' => $form->id, 'source_type' => 'submission_item', 'source_id' => $entry->id, 'component' => $this->integrationKey, 'status' => 'success', 'title' => $feed['settings']['name'], 'description' => 'Aweber feed has been successfully initialed and pushed data' ]; if (!is_wp_error($response) && $response['status'] === 'success') { do_action('fluentform/log_data', $logData); } else { $logData = [ 'parent_source_id' => $form->id, 'source_type' => 'submission_item', 'source_id' => $entry->id, 'component' => $this->integrationKey, 'status' => 'failed', 'title' => $feed['settings']['name'], 'description' => is_wp_error($response) ? $response->get_error_messages() : 'API Error when submitting Data' ]; // Contact adding failed do_action('fluentform/log_data', $logData); } } protected function getApiClient() { $settings = get_option($this->optionKey); return new AweberApi( $settings ); } } PK!qZZ%src/Integrations/Aweber/AweberApi.phpnu[authorizeCode = $authorizeCode; if($access_token && $refresh_token){ $this->accessToken = $access_token; $this->refreshToken = $refresh_token; } } // To get the authorization url for authorization code public function makeAuthorizationUrl() { $attr = [ 'response_type'=>'code', 'client_id' => $this->clientId, 'redirect_uri' => $this->$redirectUri, 'scope' => ['account.read', 'list.read', 'subscriber.read','subscriber.write', 'email.read','email.write','subscriber.read-extended'], 'state' => $this->clientSecret, // 'code_challenge'=> 'challenge', // 'code_challenge_method'=> 'S256' ]; $paramString = http_build_query($attr); return $url = $this->apiUrl . 'authorize' . '?' . $paramString; } // All request will go through this function public function getAccessToken($resource, $data = array(), $method = 'POST') { $requestApi = $this->apiUrl . $resource; $args = array( 'headers' => array( 'Accept' => 'application/json', ), 'body' => $data ); $response = wp_remote_post($requestApi, $args); /* If WP_Error, die. Otherwise, return decoded JSON. */ if (is_wp_error($response)) { return [ 'error' => 'failed', 'message' => $response->get_error_message() ]; } return json_decode($response['body'], true); } /** * Test the provided access token, refress token info. * * @access public * @return Array */ public function auth_test() { $resource = 'token'; $data = array( 'grant_type' => 'authorization_code', 'code' => $this->authorizeCode, "client_id" => $this->clientId, "client_secret" => $this->clientSecret ); return $this->getAccessToken($resource, $data, 'POST'); } public function make_request($path, $data=[], $method='GET' ) { $url = 'https://api.aweber.com/1.0/' . $path; $args = array( 'headers' => array( 'Accept' => 'application/json', 'Authorization' => 'Bearer nBR12pahFmg80vKnaPs20D9fMjLyCurO' ), 'body' => $data ); if($method == 'GET') { // $url = add_query_arg($data, $url); $response = wp_remote_get($url,$args); } else if($method == 'POST') { $response = wp_remote_post($url, [ 'body' => $data ]); } return $response; } // public function makeAuthString() // { // $userCredentials = $this->clientId . ':' . $this->clientSecret; // return $authstring = 'Basic ' . base64_encode($userCredentials); // } // private function getApiUrl($resource, $data = []) // { // if ($data) { // $paramString = http_build_query($data); // } // return $this->apiUrl . $resource['path'] . '?' . $paramString; // } public function getLists() { $lists = $this->make_request([ ], 'POST'); if(!empty($lists['error'])) { return []; } return $lists; } public function getTags() { $tags = $this->make_request([ ], 'POST'); if(!empty($tags['error'])) { return []; } return $tags; } public function getCustomFields() { $customFields = $this->make_request([ ], 'POST'); if(!empty($tags['error'])) { return []; } return $customFields; } public function addContact($contact) { $response = $this->make_request('accounts', [], $method='GET'); return new \WP_Error('error', $response['message']); } }PK! %h9src/Integrations/BuddyIntegration/FluentFormBuddyBoss.phpnu[ '', 'item_value' => '' ] ]; $defaults['bboss_profile_type'] = ''; return $defaults; } public function pushSettingsFields($fields) { $groupField = false; if (function_exists('bp_xprofile_get_groups')) { $profileFields = []; $groups = bp_xprofile_get_groups( array( 'fetch_fields' => true ) ); foreach ($groups as $group) { foreach ($group->fields as $field) { $profileFields[$field->id . ' '] = $field->name; // We need to key as string so adding an extra space } } $groupField = [ 'key' => 'bboss_profile_fields', 'label' => __('Profile Fields', 'fluentformpro'), 'component' => 'dropdown_many_fields', 'options' => $profileFields, 'remote_text' => __('X-Profile Field', 'fluentformpro'), 'local_text' => __('Form Field', 'fluentformpro'), 'tips' => __('Map your BuddyBoss x-profile fields with your form fields', 'fluentformpro') ]; } $memberTypeFields = false; if (function_exists('bp_get_member_types')) { $profileTypes = []; $member_types = bp_get_member_types(array(), 'objects'); foreach ($member_types as $typeName => $member_type) { $profileTypes[$typeName] = $member_type->labels['name']; } if ($profileTypes) { $memberTypeFields = [ 'key' => 'bboss_profile_type', 'label' => __('BuddyBoss Profile Type', 'fluentformpro'), 'component' => 'select', 'options' => $profileTypes, 'tips' => __('Select BuddyBoss Profile Type', 'fluentformpro') ]; } } if ($groupField || $memberTypeFields) { $fields[] = [ 'key' => 'html_info', 'label' => '', 'component' => 'html_info', 'html_info' => __('

    BuddyPress / BuddyBoss Settings


    ', 'fluentformpro') ]; } if ($groupField) { $fields[] = $groupField; } if ($memberTypeFields) { $fields[] = $memberTypeFields; } return $fields; } /* * This function will be called once user registration has been completed */ public function saveDataToUser($userId, $feed, $entry) { $xProfileFields = \FluentForm\Framework\Helpers\ArrayHelper::get($feed, 'processedValues.bboss_profile_fields', []); $parsedXFields = []; foreach ($xProfileFields as $xProfileField) { if (!empty($xProfileField['item_value'])) { $fieldId = intval($xProfileField['label']); $parsedXFields[$fieldId] = esc_html($xProfileField['item_value']); } } if ($parsedXFields) { $this->setXProfileFields($userId, $parsedXFields); } $profileTypeSlug = \FluentForm\Framework\Helpers\ArrayHelper::get($feed, 'processedValues.bboss_profile_type'); if ($profileTypeSlug) { $this->setProfileType($userId, $profileTypeSlug, $entry); } } private function setProfileType($userId, $profileSlug, $entry) { bp_set_member_type($userId, $profileSlug); $logData = [ 'title' => __('BuddyBoss Profile has been created - User Id: ', 'fluentformpro') . $userId, 'status' => 'success', 'description' => __('Profile has been created in BuddyBoss. Profile Type: ', 'fluentformpro') . $profileSlug, 'parent_source_id' => $entry->form_id, 'source_id' => $entry->id, 'component' => 'UserRegistration', 'source_type' => 'submission_item' ]; do_action('fluentform/log_data', $logData); } private function setXProfileFields($userId, $fields) { foreach ($fields as $fieldKey => $value) { if ($fieldKey == bp_xprofile_nickname_field_id()) { update_user_meta($userId, 'nickname', $value); //sync wp user nickname with buddyBoss } if ( strpos($value, ', ') !== false && $field_type = \BP_XProfile_Field::get_type( $fieldKey )) { if ( $field_type == 'checkbox') { $value = explode(', ', $value); } } xprofile_set_field_data($fieldKey, $userId, $value); } } } PK!488.src/Integrations/CampaignMonitor/Bootstrap.phpnu[logo = fluentFormMix('img/integrations/campaignmonitor.png'); $this->description = 'Create Campaign Monitor newsletter signup forms in WordPress, and streamline your email marketing.'; $this->registerAdminHooks(); // add_filter('fluentform/notifying_async_campaign_monitor', '__return_false'); } public function getGlobalFields($fields) { $clients = $this->getClients(); return [ 'logo' => $this->logo, 'menu_title' => __('Campaign Monitor API Settings', 'fluentformpro'), 'menu_description' => __('Campaign Monitor drives results with email marketing. It shares how to gain loyal customers with personalized email campaigns and automated customer journeys. Use Fluent Forms to collect customer information and automatically add it to your Campaign Monitor list. If you don\'t have an Campaign Monitor account, you can sign up for one here.', 'fluentformpro'), 'valid_message' => __('Your Campaign Monitor configuration is valid', 'fluentformpro'), 'invalid_message' => __('Your Campaign Monitor configuration is invalid', 'fluentformpro'), 'save_button_text' => __('Save Settings', 'fluentformpro'), 'fields' => [ 'apiKey' => [ 'type' => 'password', 'placeholder' => __('API Key', 'fluentformpro'), 'label_tips' => __("Enter your Campaign Monitor API Key, if you do not have
    Please log in to your Campaign Monitor account and find the api key", 'fluentformpro'), 'label' => __('Campaign Monitor API Key', 'fluentformpro'), ], 'clientId' => [ 'type' => 'select', 'hide_on_empty' => true, 'placeholder' => __('Select Client', 'fluentformpro'), 'label_tips' => __("Select the Campaign Monitor client that you want to connect this site", 'fluentformpro'), 'label' => __('Campaign Monitor Client', 'fluentformpro'), 'options' => $clients ] ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your Campaign Monitor API integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect Campaign Monitor', 'fluentformpro'), 'data' => [ 'apiKey' => '' ], 'show_verify' => true ], 'reload_on_save' => true ]; } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'apiKey' => '', 'status' => '', 'clientId' => '' ]; return wp_parse_args($globalSettings, $defaults); } public function saveGlobalSettings($settings) { if (!$settings['apiKey']) { $integrationSettings = [ 'apiKey' => '', 'clientId' => '', 'status' => false ]; // Update the reCaptcha details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your settings has been updated and discarded', 'fluentformpro'), 'status' => false ], 200); } try { $settings['status'] = false; $settings['apiKey'] = sanitize_text_field($settings['apiKey']); update_option($this->optionKey, $settings, 'no'); (new CampaignMonitorApi($settings['apiKey']))->auth_test(); $settings['status'] = true; $message = __('Your settings has been updated', 'fluentformpro'); if (!$settings['clientId']) { $settings['status'] = false; $message = __('Please Select Client Now', 'fluentformpro'); } update_option($this->optionKey, $settings, 'no'); wp_send_json_success([ 'message' => $message, 'status' => $settings['status'] ], 200); } catch (\Exception $e) { wp_send_json_error([ 'message' => $e->getMessage(), 'status' => false ], 400); } } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => $this->title . ' Integration', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-campaign_monitor-settings'), 'configure_message' => __('Campaign Monitor is not configured yet! Please configure your Campaign Monitor api first', 'fluentformpro'), 'configure_button_text' => __('Set Campaign Monitor API', 'fluentformpro') ]; return $integrations; } public function getIntegrationDefaults($settings, $formId) { return [ 'name' => '', 'list_id' => '', 'fieldEmailAddress' => '', 'fullName' => '', 'custom_fields' => (object)[], 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'resubscribe' => false, 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { return [ 'fields' => [ [ 'key' => 'name', 'label' => __('Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'list_id', 'label' => __('Campaign Monitor List', 'fluentformpro'), 'placeholder' => __('Select Campaign Monitor Mailing List', 'fluentformpro'), 'tips' => __('Select the Campaign Monitor Mailing List you would like to add your contacts to.', 'fluentformpro'), 'component' => 'list_ajax_options', 'options' => $this->getLists(), ], [ 'key' => 'custom_fields', 'require_list' => true, 'label' => __('Map Fields', 'fluentformpro'), 'tips' => __('Select which Fluent Forms fields pair with their
    respective Campaign Monitor fields.', 'fluentformpro'), 'component' => 'map_fields', 'field_label_remote' => __('Campaign Monitor Field', 'fluentformpro'), 'field_label_local' => __('Form Field', 'fluentformpro'), 'primary_fileds' => [ [ 'key' => 'fieldEmailAddress', 'label' => __('Email Address', 'fluentformpro'), 'required' => true, 'input_options' => 'emails' ], [ 'key' => 'fullName', 'label' => __('Full Name', 'fluentformpro') ] ] ], [ 'key' => 'resubscribe', 'require_list' => true, 'label' => __('Resubscribe', 'fluentformpro'), 'tips' => __('When this option is enabled, if the subscriber is in an inactive state or
    has previously been unsubscribed, they will be re-added to the active list.
    Therefore, this option should be used with caution and only when appropriate.', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable ReSubscription', 'fluentformpro') ], [ 'require_list' => true, 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow Campaign Monitor integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => true, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable This feed', 'fluentformpro') ] ], 'button_require_list' => true, 'integration_title' => $this->title ]; } public function getMergeFields($list, $listId, $formId) { $api = $this->getApiClient(); if (!$api) { return []; } $fields = $api->get_custom_fields($listId); $formattedFields = []; foreach ($fields as $field) { $field_key = str_replace(array('[', ']'), '', $field['Key']); $formattedFields[$field_key] = $field['FieldName']; } return $formattedFields; } protected function getLists() { $api = $this->getApiClient(); if (!$api) { return []; } $lists = $api->get_lists(); $formattedLists = []; foreach ($lists as $list) { $formattedLists[$list['ListID']] = $list['Name']; } return $formattedLists; } protected function getClients() { $api = $this->getApiClient(); if (!$api) { return []; } try { $clients = $api->get_clients(); $formattedClints = []; foreach ($clients as $client) { $formattedClints[$client['ClientID']] = $client['Name']; } return $formattedClints; } catch (\Exception $e) { return []; } } /* * Form Submission Hooks Here */ public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; if (!is_email($feedData['fieldEmailAddress'])) { $feedData['fieldEmailAddress'] = ArrayHelper::get($formData, $feedData['fieldEmailAddress']); } if (!is_email($feedData['fieldEmailAddress'])) { do_action('fluentform/integration_action_result', $feed, 'failed', __('Campaign Monitor API call has been skipped because no valid email available', 'fluentformpro')); return; } $subscriber = [ 'EmailAddress' => $feedData['fieldEmailAddress'], 'Name' => ArrayHelper::get($feedData, 'fullName'), 'Resubscribe' => ArrayHelper::isTrue($feedData, 'resubscribe'), ]; $customFiels = []; foreach (ArrayHelper::get($feedData, 'custom_fields', []) as $key => $value) { if (!$value) { continue; } $customFiels[] = [ 'Key' => $key, 'Value' => $value ]; } if ($customFiels) { $subscriber['CustomFields'] = $customFiels; } $subscriber = array_filter($subscriber); $subscriber = apply_filters_deprecated( 'fluentform_integration_data_' . $this->integrationKey, [ $subscriber, $feed, $entry ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/integration_data_' . $this->integrationKey, 'Use fluentform/integration_data_' . $this->integrationKey . ' instead of fluentform_integration_data_' . $this->integrationKey ); $subscriber = apply_filters('fluentform/integration_data_' . $this->integrationKey, $subscriber, $feed, $entry); try { // Now let's prepare the data and push to hubspot $api = $this->getApiClient(); if (!$api) { return; } $api->add_subscriber($subscriber, $feedData['list_id']); do_action('fluentform/integration_action_result', $feed, 'success', __('Campaign Monitor feed has been successfully initialed and pushed data', 'fluentformpro')); } catch (\Exception $exception) { do_action('fluentform/integration_action_result', $feed, 'failed', $exception->getMessage()); } } protected function getApiClient() { try { $settings = $this->getGlobalSettings([]); if ($settings['clientId']) { return new CampaignMonitorApi($settings['apiKey'], $settings['clientId']); } $api = new CampaignMonitorApi($settings['apiKey']); $clients = $api->get_clients(); if (!isset($clients[0])) { throw new \Exception(__('Client is not configured', 'fluentformpro'), 400); } $settings['clientId'] = $clients[0]['ClientID']; update_option($this->optionKey, $settings, 'no'); $api->set_client_id($clients[0]['ClientID']); return $api; } catch (\Exception $e) { return false; } } } PK!'baa7src/Integrations/CampaignMonitor/CampaignMonitorApi.phpnu[api_key = $api_key; $this->client_id = $client_id; } // # AUTH METHODS -------------------------------------------------------------------------------------------------- /** * Test Campaign Monitor authentication credentials. * * @since 3.5 * @access public * * @uses GF_CampaignMonitor_API::make_request() * * @return array */ public function auth_test() { return $this->make_request( 'systemdate' ); } // # CLIENT METHODS ------------------------------------------------------------------------------------------------- /** * Get Campaign Monitor client details. * * @since 3.5 * @access public * * @param string $client_id Client ID. * * @uses GF_CampaignMonitor_API::make_request() * * @return array */ public function get_client( $client_id = '' ) { return $this->make_request( 'clients/' . $client_id ); } /** * Get all Campaign Monitor clients. * * @since 3.5 * @access public * * @uses GF_CampaignMonitor_API::make_request() * * @return array */ public function get_clients() { return $this->make_request( 'clients' ); } // # LIST METHODS -------------------------------------------------------------------------------------------------- /** * Get custom fields for Campaign Monitor list. * * @since 3.5 * @access public * * @uses GF_CampaignMonitor_API::make_request() * * @return array */ public function get_custom_fields( $list_id = '' ) { return $this->make_request( 'lists/' . $list_id . '/customfields' ); } /** * Get Campaign Monitor list details. * * @since 3.5 * @access public * * @param string $list_id List ID. * * @uses GF_CampaignMonitor_API::make_request() * * @return array */ public function get_list( $list_id = '' ) { return $this->make_request( 'lists/' . $list_id ); } /** * Get Campaign Monitor lists for client. * * @since 3.5 * @access public * * @param string $list_id List ID. * * @uses GF_CampaignMonitor_API::make_request() * * @return array */ public function get_lists() { return $this->make_request( 'clients/' . $this->client_id . '/lists' ); } // # SUBSCRIBER METHODS -------------------------------------------------------------------------------------------- /** * Add subscriber to a Campaign Monitor list. * * @since 3.5 * @access public * * @param array $subscriber Subscriber attributes. * @param string $list_id List ID. * * @uses GF_CampaignMonitor_API::make_request() * * @return array */ public function add_subscriber( $subscriber = array(), $list_id = '' ) { return $this->make_request( 'subscribers/' . $list_id, $subscriber, 'POST' ); } // # HELPER METHODS ------------------------------------------------------------------------------------------------ /** * Define Campaign Monitor API key. * * @since 3.5 * @access public * * @param string $api_key API key. */ public function set_api_key( $api_key = '' ) { $this->api_key = $api_key; } /** * Define Campaign Monitor client ID. * * @since 3.5 * @access public * * @param string $client_id Client ID. */ public function set_client_id( $client_id = '' ) { $this->client_id = $client_id; } // # API REQUESTS -------------------------------------------------------------------------------------------------- /** * Make API request. * * @since 3.5 * @access private * * @param string $path Request path. * @param array $options Request option. * @param string $method Request method. Defaults to GET. * * @return array */ private function make_request( $path, $options = array(), $method = 'GET' ) { // Build request URL. $request_url = self::$api_url . $path . '.json'; // Add options if this is a GET request. if ( 'GET' === $method ) { $request_url = add_query_arg( $options, $request_url ); } // Build request arguments. $args = array( 'body' => 'GET' !== $method ? json_encode( $options ) : null, 'method' => $method, 'headers' => array( 'Authorization' => 'Basic ' . base64_encode( $this->api_key . ':x' ), ), ); // Execute request. $response = wp_remote_request( $request_url, $args ); // If request attempt threw a WordPress error, throw exception. if ( is_wp_error( $response ) ) { throw new \Exception( $response->get_error_message() ); } // Decode response. $response = json_decode( $response['body'], true ); // If error response was received, throw exception. if ( isset( $response['Code'] ) ) { throw new \Exception( $response['Message'] ); } return $response; } }PK!Z " : :*src/Integrations/CleverReach/Bootstrap.phpnu[logo = fluentFormMix('img/integrations/clever_reach.png'); $this->description = 'Connect Fluent Forms with CleverReach to grow your CleverReach subscriber list.'; $this->registerAdminHooks(); add_action('admin_init', function () { if (isset($_REQUEST['ff_cleverreach_auth'])) { $client = $this->getRemoteClient(); if (isset($_REQUEST['code'])) { // Get the access token now $code = sanitize_text_field($_REQUEST['code']); $settings = $this->getGlobalSettings([]); $settings = $client->generateAccessToken($code, $settings); if (!is_wp_error($settings)) { $settings['status'] = true; update_option($this->optionKey, $settings, 'no'); } wp_redirect(admin_url('admin.php?page=fluent_forms_settings#general-cleverreach-settings')); exit(); } else { $client->redirectToAuthServer(); } die(); } }); } public function getRemoteClient() { $settings = $this->getGlobalSettings([]); return new API( $settings ); } public function getGlobalSettings($settings = []) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'client_id' => '', 'client_secret' => '', 'status' => false, 'access_token' => '', 'refresh_token' => '', 'expire_at' => false ]; return wp_parse_args($globalSettings, $defaults); } public function saveGlobalSettings($settings) { if (empty($settings['client_id']) || empty($settings['client_secret'])) { $integrationSettings = [ 'client_id' => '', 'client_secret' => '', 'status' => false, 'access_token' => '' ]; // Update the details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your settings has been updated', 'fluentformpro'), 'status' => false ], 200); } // Verify API key now try { $oldSettings = $this->getGlobalSettings([]); $oldSettings['client_id'] = sanitize_text_field($settings['client_id']); $oldSettings['client_secret'] = sanitize_text_field($settings['client_secret']); $oldSettings['status'] = false; update_option($this->optionKey, $oldSettings, 'no'); $client = $this->getRemoteClient(); $check = $client->checkForClientId(); if (is_wp_error($check)) { $integrationSettings = [ 'client_id' => '', 'client_secret' => '', 'status' => false, 'access_token' => '' ]; update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_error([ 'message' => __($check->errors['invalid_client'][0], 'fluentformpro'), 'status' => false ], 400); } else { wp_send_json_success([ 'message' => __('You are redirect to authenticate', 'fluentformpro'), 'redirect_url' => admin_url('?ff_cleverreach_auth') ], 200); } } catch (\Exception $exception) { wp_send_json_error([ 'message' => $exception->getMessage() ], 400); } } public function getGlobalFields($fields) { return [ 'logo' => $this->logo, 'menu_title' => __('CleverReach Settings', 'fluentformpro'), 'menu_description' => __($this->description, 'fluentformpro'), 'valid_message' => __('Your CleverReach API Key is valid', 'fluentformpro'), 'invalid_message' => __('Your CleverReach API Key is not valid', 'fluentformpro'), 'save_button_text' => __('Save Settings', 'fluentformpro'), 'config_instruction' => __($this->getConfigInstructions(), 'fluentformpro'), 'fields' => [ 'client_id' => [ 'type' => 'text', 'placeholder' => __('CleverReach Client ID', 'fluentformpro'), 'label_tips' => __('Enter your CleverReach Client ID', 'fluentformpro'), 'label' => __('CleverReach Client ID', 'fluentformpro'), ], 'client_secret' => [ 'type' => 'password', 'placeholder' => __('CleverReach App Client Secret', 'fluentformpro'), 'label_tips' => __('Enter your CleverReach Client secret', 'fluentformpro'), 'label' => __('CleverReach Client Secret', 'fluentformpro'), ], ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your CleverReach API integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect CleverReach', 'fluentformpro'), 'data' => [ 'client_id' => '', 'client_secret' => '', 'access_token' => '', ], 'show_verify' => true ] ]; } protected function getConfigInstructions() { ob_start(); ?>

    To Authenticate CleverReach you have to enable your API first

    1. Go to Your CleverReach account dashboard, Click on the profile icon on the top right corner. Click on My Account >> Extras >> REST Api then click on Create an OAuth App now button.
    2. Then give your oauth app a name >> choose REST API Version 3 >> Select the Recipients and Forms scopes >> Redirect URL should be '*' and save it.
    3. Paste your CleverReach account Client Id and Secret Id. Then click save settings.
    integrationKey] = [ 'title' => $this->title . ' Integration', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-cleverreach-settings'), 'configure_message' => __('CleverReach is not configured yet! Please configure your CleverReach API first', 'fluentformpro'), 'configure_button_text' => __('Set CleverReach API', 'fluentformpro') ]; return $integrations; } public function getIntegrationDefaults($settings, $formId) { return [ 'name' => '', 'list_id' => '', 'fieldEmailAddress' => '', 'custom_fields' => (object)[], 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { return [ 'fields' => [ [ 'key' => 'name', 'label' => __('Feed Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'list_id', 'label' => __('CleverReach List', 'fluentformpro'), 'required' => true, 'placeholder' => __('Select CleverReach List', 'fluentformpro'), 'tips' => __('Select the CleverReach list you would like to add your contacts to.', 'fluentformpro'), 'component' => 'list_ajax_options', 'options' => $this->getLists(), ], [ 'key' => 'custom_fields', 'require_list' => true, 'label' => __('Map Fields', 'fluentformpro'), 'tips' => __('Associate your CleverReach merge tags to the appropriate Fluent Forms fields by selecting the appropriate form field from the list.', 'fluentformpro'), 'component' => 'map_fields', 'field_label_remote' => __('CleverReach Field', 'fluentformpro'), 'field_label_local' => __('Form Field', 'fluentformpro'), 'primary_fileds' => [ [ 'key' => 'email', 'label' => __('Email Address', 'fluentformpro'), 'required' => true, 'input_options' => 'emails' ], ] ], [ 'require_list' => true, 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow CleverReach integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => true, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable This feed','fluentformpro'), ] ], 'integration_title' => $this->title ]; } protected function getLists() { $client = $this->getRemoteClient(); $settings = get_option($this->optionKey); try { $token = ($settings['access_token']); $lists = $client->makeRequest('https://rest.cleverreach.com/v3/groups', null, 'GET', ['Authorization' => 'Bearer ' . $token]); if (!$lists || is_wp_error($lists)) { return []; } } catch (\Exception $exception) { return []; } $formattedLists = []; foreach ($lists as $list) { $formattedLists[$list['id']] = $list['name']; } return $formattedLists; } public function getMergeFields($list, $listId, $formId) { $client = $this->getRemoteClient(); if (!$this->isConfigured()) { return false; } $settings = get_option($this->optionKey); try { $token = ($settings['access_token']); $lists = $client->makeRequest('https://rest.cleverreach.com/v3/groups/' . $listId . '/attributes/', null, 'GET', ['Authorization' => 'Bearer ' . $token]); if (!$lists) { return []; } } catch (\Exception $exception) { return false; } if (is_wp_error($lists)) { return []; } $mergedFields = $lists; $fields = []; foreach ($mergedFields as $merged_field) { $fields[$merged_field['name']] = $merged_field['name']; } return $fields; } public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; if (!is_email($feedData['email'])) { $feedData['email'] = ArrayHelper::get($formData, $feedData['email']); } if (!is_email($feedData['email'])) { do_action('fluentform/integration_action_result', $feed, 'failed', __('CleverReach API call has been skipped because no valid email available', 'fluentformpro')); return; } $subscriber = []; $subscriber['list_id'] = $feedData['list_id']; $subscriber['email'] = $feedData['email']; $subscriber['attributes'] = ArrayHelper::get($feedData, 'custom_fields'); $client = $this->getRemoteClient(); $response = $client->subscribe($subscriber); if (is_wp_error($response)) { $error = $response->get_error_message(); // it's failed do_action('fluentform/integration_action_result', $feed, 'failed', $error); } else { $message = __('CleverReach has been successfully initialed and pushed data', 'fluentformpro'); // It's success do_action('fluentform/integration_action_result', $feed, 'success', $message); } } } PK!2PC33$src/Integrations/CleverReach/API.phpnu[clientId = $settings['client_id']; $this->clientSecret = $settings['client_secret']; $this->accessToken = $settings['access_token']; $this->callBackUrl = admin_url('?ff_cleverreach_auth'); $this->settings = $settings; } public function redirectToAuthServer() { $url = 'https://rest.cleverreach.com/oauth/authorize.php?client_id=' . $this->clientId . '&grant=basic&response_type=code&redirect_uri=' . $this->callBackUrl; wp_redirect($url); exit(); } public function checkForClientId() { $url = 'https://rest.cleverreach.com/oauth/authorize.php?client_id=' . $this->clientId . '&grant=basic&response_type=code&redirect_uri=' . $this->callBackUrl; $response = wp_remote_get($url); if (is_wp_error($response)) { return $response; } $body = wp_remote_retrieve_body($response); $body = \json_decode($body, true); if (isset($body['error_description'])) { return new \WP_Error('invalid_client', $body['error_description']); } } public function generateAccessToken($code, $settings) { $response = wp_remote_post('https://rest.cleverreach.com/oauth/token.php', [ 'body' => [ 'client_id' => $this->clientId, 'client_secret' => $this->clientSecret, 'grant_type' => 'authorization_code', 'redirect_uri' => $this->callBackUrl, 'code' => $code ] ]); if (is_wp_error($response)) { return $response; } $body = wp_remote_retrieve_body($response); $body = \json_decode($body, true); if (isset($body['error_description'])) { return new \WP_Error('invalid_client', $body['error_description']); } $settings['access_token'] = $body['access_token']; $settings['refresh_token'] = $body['refresh_token']; $settings['expire_at'] = time() + intval($body['expires_in']); return $settings; } protected function getApiSettings() { $apiSettings = $this->maybeRefreshToken(); if (is_wp_error($apiSettings)) { return $apiSettings; } if (!$apiSettings['status'] || !$apiSettings['expire_at']) { return new \WP_Error('invalid', __('API key is invalid', 'fluentformpro')); } return [ 'client_id' => $this->clientId, 'client_secret' => $this->clientSecret, 'callback' => $this->callBackUrl, 'access_token' => $this->accessToken, 'refresh_token' => $apiSettings['refresh_token'], 'expire_at' => $apiSettings['expire_at'] ]; } protected function maybeRefreshToken() { $settings = $this->settings; $expireAt = $settings['expire_at']; if ($expireAt && $expireAt <= (time() - 30)) { // we have to regenerate the tokens $response = wp_remote_post('https://rest.cleverreach.com/oauth/token.php', [ 'body' => [ 'client_id' => $this->clientId, 'client_secret' => $this->clientSecret, 'grant_type' => 'refresh_token', 'refresh_token' => $settings['refresh_token'], 'redirect_uri' => $this->callBackUrl ] ]); if (is_wp_error($response)) { return $response; } $body = wp_remote_retrieve_body($response); $body = \json_decode($body, true); $code = wp_remote_retrieve_response_code($response); if ($code == 400) { if (isset($body['error_description'])) { return new \WP_Error($code, $body['error_description']); } return new \WP_Error($code, __('Refresh token is not working', 'fluentformpro')); } $settings['access_token'] = $body['access_token']; $settings['refresh_token'] = $body['refresh_token']; $settings['expire_at'] = time() + intval($body['expires_in']); } return $settings; } public function makeRequest($url, $bodyArgs, $type = 'GET', $headers = false) { $settings = $this->getApiSettings(); if (is_wp_error($settings)) { return $settings; } $headers['Content-type'] = 'application/x-www-form-urlencoded'; $args = [ 'headers' => $headers ]; if ($bodyArgs) { $args['body'] = $bodyArgs; } $args['method'] = $type; $request = wp_remote_request($url, $args); if (is_wp_error($request)) { $message = $request->get_error_message(); return new \WP_Error(423, $message); } $body = json_decode(wp_remote_retrieve_body($request), true); if (!empty($body['error'])) { $error = 'Unknown Error'; if (isset($body['error_description'])) { $error = $body['error_description']; } else { if (!empty($body['error']['message'])) { $error = $body['error']['message']; } } return new \WP_Error(423, $error); } return $body; } public function subscribe($subscriber) { $response = $this->makeRequest( 'https://rest.cleverreach.com/v3/groups/' . $subscriber['list_id'] . '/receivers', $subscriber, 'POST', ['Authorization' => 'Bearer ' . $this->accessToken] ); if (is_wp_error($response)) { $message = $response->get_error_message(); $code = $response->get_error_code(); return new \WP_Error($code, $message); } if (isset($response['errors'])) { return new \WP_Error('error', $response['errors']); } return $response; } } PK!SS(src/Integrations/ClickSend/Bootstrap.phpnu[logo = fluentFormMix('img/integrations/clicksend.png'); $this->description = 'Send SMS in real time when a form is submitted with ClickSend.'; $this->registerAdminHooks(); add_filter('fluentform/save_integration_value_' . $this->integrationKey, [$this, 'validate'], 10, 3); add_action('wp_ajax_fluentform_clicksend_sms_config', array($this, 'getClickSendConfigOptions')); // add_filter('fluentform/notifying_async_clicksend_sms_notification', '__return_false'); add_filter( 'fluentform/get_integration_values_clicksend_sms_notification', [$this, 'resolveIntegrationSettings'], 100, 3 ); } public function getClickSendConfigOptions() { } public function getGlobalFields($fields) { return [ 'logo' => $this->logo, 'menu_title' => __('SMS Provider Settings (ClickSend)', 'fluentformpro'), 'menu_description' => __('Please Provide your ClickSend Settings here', 'fluentformpro'), 'valid_message' => __('Your ClickSend API Key is valid', 'fluentformpro'), 'invalid_message' => __('Your ClickSend API Key is not valid', 'fluentformpro'), 'save_button_text' => __('Save Settings', 'fluentformpro'), 'config_instruction' => __($this->getConfigInstructions(), 'fluentformpro'), 'fields' => [ 'senderNumber' => [ 'type' => 'text', 'placeholder' => __('ClickSend Sender Number', 'fluentformpro'), 'label_tips' => __("Enter your ClickSend sender number", 'fluentformpro'), 'label' => __('Sender Number', 'fluentformpro'), ], 'username' => [ 'type' => 'text', 'placeholder' => __('ClickSend Username', 'fluentformpro'), 'label_tips' => __("Enter ClickSend Username. This can be found from ClickSend", 'fluentformpro'), 'label' => __('Username', 'fluentformpro'), ], 'authToken' => [ 'type' => 'password', 'placeholder' => __('API Key', 'fluentformpro'), 'label_tips' => __("Enter ClickSend API Key. This can be found from ClickSend", 'fluentformpro'), 'label' => __('API Key', 'fluentformpro'), ] ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your ClickSend API integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect ClickSend', 'fluentformpro'), 'data' => [ 'authToken' => '' ], 'show_verify' => true ] ]; } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'senderNumber' => '', 'username' => '', 'authToken' => '', 'provider' => 'ClickSend' ]; return wp_parse_args($globalSettings, $defaults); } public function saveGlobalSettings($settings) { try { if (empty($settings['authToken'])) { //prevent saving integration without the sender number throw new \Exception( __('API Key is required', 'fluentformpro') ); } if (empty($settings['senderNumber'])) { //prevent saving integration without the sender number throw new \Exception( __('Sender number is required', 'fluentformpro') ); } if (empty($settings['username'])) { //prevent saving integration without the sender number throw new \Exception( __('Username number is required', 'fluentformpro') ); } $integrationSettings = [ 'senderNumber' => sanitize_textarea_field($settings['senderNumber']), 'username' => sanitize_text_field($settings['username']), 'authToken' => sanitize_text_field($settings['authToken']), 'provider' => 'ClickSend', 'status' => false ]; update_option($this->optionKey, $integrationSettings, 'no'); $api = new ClickSend($settings['authToken'], $settings['username']); $result = $api->auth_test(); if (!empty($result['error'])) { throw new \Exception($result['message']); } } catch (\Exception $exception) { $integrationSettings = [ 'senderNumber' => '', 'username' => '', 'authToken' => '', 'provider' => 'ClickSend', 'status' => false ]; update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_error([ 'message' => $exception->getMessage() ], 400); } // Integration key is verified now, Proceed now $integrationSettings = [ 'senderNumber' => sanitize_textarea_field($settings['senderNumber']), 'username' => sanitize_text_field($settings['username']), 'authToken' => sanitize_text_field($settings['authToken']), 'provider' => 'ClickSend', 'status' => true ]; // Update the reCaptcha details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your ClickSend API Key has been verified and successfully set', 'fluentformpro'), 'status' => true ], 200); } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => __('ClickSend SMS Notification', 'fluentformpro'), 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-clicksend_sms_notification-settings'), 'configure_message' => __('ClickSend SMS Notification is not configured yet! Please configure your ClickSend SMS api first', 'fluentformpro'), 'configure_button_text' => __('Set ClickSend SMS Notification API', 'fluentformpro') ]; return $integrations; } public function getIntegrationDefaults($settings, $formId) { $name = $this->app->request->get('serviceName', ''); $listId = $this->app->request->get('serviceId', ''); return [ 'name' => $name, 'receiver_number' => '', 'list_id' => $listId, 'email' => '', 'message_body' => 'message-input', 'message' => '', 'phone_number' => '', 'fields' => (object)[], 'other_add_contact_fields' => [ [ 'item_value' => '', 'label' => '' ] ], 'contact_list_name' => '', 'campaign_name' => '', 'email_campaign_subject' => '', 'campaign_list_id' => '', 'schedule' => '', 'template_id' => '', 'email_template_id' => '', 'email_address_id' => '', 'email_form_name' => '', 'enabled' => true, 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], ]; } public function getSettingsFields($settings, $formId) { $fieldSettings = [ 'fields' => [ [ 'key' => 'name', 'label' => __('Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'list_id', 'label' => __('Services', 'fluentformpro'), 'placeholder' => __('Choose Service', 'fluentformpro'), 'required' => true, 'component' => 'refresh', 'options' => [ 'single-sms' => 'Single SMS', 'sms-campaign' => 'SMS Campaign', 'create-new-contact' => 'Create Subscriber Contact', 'add-contact-list' => 'Add Contact List', 'email-campaign' => 'Add Email Campaign', ] ] ], 'button_require_list' => false, 'integration_title' => $this->title ]; $listId = $this->app->request->get( 'serviceId', ArrayHelper::get($settings, 'list_id') ); if ($listId) { $fields = $this->getFieldsByService($listId); $fields = array_merge($fieldSettings['fields'], $fields); $fieldSettings['fields'] = $fields; } $fieldSettings['fields'] = array_merge($fieldSettings['fields'], [ [ 'require_list' => false, 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow this integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => false, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable This feed', 'fluentformpro') ] ]); return $fieldSettings; } public function getFieldsByService($listId) { $api = $this->getRemoteClient(); switch ($listId){ case 'single-sms': $template_options = array(); $templates = $api->getTemplates('sms/templates'); if (!is_wp_error($templates)) { foreach ($templates['data']['data'] as $template) { $template_options[$template['template_id']] = $template['template_name']; } } $fields = [ [ 'key' => 'message_body', 'label' => __('Message Body', 'fluentformpro'), 'tips' => __('Select your message body type e.g. Input Message or Template Message.', 'fluentformpro'), 'placeholder' => __('Choose Message Body', 'fluentformpro'), 'required' => true, 'component' => 'select', 'options' => [ 'message-input' => 'Input Message', 'template-message' => 'Template Message', ] ], [ 'key' => 'receiver_number', 'label' => __('To', 'fluentformpro'), 'required' => true, 'tips' => __('Enter a receiver number or select input field shortcode.', 'fluentformpro'), 'placeholder' => __('Type the receiver number', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'message', 'label' => __('Message', 'fluentformpro'), 'tips' => __('Enter your message. If you chose Template Message as Message Body, you can ignore this settings.', 'fluentformpro'), 'required' => false, 'placeholder' => __('Message Body', 'fluentformpro'), 'component' => 'value_textarea' ], [ 'key' => 'template_id', 'label' => __('SMS Template', 'fluentformpro'), 'placeholder' => __('Choose Template', 'fluentformpro'), 'tips' => __('Choose a template for SMS body. This settings won\'t take effect if you chose Input Message as Message Body.', 'fluentformpro'), 'required' => false, 'component' => 'select', 'options' => $template_options ], [ 'key' => 'schedule', 'label' => __('SMS Schedule', 'fluentformpro'), 'placeholder' => __('SMS schedule date and time ', 'fluentformpro'), 'tips' => __('Optional. Choose a datetime for sending SMS. If empty, SMS will be sent immediately.', 'fluentformpro'), 'required' => false, 'component' => 'datetime', ] ]; break; case 'sms-campaign': $template_options = array(); $templates = $api->getTemplates('sms/templates'); if (!is_wp_error($templates)) { foreach ($templates['data']['data'] as $template) { $template_options[$template['template_id']] = $template['template_name']; } } $list_options = array(); $lists = $api->getLists(); if (!is_wp_error($lists)) { foreach ($lists['data']['data'] as $list) { $list_options[$list['list_id']] = $list['list_name']; } } $fields = [ [ 'key' => 'message_body', 'label' => __('Message Body', 'fluentformpro'), 'tips' => __('Select your message body type e.g. Input Message or Template Message.', 'fluentformpro'), 'placeholder' => __('Choose Message Body', 'fluentformpro'), 'required' => true, 'component' => 'select', 'options' => [ 'message-input' => 'Input Message', 'template-message' => 'Template Message', ] ], [ 'key' => 'campaign_name', 'label' => __('Campaign Name', 'fluentformpro'), 'tips' => __('Enter your campaign name or select input shortcode field for campaign name.', 'fluentformpro'), 'required' => true, 'placeholder' => __('Campaign Name', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'campaign_list_id', 'label' => __('Campaign List', 'fluentformpro'), 'placeholder' => __('Choose list', 'fluentformpro'), 'tips' => __('Choose a list for sending SMS to all of its contact.', 'fluentformpro'), 'required' => true, 'component' => 'select', 'options' => $list_options ], [ 'key' => 'message', 'label' => __('Message', 'fluentformpro'), 'tips' => __('Enter your message. If you chose Template Message as Message Body, you can ignore this settings.', 'fluentformpro'), 'required' => false, 'placeholder' => __('Message Body', 'fluentformpro'), 'component' => 'value_textarea' ], [ 'key' => 'template_id', 'label' => __('SMS Template', 'fluentformpro'), 'placeholder' => __('Choose Template', 'fluentformpro'), 'tips' => __('Choose a template for SMS body. This settings won\'t take effect if you chose Input Message as Message Body.', 'fluentformpro'), 'required' => false, 'component' => 'select', 'options' => $template_options ], [ 'key' => 'schedule', 'label' => __('Campaign Schedule', 'fluentformpro'), 'placeholder' => __('Campaign schedule date and time ', 'fluentformpro'), 'tips' => __('Choose a datetime for your SMS campaign.', 'fluentformpro'), 'required' => false, 'component' => 'datetime', ] ]; break; case 'create-new-contact': $list_options = array(); $lists = $api->getLists(); if (!is_wp_error($lists)) { foreach ($lists['data']['data'] as $list){ $list_options[$list['list_id']] = $list['list_name']; } } $fields = [ [ 'key' => 'campaign_list_id', 'label' => __('Campaign List', 'fluentformpro'), 'placeholder' => __('Choose list', 'fluentformpro'), 'tips' => __('Choose the list to which the contact should be added.', 'fluentformpro'), 'required' => true, 'component' => 'select', 'options' => $list_options ], [ 'key' => 'phone_number', 'label' => __('Phone Number', 'fluentformpro'), 'placeholder' => __('Subscriber Number', 'fluentformpro'), 'tips' => __('Enter subscriber or select input shortcode field to add contact in the list.', 'fluentformpro'), 'required' => true, 'component' => 'value_text', ], [ 'key' => 'email', 'label' => __('Email', 'fluentformpro'), 'placeholder' => __('Subscriber Email', 'fluentformpro'), 'tips' => __('Enter subscriber email or select input shortcode field to add contact in the list.', 'fluentformpro'), 'required' => true, 'component' => 'value_text', ], [ 'key' => 'other_add_contact_fields', 'required' => false, 'label' => __('Other Fields', 'fluentformpro'), 'tips' => __('Other contact fields to add more information about the contact. These fields are optional.', 'fluentformpro'), 'component' => 'dropdown_many_fields', 'options' => [ 'first_name' => __('First Name', 'fluentformpro'), 'last_name' => __('Last Name', 'fluentformpro'), 'organization_name' => __('Company', 'fluentformpro'), 'fax_number' => __('Fax Number', 'fluentformpro'), 'address_line_1' => __('Address Line 1', 'fluentformpro'), 'address_line_2' => __('Address Line 2', 'fluentformpro'), 'address_city' => __('City', 'fluentformpro'), 'address_state' => __('State', 'fluentformpro'), 'address_postal_code' => __('Postal Code', 'fluentformpro'), 'address_country' => __('Country', 'fluentformpro'), 'custom_1' => __('Custom Field 1', 'fluentformpro'), 'custom_2' => __('Custom Field 2', 'fluentformpro'), 'custom_3' => __('Custom Field 3', 'fluentformpro'), 'custom_4' => __('Custom Field 4', 'fluentformpro'), ] ], ]; break; case 'email-campaign': $list_options = array(); $lists = $api->getLists(); if (!is_wp_error($lists)) { foreach ($lists['data']['data'] as $list) { $list_options[$list['list_id']] = $list['list_name']; } } $template_options = array(); $templates = $api->getTemplates('email/templates'); if (!is_wp_error($templates)) { foreach ($templates['data']['data'] as $template) { $template_options[$template['template_id']] = $template['template_name']; } } $email_address_options = array(); $email_address = $api->getEmailAddress('email/addresses'); if (!is_wp_error($email_address)) { foreach ($email_address['data']['data'] as $email_info) { $email_address_options[$email_info['email_address_id']] = $email_info['email_address']; } } $from_name_options = array(); $account_info = $api->get('account'); if (!is_wp_error($account_info)) { $first_name = $account_info['data']['user_first_name']; $last_name = $account_info['data']['user_last_name']; $from_name_options[$first_name . ' ' . $last_name] = $first_name . ' ' . $last_name; $from_name_options[$first_name] = $first_name; $from_name_options[$last_name] = $last_name; $from_name_options[$account_info['data']['username']] = $account_info['data']['username']; $from_name_options[$account_info['data']['account_name']] = $account_info['data']['account_name']; } $fields = [ [ 'key' => 'campaign_name', 'label' => __('Campaign Name', 'fluentformpro'), 'tips' => __('Enter your campaign name or select input shortcode field for campaign name.', 'fluentformpro'), 'required' => true, 'placeholder' => __('Campaign Name', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'email_campaign_subject', 'label' => __('Campaign Subject', 'fluentformpro'), 'tips' => __('Enter your campaign subject or select input shortcode field for campaign subject.', 'fluentformpro'), 'required' => true, 'placeholder' => __('Campaign Subject', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'campaign_list_id', 'label' => __('Campaign List', 'fluentformpro'), 'placeholder' => __('Choose list', 'fluentformpro'), 'tips' => __('Choose a list for sending email to all of its contact.', 'fluentformpro'), 'required' => true, 'component' => 'select', 'options' => $list_options ], [ 'key' => 'message', 'label' => __('Message', 'fluentformpro'), 'tips' => __('Enter your message.', 'fluentformpro'), 'required' => true, 'placeholder' => __('Message Body', 'fluentformpro'), 'component' => 'value_textarea' ], [ 'key' => 'email_template_id', 'label' => __('Email Template', 'fluentformpro'), 'placeholder' => __('Choose Template', 'fluentformpro'), 'tips' => __('Choose a template for SMS body.', 'fluentformpro'), 'required' => false, 'component' => 'select', 'options' => $template_options ], [ 'key' => 'email_address_id', 'label' => __('From Email Address', 'fluentformpro'), 'placeholder' => __('Enter From Email', 'fluentformpro'), 'tips' => __('Enter an email address for Form Email.', 'fluentformpro'), 'required' => true, 'component' => 'select', 'options' => $email_address_options ], [ 'key' => 'email_form_name', 'label' => __('Email Form Name', 'fluentformpro'), 'placeholder' => __('Enter Form Name', 'fluentformpro'), 'tips' => __('Enter a name for sending email Form Name.', 'fluentformpro'), 'required' => true, 'component' => 'select', 'options' => $from_name_options ], [ 'key' => 'schedule', 'label' => __('Campaign Schedule', 'fluentformpro'), 'placeholder' => __('Campaign schedule date and time ', 'fluentformpro'), 'tips' => __('Choose a datetime for your sms campaign.', 'fluentformpro'), 'required' => false, 'component' => 'datetime', ] ]; break; case 'add-contact-list': $fields = [ [ 'key' => 'contact_list_name', 'label' => __('List Name', 'fluentformpro'), 'placeholder' => __('Contact List Name', 'fluentformpro'), 'tips' => __('Enter name or select input shortcode field for contact list.', 'fluentformpro'), 'required' => true, 'component' => 'value_text', ], ]; break; default: return []; } return $fields; } public function resolveIntegrationSettings($settings, $feed, $formId) { $serviceName = $this->app->request->get('serviceName', ''); $serviceId = $this->app->request->get('serviceId', ''); if ($serviceName) { $settings['name'] = $serviceName; } if ($serviceId) { $settings['list_id'] = $serviceId; } return $settings; } public function getMergeFields($list, $listId, $formId) { return false; } public function validate($settings, $integrationId, $formId) { $error = false; $errors = array(); foreach ($this->getFieldsByService($settings['list_id']) as $field){ if ($field['required'] && empty($settings[$field['key']])) { $error = true; $errors[$field['key']] = [__($field['label'] .' is required', 'fluentformpro')]; } } if ($error){ wp_send_json_error([ 'message' => __('Validation Failed', 'fluentformpro'), 'errors' => $errors ], 423); } return $settings; } /* * Form Submission Hooks Here */ public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; if (empty($feedData['list_id'])) { do_action('fluentform/integration_action_result', $feed, 'failed', __('No Valid Service Found', 'fluentformpro')); return; } $apiSettings = $this->getGlobalSettings([]); $api = $this->getRemoteClient(); // sms body $smsBody = ''; if (!empty($feedData['message_body'])) { if ($feedData['message_body'] == 'template-message' && !empty($feedData['template_id'])) { $templates = $api->getTemplates('sms/templates'); if (!is_wp_error($templates)) { foreach ($templates['data']['data'] as $template) { if ($template['template_id'] == $feedData['template_id']) { $smsBody = $template['body']; } } } } if ($feedData['message_body'] == 'message-input' && !empty($feedData['message'])) { $smsBody = $feedData['message']; } } // sms time schedule $schedule = 0; if (!empty($feedData['schedule'])) { $schedule = strtotime($feedData['schedule']); } // switch services and do operation switch ($feedData['list_id']){ case 'single-sms': if ( empty($feedData['message_body']) || empty($feedData['receiver_number']) || ($feedData['message_body'] == 'template-message' && empty($feedData['template_id'])) || ($feedData['message_body'] == 'message-input' && empty($feedData['message'])) ) { do_action('fluentform/integration_action_result', $feed, 'failed', __('Not Fulfilled Required Field', 'fluentformpro')); return; } $action = 'single-sms'; $smsData = [ "messages" => array([ 'body' => $smsBody, 'schedule' => $schedule, 'from' => $apiSettings['senderNumber'], 'to' => $feedData['receiver_number'], ]) ]; $this->handleSMSResponse($action, $smsData, $feed, $entry); break; case 'sms-campaign': if (empty($feedData['message_body']) || empty($feedData['campaign_list_id']) || ($feedData['message_body'] == 'template-message' && empty($feedData['template_id'])) || ($feedData['message_body'] == 'message-input' && empty($feedData['message'])) ) { do_action('fluentform/integration_action_result', $feed, 'failed', __('Not Fulfilled Required Field', 'fluentformpro')); return; } $action = 'sms-campaign'; $smsData = [ 'body' => $smsBody, 'schedule' => $schedule, 'from' => $apiSettings['senderNumber'], 'name' => $feedData['campaign_name'], 'list_id' => $feedData['campaign_list_id'] ]; $this->handleSMSResponse($action, $smsData, $feed, $entry); break; case 'create-new-contact': if (empty($feedData['phone_number']) || empty($feedData['campaign_list_id']) || empty($feedData['email'])) { do_action('fluentform/integration_action_result', $feed, 'failed', __('Not Fulfilled Required Field', 'fluentformpro')); return; } $data = array(); $data['phone_number'] = $feedData['phone_number']; $data['email'] = sanitize_email($feedData['email']); if ($feedData['other_add_contact_fields']) { foreach ($feedData['other_add_contact_fields'] as $field) { $data[$field['label']] = $field['item_value']; } } $response = $api->addSubscriberContact($feedData['campaign_list_id'], $data); if (is_wp_error($response)) { $this->handleFailed($feed, $response->get_error_message()); } else { $this->handleSuccess($feed, __('ClickSend SMS feed has been successfully initialed and add subscriber in contact list', 'fluentformpro')); } break; case 'add-contact-list': if (empty($feedData['contact_list_name'])) { do_action('fluentform/integration_action_result', $feed, 'failed', __('Not Fulfilled Required Field', 'fluentformpro')); return; } $data = array(); $data['list_name'] = $feedData['contact_list_name']; $response = $api->addContactList($data); if (is_wp_error($response)) { $this->handleFailed( $feed, $response->get_error_message()); } else { $this->handleSuccess($feed,__('ClickSend SMS feed has been successfully initialed and add contact list', 'fluentformpro')); } break; case 'email-campaign': if ( empty($feedData['email_address_id']) || empty($feedData['campaign_list_id']) || empty($feedData['email_campaign_subject']) || empty($feedData['campaign_name']) || empty($feedData['email_form_name']) || empty($feedData['message']) ) { do_action('fluentform/integration_action_result', $feed, 'failed', __('Not Fulfilled Required Field', 'fluentformpro')); return; } $data = array(); $data['list_id'] = $feedData['campaign_list_id']; $data['subject'] = $feedData['email_campaign_subject']; $data['name'] = $feedData['campaign_name']; $data['body'] = $feedData['message']; $data['from_name'] = $feedData['email_form_name']; $data['schedule'] = $schedule; $data['from_email_address_id'] = $feedData['email_address_id']; if ($feedData['email_template_id']) { $data['template_id'] = $feedData['email_template_id']; } $response = $api->addEmailCampaign($data); if (is_wp_error($response)) { $this->handleFailed($feed, $response->get_error_message()); } else { $this->handleSuccess($feed, __('ClickSend SMS feed has been successfully initialed and pushed email campaign data', 'fluentformpro')); } break; } } public function handleSMSResponse($action, $smsData, $feed, $entry) { $smsData = apply_filters_deprecated( 'fluentform_integration_data_' . $this->integrationKey, [ $smsData, $feed, $entry ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/integration_data_' . $this->integrationKey, 'Use fluentform/integration_data_' . $this->integrationKey . ' instead of fluentform_integration_data_' . $this->integrationKey ); $smsData = apply_filters('fluentform/integration_data_' . $this->integrationKey, $smsData, $feed, $entry); $api = $this->getRemoteClient(); $response = $api->sendSMS($action, $smsData); if (is_wp_error($response)) { $this->handleFailed( $feed, $response->get_error_message()); } else { $this->handleSuccess($feed ); } } public function handleFailed( $feed, $err_msg = 'ClickSend Integration Data insert failed.') { do_action('fluentform/integration_action_result', $feed, 'failed', __($err_msg, 'fluentformpro')); } public function handleSuccess( $feed, $success_msg = 'ClickSend feed has been successfully initialed and pushed data') { // It's success do_action('fluentform/integration_action_result', $feed, 'success', __($success_msg, 'fluentformpro')); } protected function getConfigInstructions() { ob_start(); ?>

    To Authenticate clicksend you have to clicksend account first. Sign UP

    1. Go to Your ClickSend account Dashboard, Click on the profile icon and also click on account settings or browse Account link
    2. You'll need an API key and clicksend number. You can access your API key and purchase a number.
    3. Copy your ClickSend purchase number, username and API key. And paste bellow input. Then click save settings.
    getGlobalSettings([]); return new ClickSend($settings['authToken'], $settings['username']); } } PK!8RV(src/Integrations/ClickSend/ClickSend.phpnu[authToken = $authToken; $this->username = $username; } public function default_options() { return array( 'api_key' => $this->apiKey ); } public function make_request( $action, $options = array(), $method = 'GET' ) { $args = array( 'headers' => array( 'Authorization' => 'Basic ' . base64_encode( $this->username . ':' . $this->authToken ), 'Content-Type' => 'application/json', ) ); /* Build request URL. */ $request_url = $this->apiUrl . $action; /* Execute request based on method. */ switch ( $method ) { case 'POST': $args['body'] = json_encode($options); $response = wp_remote_post( $request_url, $args ); break; case 'GET': $response = wp_remote_get( $request_url, $args ); break; } /* If WP_Error, die. Otherwise, return decoded JSON. */ if ( is_wp_error( $response ) ) { return [ 'error' => 'API_Error', 'message' => $response->get_error_message(), 'response' => $response ]; } else if($response['response']['code'] >= 300) { return [ 'error' => 'API_Error', 'message' => $response['response']['message'], 'response' => $response ]; } else { return json_decode( $response['body'], true ); } } /** * Test the provided API credentials. * * @access public * @return bool */ public function auth_test() { return $this->make_request('sms/inbound', [], 'GET'); } public function sendSMS($action , $data) { switch ( $action ) { case 'single-sms': $response = $this->make_request('sms/send', $data, 'POST'); break; case 'sms-campaign': $response = $this->make_request('sms-campaigns/send', $data, 'POST'); break; } if(!empty($response['error'])) { return new \WP_Error('api_error', $response['message']); } return $response; } public function addSubscriberContact($campaign_list_id,$data){ $response = $this->make_request("lists/$campaign_list_id/contacts",$data, 'POST'); if(!empty($response['error'])) { return new \WP_Error('api_error', $response['message']); } return $response; } public function addContactList($data){ $response = $this->make_request("lists", $data, 'POST'); if(!empty($response['error'])) { return new \WP_Error('api_error', $response['message']); } return $response; } public function addEmailCampaign($data){ $response = $this->make_request("email-campaigns/send", $data, 'POST'); if(!empty($response['error'])) { return new \WP_Error('api_error', $response['message']); } return $response; } public function getLists(){ $response = $this->make_request('lists',[],'GET'); if(!empty($response['error'])) { return new \WP_Error('api_error', $response['message']); } return $response; } public function getTemplates($action){ $response = $this->make_request($action,[],'GET'); if(!empty($response['error'])) { return new \WP_Error('api_error', $response['message']); } return $response; } public function getEmailAddress($action){ $response = $this->make_request($action,[],'GET'); if(!empty($response['error'])) { return new \WP_Error('api_error', $response['message']); } return $response; } public function get($action){ $response = $this->make_request($action,[],'GET'); if(!empty($response['error'])) { return new \WP_Error('api_error', $response['message']); } return $response; } } PK!e]e]`G`G.src/Integrations/ConstantContact/Bootstrap.phpnu[logo = fluentFormMix('img/integrations/constantcontact.png'); $this->description = 'Connect Constant Contact with Fluent Forms and create subscriptions forms right into WordPress and grow your list.'; $this->registerAdminHooks(); add_filter('fluentform/save_integration_value_' . $this->integrationKey, [$this, 'validate'], 10, 3); //add_filter('fluentform/notifying_async_constatantcontact', '__return_false'); } public function validate($settings, $integrationId, $formId) { if (empty($settings['email_address'])) { wp_send_json_error([ 'message' => __('Email is Required', 'fluentformpro'), 'errors' =>[] ], 422); } return $settings; } public function getGlobalFields($fields) { return [ 'logo' => $this->logo, 'menu_title' => __('Constant Contact API Settings', 'fluentformpro'), 'menu_description' => __('Constant Contact is an integrated email marketing, marketing automation, and small business CRM. Save time while growing your business with sales automation. Use Fluent Forms to collect customer information and automatically add it to your Constant Contact list. If you don\'t have an Constant Contact account, you can sign up for one here.', 'fluentformpro'), 'valid_message' => __('Your Constant Contact configuration is valid', 'fluentformpro'), 'invalid_message' => __('Your Constant Contact configuration is invalid', 'fluentformpro'), 'save_button_text' => __('Verify Constant Contact ', 'fluentformpro'), 'config_instruction' => $this->getConfigInstractions(), 'fields' => [ 'accessToken' => [ 'type' => 'text', 'placeholder' => 'access token Key', 'label_tips' => __("Enter your Constant Contact access token Key, if you do not have
    Please click here to get yours", 'fluentformpro'), 'label' => __('Constant Contact access Key', 'fluentformpro'), ], ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your Constant Contact API integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect Constant Contact', 'fluentformpro'), 'data' => [ 'accessToken' => '' ], 'show_verify' => true ] ]; } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'accessToken' => '', 'status' => '' ]; return wp_parse_args($globalSettings, $defaults); } /* * Saving The Global Settings * */ public function saveGlobalSettings($settings) { if (!$settings['accessToken']) { $integrationSettings = [ 'accessToken' => '', 'status' => false ]; // Update the details with access token update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your settings has been updated', 'fluentformpro'), 'status' => false, 'require_load' => true ], 200); } try { $settings['status'] = false; update_option($this->optionKey, $settings, 'no'); $api = new API($settings['accessToken']); $auth = $api->auth_test(); if (!ArrayHelper::get($auth, '0.error_key')) { $settings['status'] = true; update_option($this->optionKey, $settings, 'no'); wp_send_json_success([ 'status' => true, 'message' => __('Your settings has been updated!', 'fluentformpro') ], 200); } throw new \Exception('Invalid Credentials', 400); } catch (\Exception $e) { wp_send_json_error([ 'status' => false, 'message' => $e->getMessage() ], $e->getCode()); } } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => $this->title . ' Integration', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-constatantcontact-settings'), 'configure_message' => __('Constant Contact is not configured yet! Please configure your Constant Contact api first', 'fluentformpro'), 'configure_button_text' => __('Set Constant Contact API', 'fluentformpro') ]; return $integrations; } public function getIntegrationDefaults($settings, $formId) { return [ 'name' => '', 'list_id' => '', 'email_address' => '', 'first_name' => '', 'last_name' => '', 'job_title' => '', 'company_name' => '', 'home_phone' => '', 'work_phone' => '', 'address_line_1' => '', 'address_line_2' => '', 'city_name' => '', 'state_name' => '', 'zip_code' => '', 'country_name' => '', 'custom_fields' => (object)[], 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'update_if_exist' => false, 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { return [ 'fields' => [ [ 'key' => 'name', 'label' => __('Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Title', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'list_id', 'label' => __('Constant Contact List', 'fluentformpro'), 'placeholder' => __('Select Constant Contact Mailing List', 'fluentformpro'), 'tips' => __('Select the Constant Contact Mailing List you would like to add your contacts to.', 'fluentformpro'), 'component' => 'list_ajax_options', 'options' => $this->getLists(), ], [ 'key' => 'custom_fields', 'require_list' => true, 'label' => __('Map Fields', 'fluentformpro'), 'tips' => __('Select which Fluent Forms fields pair with their
    respective Constant Contact fields.', 'fluentformpro'), 'component' => 'map_fields', 'field_label_remote' => __('Constant Contact Field', 'fluentformpro'), 'field_label_local' => __('Form Field', 'fluentformpro'), 'primary_fileds' => [ [ 'key' => 'email_address', 'label' => __('Email Address', 'fluentformpro'), 'required' => true, 'input_options' => 'emails' ], [ 'key' => 'first_name', 'label' => __('First Name', 'fluentformpro'), ], [ 'key' => 'last_name', 'label' => __('Last Name', 'fluentformpro'), ], [ 'key' => 'job_title', 'label' => __('Job Title', 'fluentformpro') ], [ 'key' => 'company_name', 'label' => __('Company name', 'fluentformpro') ], [ 'key' => 'home_phone', 'label' => __('Home Phone Number', 'fluentformpro') ], [ 'key' => 'work_phone', 'label' => __('Work Phone Number', 'fluentformpro') ], [ 'key' => 'address_line_1', 'label' => __('Address Line 1', 'fluentformpro') ], [ 'key' => 'address_line_2', 'label' => __('Address Line 2', 'fluentformpro') ], [ 'key' => 'city_name', 'label' => __('City', 'fluentformpro') ], [ 'key' => 'state_name', 'label' => __('State', 'fluentformpro') ], [ 'key' => 'zip_code', 'label' => __('ZIP Code', 'fluentformpro') ] ] ], [ 'require_list' => true, 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow Constant Contact integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => true, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable This feed', 'fluentformpro') ] ], 'button_require_list' => true, 'integration_title' => $this->title ]; } protected function getLists() { $api = $this->getRemoteApi(); $lists = $api->get_lists(); $formateddLists = []; if(is_wp_error($lists)) { return $formateddLists; } foreach ($lists as $list) { $formateddLists[$list['id']] = $list['name']; } return $formateddLists; } protected function getConfigInstractions() { ob_start(); ?>

    Constant contact V3 is beta, so we just downgrade to V2 as per user request, see this instruction bellow to reauthenticate with V2

    1. Click here to Get Access Token.
    2. Then If you already have an account click "I already have an account"
    3. Copy your Constant Contact access token and paste bellow field
    getRemoteApi(); return $api->makeAuthorizationUrl(); } public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; if (!is_email($feedData['email_address'])) { $feedData['email_address'] = ArrayHelper::get($formData, $feedData['email_address']); } if (!is_email($feedData['email_address']) || !$feedData['list_id']) { do_action('fluentform/integration_action_result', $feed, 'failed', __('Constant Contact API call has been skipped because no valid email available', 'fluentformpro')); return false; } /* Prepare audience member import array. */ $subscriber_details = array( 'custom_fields' => array(), ); $mapFields = ArrayHelper::only($feedData, [ 'email_address', 'list_id', 'first_name', 'last_name', 'job_title', 'company_name', 'home_phone', 'work_phone', 'address_line_1', 'address_line_2', 'city_name', 'state_name', 'zip_code' ]); foreach ($mapFields as $field_name => $field_value) { if(!$field_value) { continue; } $emailTypes = [ 'email_address' => 'email_address' ]; if(in_array($field_name, array_keys($emailTypes))) { $field_value = trim( $field_value ); if ( ! isset( $subscriber_details['email_address'] ) ) { $subscriber_details['email_addresses'] = array(); } $subscriber_details['email_addresses'][0][ $emailTypes[$field_name] ] = $field_value; continue; } $addressTypes = [ 'address_line_1' => 'line1', 'address_line_2' => 'line2', 'city_name' => 'city', 'state_name' => 'state', 'zip_code' => 'postal_code', ]; if(in_array($field_name, array_keys($addressTypes))) { $field_value = trim( $field_value ); if ( ! isset( $subscriber_details['addresses'] ) ) { $subscriber_details['addresses'] = array(); } $subscriber_details['addresses'][0][ $addressTypes[$field_name] ] = $field_value; continue; } $listTypes = [ 'list_id' => 'id' ]; if(in_array($field_name, array_keys($listTypes))) { $field_value = trim( $field_value ); if ( ! isset( $subscriber_details['lists'] ) ) { $subscriber_details['lists'] = array(); } $subscriber_details['lists'][0][ $listTypes[$field_name] ] = $field_value; continue; } if ( ! isset( $subscriber_details[ $field_name ] ) ) { $subscriber_details[ $field_name ] = $field_value; } } if($subscriber_details['addresses']){ $subscriber_details['addresses'][0]['address_type'] = 'BUSINESS'; } if( !empty($feedData['work_number'])){ $subscriber_details['work_phone'] = $feedData['work_number']; } if( !empty($feedData['home_number'])){ $subscriber_details['home_phone'] = $feedData['home_number']; } if($customFiels = ArrayHelper::get($feedData, 'custom_fields')) { foreach ($customFiels as $fieldKey => $fieldValue) { if(!$fieldValue) { continue; } $subscriber_details['custom_fields'][] = array( 'custom_field_id' => $fieldKey, 'value' => $field_value, ); } } $subscriber_details = apply_filters_deprecated( 'fluentform_integration_data_' . $this->integrationKey, [ $subscriber_details, $feed, $entry ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/integration_data_' . $this->integrationKey, 'Use fluentform/integration_data_' . $this->integrationKey . ' instead of fluentform_integration_data_' . $this->integrationKey ); $subscriber_details = apply_filters('fluentform/integration_data_' . $this->integrationKey, $subscriber_details, $feed, $entry); $api = $this->getRemoteApi(); $subscription_results = $api->subscribeToList($subscriber_details); if ( !is_wp_error( $subscription_results ) && isset($subscription_results['id']) ) { do_action('fluentform/integration_action_result', $feed, 'success', __('Constant Contact has been successfully initialed and pushed data', 'fluentformpro')); } else { do_action('fluentform/integration_action_result', $feed, 'failed', ArrayHelper::get($subscription_results[0], 'error_message')); } } public function getMergeFields($list, $listId, $formId) { return []; } protected function getRemoteApi() { $Settings = get_option($this->optionKey); return new API($Settings['accessToken']); } } PK!/ (src/Integrations/ConstantContact/API.phpnu[appKey = FF_CC_APP_KEY; } $this->access_token = $access_token; } // To get the authorization url for authorization code public function makeAuthorizationUrl() { return $url = 'https://api.constantcontact.com/mashery/account/'. $this->appKey ; } public function auth_test() { return $account = $this->make_request('account/info', [], 'GET'); } private function getApiUrl($resource) { $parameters = []; if ($resource =='contacts') { $actionName = 'ACTION_BY_OWNER'; $actionName = apply_filters_deprecated( 'ff_integration_constantcontact_action_by', [ $actionName ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/integration_constantcontact_action_by', 'Use fluentform/integration_constantcontact_action_by instead of ff_integration_constantcontact_action_by.' ); $parameters['action_by'] = apply_filters('fluentform/integration_constantcontact_action_by', $actionName); } $parameters['api_key'] = $this->appKey; $paramString = http_build_query($parameters); return $this->api_url . $resource . '?' . $paramString; } public function make_request($resource, $data, $method = 'GET') { $requestApi = $this->getApiUrl($resource, $data); $args = array( 'headers' => array( 'Accept' => 'application/json', 'Content-Type' => 'application/json', 'Authorization' => 'Bearer'. ' ' . $this->access_token ), 'body' => json_encode($data) ); if ($method == 'GET') { unset($args['body']); $response = wp_remote_get($requestApi, $args); } else if ($method == 'POST') { $args['headers']['action_by'] = 'ACTION_BY_OWNER'; $response = wp_remote_post($requestApi, $args); } else { return (new \WP_Error(423, 'Request method could not be found')); } /* If WP_Error, die. Otherwise, return decoded JSON. */ if (is_wp_error($response)) { return (new \WP_Error(423, $response->get_error_message())); } return json_decode($response['body'], true); } public function get_lists(){ return $this->make_request('lists', [], 'GET'); } public function subscribeToList($data){ return $this->make_request('contacts', $data, 'POST'); } } PK!,h f7f7)src/Integrations/ConvertKit/Bootstrap.phpnu[logo = fluentFormMix('img/integrations/convertkit.png'); $this->description = 'Connect ConvertKit with Fluent Forms and create subscription forms right into WordPress and grow your list.'; $this->registerAdminHooks(); // add_filter('fluentform/notifying_async_convertkit', '__return_false'); } public function getGlobalFields($fields) { return [ 'logo' => $this->logo, 'menu_title' => __('ConvertKit Settings', 'fluentformpro'), 'menu_description' => __('ConvertKit is email marketing software for creators. Use Fluent Forms to collect customer information and automatically add it as ConvertKit subscriber list.', 'fluentformpro'), 'valid_message' => __('Your ConvertKit API Key is valid', 'fluentformpro'), 'invalid_message' => __('Your ConvertKit API Key is not valid', 'fluentformpro'), 'save_button_text' => __('Save Settings', 'fluentformpro'), 'fields' => [ 'apiKey' => [ 'type' => 'text', 'placeholder' => __('API Key', 'fluentformpro'), 'label_tips' => __("Enter your ConvertKit API Key, if you do not have
    Please login to your ConvertKit account and go to
    Profile -> Account Settings -> Account Info", 'fluentformpro'), 'label' => __('ConvertKit API Key', 'fluentformpro'), ], 'apiSecret' => [ 'type' => 'password', 'placeholder' => __('API Secret', 'fluentformpro'), 'label_tips' => __("Enter your ConvertKit API Secret, if you do not have
    Please login to your ConvertKit account and go to
    Profile -> Account Settings -> Account Info", 'fluentformpro'), 'label' => __('ConvertKit API Secret', 'fluentformpro'), ] ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your ConvertKit API integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect ConvertKit', 'fluentformpro'), 'data' => [ 'apiKey' => '' ], 'show_verify' => true ] ]; } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'apiKey' => '', 'apiSecret' => '', 'status' => '' ]; return wp_parse_args($globalSettings, $defaults); } public function saveGlobalSettings($settings) { if (!$settings['apiKey']) { $integrationSettings = [ 'apiKey' => '', 'apiSecret' => '', 'status' => false ]; // Update the reCaptcha details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your settings has been updated', 'fluentformpro'), 'status' => false ], 200); } // Verify API key now try { $integrationSettings = [ 'apiKey' => sanitize_text_field($settings['apiKey']), 'apiSecret' => sanitize_text_field($settings['apiSecret']), 'status' => false ]; update_option($this->optionKey, $integrationSettings, 'no'); $api = new API($settings['apiKey'], $settings['apiSecret']); $result = $api->auth_test(); if (!empty($result['error'])) { throw new \Exception($result['message']); } } catch (\Exception $exception) { wp_send_json_error([ 'message' => $exception->getMessage() ], 400); } // Integration key is verified now, Proceed now $integrationSettings = [ 'apiKey' => sanitize_text_field($settings['apiKey']), 'apiSecret' => sanitize_text_field($settings['apiSecret']), 'status' => true ]; // Update the reCaptcha details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your ConvertKit api key has been verified and successfully set', 'fluentformpro'), 'status' => true ], 200); } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => $this->title . ' Integration', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-convertkit-settings'), 'configure_message' => __('ConvertKit is not configured yet! Please configure your ConvertKit api first', 'fluentformpro'), 'configure_button_text' => __('Set ConvertKit API', 'fluentformpro') ]; return $integrations; } public function getIntegrationDefaults($settings, $formId) { return [ 'name' => '', 'list_id' => '', 'email' => '', 'first_name' => '', 'fields' => (object)[], 'tags' => [], 'tag_ids_selection_type' => 'simple', 'tag_routers' => [], 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'resubscribe' => false, 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { return [ 'fields' => [ [ 'key' => 'name', 'label' => __('Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'list_id', 'label' => __('ConvertKit Form', 'fluentformpro'), 'placeholder' => __('Select ConvertKit Form', 'fluentformpro'), 'tips' => __('Select the ConvertKit Form you would like to use to add subscriber', 'fluentformpro'), 'component' => 'list_ajax_options', 'options' => $this->getLists(), ], [ 'key' => 'fields', 'require_list' => true, 'label' => __('Map Fields', 'fluentformpro'), 'tips' => __('Select which Fluent Forms fields pair with their
    respective ConvertKit fields.', 'fluentformpro'), 'component' => 'map_fields', 'field_label_remote' => __('ConvertKit Field', 'fluentformpro'), 'field_label_local' => __('Form Field', 'fluentformpro'), 'primary_fileds' => [ [ 'key' => 'email', 'label' => __('Email Address', 'fluentformpro'), 'required' => true, 'input_options' => 'emails' ], [ 'key' => 'first_name', 'label' => __('First Name', 'fluentformpro') ] ] ], [ 'tips' => __('Select tags for this subscriber.', 'fluentformpro'), 'key' => 'tags', 'require_list' => true, 'label' => __('Contact Tags', 'fluentformpro'), 'placeholder' => __('Select Tags', 'fluentformpro'), 'component' => 'selection_routing', 'simple_component' => 'select', 'routing_input_type' => 'select', 'routing_key' => 'tag_ids_selection_type', 'settings_key' => 'tag_routers', 'is_multiple' => true, 'labels' => [ 'choice_label' => __('Enable Dynamic Tag Selection', 'fluentformpro'), 'input_label' => '', 'input_placeholder' => __('Set Tag', 'fluentformpro') ], 'options' => $this->getTags() ], [ 'require_list' => true, 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow ConvertKit integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => true, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable This feed', 'fluentformpro'), ] ], 'button_require_list' => true, 'integration_title' => $this->title ]; } protected function getLists() { $api = $this->getRemoteClient(); $lists = $api->getLists(); $formateddLists = []; foreach ($lists as $list) { $formateddLists[$list['id']] = $list['name']; } return $formateddLists; } protected function getTags() { $api = $this->getRemoteClient(); $tags = $api->getTags(); $formatedTags = []; foreach ($tags as $tag) { $formatedTags[strval($tag['id'])] = $tag['name']; } return $formatedTags; } public function getMergeFields($list, $listId, $formId) { $api = $this->getRemoteClient(); if (!$api) { return []; } $fields = $api->getCustomFields(); $formattedFields = []; foreach ($fields as $field) { $formattedFields[$field['key']] = $field['label']; } return $formattedFields; } /* * Form Submission Hooks Here */ public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; if (!is_email($feedData['email'])) { $feedData['email'] = ArrayHelper::get($formData, $feedData['email']); } if(!is_email($feedData['email'])) { do_action('fluentform/integration_action_result', $feed, 'failed', __('ConvertKit API call has been skipped because no valid email available', 'fluentformpro')); return; } $subscriber = [ 'email' => $feedData['email'], 'first_name' => ArrayHelper::get($feedData, 'first_name') ]; $customFields = []; foreach (ArrayHelper::get($feedData, 'fields', []) as $key => $value) { if (!$value) { continue; } $customFields[$key] = $value; } $tags = $this->getSelectedTagIds($feedData, $formData, 'tags'); if ($tags) { $subscriber['tags'] = $tags; } if($customFields) { $subscriber['fields'] = $customFields; } $subscriber = array_filter($subscriber); $subscriber = apply_filters_deprecated( 'fluentform_integration_data_' . $this->integrationKey, [ $subscriber, $feed, $entry ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/integration_data_' . $this->integrationKey, 'Use fluentform/integration_data_' . $this->integrationKey . ' instead of fluentform_integration_data_' . $this->integrationKey ); $subscriber = apply_filters('fluentform/integration_data_' . $this->integrationKey, $subscriber, $feed, $entry); $api = $this->getRemoteClient(); $response = $api->subscribe($feedData['list_id'], $subscriber); if(is_wp_error($response)) { do_action('fluentform/integration_action_result', $feed, 'failed', $response->get_error_message()); } else { do_action('fluentform/integration_action_result', $feed, 'success', __('ConvertKit feed has been successfully initialed and pushed data', 'fluentformpro')); } } public function getRemoteClient() { $settings = $this->getGlobalSettings([]); return new API($settings['apiKey'], $settings['apiSecret']); } } PK!L #src/Integrations/ConvertKit/API.phpnu[apiKey = $apiKey; $this->apiSecret = $apiSecret; } public function default_options() { return array( 'api_key' => $this->apiKey ); } public function make_request( $action, $options = array(), $method = 'GET' ) { /* Build request options string. */ $request_options = $this->default_options(); $request_options = wp_parse_args($options, $request_options); $options_string = http_build_query( $request_options ); /* Execute request based on method. */ switch ( $method ) { case 'POST': $args = array( 'body' => json_encode($options), 'headers' => [ 'Accept' => 'application/json', 'Content-Type' => 'application/json' ] ); $response = wp_remote_post( $this->apiUrl.$action.'?api_key='.$this->apiKey, $args ); break; case 'GET': /* Build request URL. */ $request_url = $this->apiUrl . $action.'?' . $options_string; $response = wp_remote_get( $request_url ); break; } /* If WP_Error, die. Otherwise, return decoded JSON. */ if ( is_wp_error( $response ) ) { return [ 'error' => 'API_Error', 'message' => $response->get_error_message() ]; } else { return json_decode( $response['body'], true ); } } /** * Test the provided API credentials. * * @access public * @return bool */ public function auth_test() { return $this->make_request('forms', [], 'GET'); } public function subscribe($formId, $data) { $response = $this->make_request('forms/'.$formId.'/subscribe', $data, 'POST'); if(!empty($response['error'])) { return new \WP_Error('api_error', $response['message']); } return $response['subscription']; } /** * Get all Forms in the system. * * @access public * @return array */ public function getLists() { $response = $this->make_request( 'forms', array(), 'GET' ); if(empty($response['error'])) { return $response['forms']; } return []; } /** * Get all Tags in the system. * * @access public * @return array */ public function getTags() { $response = $this->make_request( 'tags', array(), 'GET' ); if(empty($response['error'])) { return $response['tags']; } return false; } public function getCustomFields() { $response = $this->make_request( 'custom_fields', array(), 'GET' ); if(empty($response['error'])) { return $response['custom_fields']; } return false; } } PK!ѓ$"$"&src/Integrations/Discord/Bootstrap.phpnu[logo = fluentFormMix('img/integrations/discord.png'); $this->description = __( 'Send notification with form data to your Discord channel when a form is submitted.', 'fluentformpro'); add_filter('fluentform/save_integration_value_' . $this->integrationKey, [$this, 'validate'], 10, 3); $this->registerAdminHooks(); // add_filter('fluentform/notifying_async_' . $this->integrationKey, '__return_false'); } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'category' => 'crm', 'disable_global_settings' => 'yes', 'logo' => $this->logo, 'title' => $this->title . ' Integration', 'is_active' => $this->isConfigured() ]; return $integrations; } public function getIntegrationDefaults($settings, $formId) { return [ 'name' => '', 'description' => '', 'footer' => '', 'webhook' => '', 'fields' => [], 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { return [ 'fields' => [ [ 'key' => 'name', 'label' => __('Feed Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'webhook', 'label' => __('Webhook Url', 'fluentformpro'), 'tips' => __( 'Paste your webhook url here. Click "Edit Channel" cog and create your channel webhook from integrations.', 'fluentformpro' ), 'component' => 'text', 'placeholder' => __('Webhook', 'fluentformpro'), 'required' => true, ], [ 'key' => 'description', 'label' => __('Description', 'fluentformpro'), 'placeholder' => __('Discord Message Description', 'fluentformpro'), 'component' => 'value_textarea' ], [ 'key' => 'fields', 'label' => __('Input Fields', 'fluentformpro'), 'component' => 'checkbox-multiple-text', 'options' => $this->getInputFields($formId), ], [ 'key' => 'footer', 'label' => __('Footer', 'fluentformpro'), 'placeholder' => __('Discord Message Footer', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __( 'Allow Discord integration conditionally based on your submission values', 'fluentformpro' ), 'component' => 'conditional_block' ], [ 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable This feed', 'fluentformpro'), ], ], 'integration_title' => $this->title ]; } public function getMergeFields($list = false, $listId = false, $formId = false) { return []; } public function addGlobalMenu($setting) { return $setting; } public function isConfigured() { return true; } public function getInputFields($formId) { $formApi = fluentFormApi()->form($formId); return $formApi->labels(); } public function validate($settings, $integrationId, $formId) { if (!$settings['webhook']) { wp_send_json_error([ 'message' => __('Validation Failed', 'fluentformpro'), 'errors' => [ 'webhook' => ['Webhook is required'] ] ], 423); } return $settings; } public function notify($feed, $formData, $entry, $form) { $settings = $feed['processedValues']; $inputs = FormFieldsParser::getEntryInputs($form); $labels = FormFieldsParser::getAdminLabels($form, $inputs); $messageTitle = ArrayHelper::get($settings, 'name'); $parsedFormData = FormDataParser::parseData((object)$formData, $inputs, $form->id); $fields = []; $selectedFields = ArrayHelper::get($settings,'fields'); foreach ($selectedFields as $label => $key) { if (empty($value = ArrayHelper::get($parsedFormData, $key)) && $value !== "0") { continue; } if ($element = ArrayHelper::get($inputs, $key)) { if ( 'tabular_grid' == ArrayHelper::get($element, 'element') && $gridValue = Helper::getTabularGridFormatValue($formData[$key], $element, "\n", ", ") ) { $value = $gridValue; } } $fields[] = [ 'name' => ArrayHelper::get($labels,$key), 'value' => str_replace('
    ', "\n", $value), 'inline' => true ]; } $webhook = ArrayHelper::get($settings, 'webhook'); $description = ArrayHelper::get($settings, 'description'); $footer = ArrayHelper::get($settings, 'footer'); $entryLink = admin_url( 'admin.php?page=fluent_forms&form_id=' . $form->id . '&route=entries#/entries/' . $entry->id ); $messageArgs = [ 'embeds' => [ 0 => [ 'fields' => $fields, 'title' => esc_html($messageTitle), 'url' => esc_url_raw($entryLink), 'description' => sanitize_text_field($description), 'color' => hexdec('3F9EFF'), 'footer' => [ 'text' => sanitize_text_field($footer) ] ], ], 'content' => '*New submission on '. $form->title.' (#' . $entry->id . ')*' ]; $messageArgs = apply_filters_deprecated( 'ff_integration_discord_message', [ $messageArgs, $feed ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/integration_discord_message', 'Use fluentform/integration_discord_message instead of ff_integration_discord_message.' ); $message = apply_filters('fluentform/integration_discord_message', $messageArgs, $feed); $response = Discord::sendMessage($webhook, $message); if (is_wp_error($response)) { do_action('fluentform/integration_action_result', $feed, 'failed', $response->get_error_message()); } else { do_action( 'fluentform/integration_action_result', $feed, 'success', __('Discord feed has been successfully initialed and pushed data','fluentformpro') ); } } } PK!RL$src/Integrations/Discord/Discord.phpnu[ json_encode($message) ]; $res = wp_remote_post($webhook, [ 'body' => $data, 'header' => [ 'content-type' => 'multipart/form-data', ] ]); if(!is_wp_error($res) && ($res['response']['code'] == 200 || $res['response']['code'] == 201 || $res['response']['code'] == 204)) { return true; } return new \WP_Error($res['response']['code'] ,wp_remote_retrieve_response_message($res)); } } PK!nBB#src/Integrations/Drip/Bootstrap.phpnu[logo = fluentFormMix('img/integrations/drip.png'); $this->description = 'This module lets you create Drip subscribers from WordPress, so you can build your email list.'; $this->registerAdminHooks(); // add_filter('fluentform/notifying_async_drip', '__return_false'); } public function getGlobalFields($fields) { return [ 'logo' => $this->logo, 'menu_title' => __('Drip API Settings', 'fluentformpro'), 'menu_description' => __('Drip is an ECRM and Ecommerce CRM designed for building personal and profitable relationships with your customers at scale. Use Fluent Forms to collect customer information and automatically add it to your Drip list.', 'fluentformpro'), 'valid_message' => __('Your Drip configuration is valid', 'fluentformpro'), 'invalid_message' => __('Your Drip configuration is invalid', 'fluentformpro'), 'save_button_text' => __('Save Settings', 'fluentformpro'), 'fields' => [ 'apiKey' => [ 'type' => 'password', 'placeholder' => __('API Token', 'fluentformpro'), 'label_tips' => __("Enter your Drip API Key, if you do not have
    Please login to your Drip account settings -> User Info and find the api key", 'fluentformpro'), 'label' => __('Drip API Token', 'fluentformpro'), ], 'accountId' => [ 'type' => 'number', 'placeholder' => __('Account ID', 'fluentformpro'), 'required' => true, 'label_tips' => __("Please Provide your Drip Account ID. Go to your Drip account settings -> general info and find the Account ID", 'fluentformpro'), 'label' => __('Drip Account ID', 'fluentformpro'), ], ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your Drip API integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect Drip', 'fluentformpro'), 'data' => [ 'apiKey' => '' ], 'show_verify' => true ] ]; } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'apiKey' => '', 'accountId' => '', 'status' => '' ]; return wp_parse_args($globalSettings, $defaults); } public function saveGlobalSettings($settings) { if (!$settings['apiKey']) { $integrationSettings = [ 'apiKey' => '', 'accountId' => '', 'status' => false ]; // Update the reCaptcha details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your settings has been updated and discarded', 'fluentformpro'), 'status' => false ], 200); } try { $settings['status'] = false; update_option($this->optionKey, $settings, 'no'); $api = new DripApi($settings['apiKey'], $settings['accountId']); $auth = $api->auth_test(); if (!empty($auth['accounts'])) { $settings['status'] = true; update_option($this->optionKey, $settings, 'no'); wp_send_json_success([ 'status' => true, 'message' => __('Your settings has been updated!', 'fluentformpro') ], 200); } $message = 'Invalid Credentials'; if (is_wp_error($auth)) { $message = $auth->get_error_message(); } else if (isset($auth['errors'][0]['message'])) { $message = $auth['errors'][0]['message']; } throw new \Exception($message, 423); } catch (\Exception $e) { wp_send_json_error([ 'status' => false, 'message' => $e->getMessage() ], $e->getCode()); } } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => $this->title . ' Integration', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-drip-settings'), 'configure_message' => __('Drip is not configured yet! Please configure your Drip API first', 'fluentformpro'), 'configure_button_text' => __('Set Drip API', 'fluentformpro') ]; return $integrations; } public function getIntegrationDefaults($settings, $formId) { return [ 'name' => '', 'fieldEmailAddress' => '', 'custom_field_mappings' => (object)[], 'default_fields' => (object)[], 'other_fields_mapping' => [ [ 'item_value' => '', 'label' => '' ] ], 'custom_fields' => [ [ 'item_value' => '', 'label' => '' ] ], 'ip_address' => '{ip}', 'eu_consent' => '', 'tags' => '', 'tag_routers' => [], 'tag_ids_selection_type' => 'simple', 'remove_tags' => '', 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { return [ 'fields' => [ [ 'key' => 'name', 'label' => __('Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'custom_field_mappings', 'require_list' => false, 'label' => __('Map Fields', 'fluentformpro'), 'tips' => __('Select which Fluent Forms fields pair with their
    respective Drip fields.', 'fluentformpro'), 'component' => 'map_fields', 'field_label_remote' => __('Drip Field', 'fluentformpro'), 'field_label_local' => __('Form Field', 'fluentformpro'), 'primary_fileds' => [ [ 'key' => 'fieldEmailAddress', 'label' => __('Email Address', 'fluentformpro'), 'required' => true, 'input_options' => 'emails' ] ], 'default_fields' => [ array( 'name' => 'first_name', 'label' => esc_html__('First Name', 'fluentformpro'), 'required' => false ), array( 'name' => 'last_name', 'label' => esc_html__('Last Name', 'fluentformpro'), 'required' => false ) ] ], [ 'key' => 'other_fields_mapping', 'require_list' => false, 'label' => __('Other Fields', 'fluentformpro'), 'tips' => __('Select which Fluent Forms fields pair with their
    respective Drip fields.', 'fluentformpro'), 'component' => 'dropdown_many_fields', 'field_label_remote' => __('Drip Field', 'fluentformpro'), 'field_label_local' => __('Form Field', 'fluentformpro'), 'options' => [ 'address1' => __('Address Line 1', 'fluentformpro'), 'address2' => __('Address Line 2', 'fluentformpro'), 'city' => __('City', 'fluentformpro'), 'state' => __('State', 'fluentformpro'), 'zip' => __('ZIP code', 'fluentformpro'), 'country' => __('Country', 'fluentformpro'), 'phone' => __('Phone', 'fluentformpro') ] ], [ 'key' => 'custom_fields', 'require_list' => false, 'label' => __('Custom Fields', 'fluentformpro'), 'tips' => __('custom field data', 'fluentformpro'), 'component' => 'dropdown_label_repeater', ], [ 'key' => 'tags', 'require_list' => false, 'label' => __('Contact Tags', 'fluentformpro'), 'tips' => __('Associate tags to your Drip contacts with a comma separated list (e.g. new lead, FluentForms, web source). Commas within a merge tag value will be created as a single tag.', 'fluentformpro'), 'component' => 'selection_routing', 'simple_component' => 'value_text', 'routing_input_type' => 'text', 'routing_key' => 'tag_ids_selection_type', 'settings_key' => 'tag_routers', 'labels' => [ 'choice_label' => __('Enable Dynamic Tag Input', 'fluentformpro'), 'input_label' => '', 'input_placeholder' => __('Tag', 'fluentformpro') ], 'inline_tip' => __('Please provide each tag by comma separated value, You can use dynamic smart codes', 'fluentformpro') ], [ 'require_list' => false, 'key' => 'remove_tags', 'label' => __('Remove tags', 'fluentformpro'), 'placeholder' => __('Type Tags (comma separated)', 'fluentformpro'), 'tips' => __('Type tags as comma separated that need to be removed', 'fluentformpro'), 'component' => 'value_text' ], [ 'require_list' => false, 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow Drip integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => false, 'key' => 'eu_consent', 'label' => __('EU Consent', 'fluentformpro'), 'tips' => __('specifying whether the subscriber granted for GDPR consent', 'fluentformpro'), 'component' => 'radio_choice', 'options' => [ '' => __('Default', 'fluentformpro'), 'granted' => __('Granted', 'fluentformpro'), ] ], [ 'require_list' => false, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable This feed', 'fluentformpro') ] ], 'button_require_list' => false, 'integration_title' => $this->title ]; } public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; if (!is_email($feedData['fieldEmailAddress'])) { $feedData['fieldEmailAddress'] = ArrayHelper::get($formData, $feedData['fieldEmailAddress']); } if (!is_email($feedData['fieldEmailAddress'])) { do_action('fluentform/integration_action_result', $feed, 'failed', __('Drip API called skipped because no valid email available', 'fluentformpro')); return; } $addData = [ 'email' => $feedData['fieldEmailAddress'] ]; $addData = array_merge($addData, ArrayHelper::get($feedData, 'default_fields')); foreach (ArrayHelper::get($feedData, 'other_fields_mapping') as $item) { $addData[$item['label']] = $item['item_value']; } if ($customFields = ArrayHelper::get($feedData, 'custom_fields')) { $customData = []; foreach ($customFields as $customField) { $customData[$customField['label']] = $customField['item_value']; } $customData = array_filter($customData); if ($customData) { $addData['custom_fields'] = $customData; } } $tags = $this->getSelectedTagIds($feedData, $formData, 'tags'); if(!is_array($tags)) { $tags = explode(',', $tags); } $tags = array_map('trim', $tags); $tags = array_filter($tags); if ($tags) { $addData['tags'] = $tags; } $removeTags = array_filter(explode(",", $feedData['remove_tags'])); if ($removeTags) { $addData['remove_tags'] = array_map('trim', $removeTags); } if (!empty($feedData['ip_address'])) { $addData['ip_address'] = $feedData['ip_address']; } if (!empty($feedData['eu_consent'])) { $addData['eu_consent'] = $feedData['eu_consent']; } $addData = array_filter($addData); $addData = apply_filters_deprecated( 'fluentform_integration_data_' . $this->integrationKey, [ $addData, $feed, $entry ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/integration_data_' . $this->integrationKey, 'Use fluentform/integration_data_' . $this->integrationKey . ' instead of fluentform_integration_data_' . $this->integrationKey ); $addData = apply_filters('fluentform/integration_data_' . $this->integrationKey, $addData, $feed, $entry); // Now let's prepare the data and push to drip $api = $this->getApiClient(); $response = $api->addContact($addData); if (!is_wp_error($response)) { do_action('fluentform/integration_action_result', $feed, 'success', __('Drip feed has been successfully initialed and pushed data', 'fluentformpro')); } else { $error = is_wp_error($response) ? $response->get_error_messages() : __('API Error when submitting Data', 'fluentformpro'); do_action('fluentform/integration_action_result', $feed, 'failed', $error); } } protected function getApiClient() { $settings = $this->getGlobalSettings([]); return new DripApi( $settings['apiKey'], $settings['accountId'] ); } public function getMergeFields($list, $listId, $formId) { return []; } } PK!:݌4 4 !src/Integrations/Drip/DripApi.phpnu[apiKey = $apiKey; $this->accountId = $accountId; } public function make_request($endpoint = '', $data = array(), $method = 'POST') { $data['api_key'] = $this->apiKey; $args = array( 'method' => $method, 'headers' => array( 'content-type' => 'application/vnd.api+json', 'Authorization' => 'Basic '.base64_encode( $this->apiKey ) ), ); if($method == 'POST') { $args['body'] = wp_json_encode($data); $response = wp_remote_post($this->apiUrl.$endpoint, $args); } else { $response = wp_remote_get($this->apiUrl.$endpoint, $args); } /* If WP_Error, die. Otherwise, return decoded JSON. */ if (is_wp_error($response)) { return $response; } return json_decode($response['body'], true); } /** * Test the provided API credentials. * * @access public * @return array|\WP_Error */ public function auth_test() { return $this->make_request('accounts', [], 'GET'); } public function addContact($contact) { $accountId = $this->accountId; $contactObj = [ 'subscribers' => [$contact] ]; $response = $this->make_request($accountId.'/subscribers',$contactObj, 'POST'); if(!empty($response['subscribers'])) { return $response; } $message = 'API Eroror'; if(is_wp_error($response)) { $message= $response->get_error_message(); } return new \WP_Error('error', $message); } public function add_note( $contact_id, $email, $note ) { return $this->make_request([ 'action' => 'contact_add_note', 'value' => (object) [ 'contact_id' => $contact_id, 'email' => $email, 'note' => $note ], ], 'POST'); } } PK!Im0m0&src/Integrations/GetGist/Bootstrap.phpnu[logo = fluentFormMix('img/integrations/getgist.png'); $this->description = 'Gist is an email marketing tool, and you can connect Fluent Forms to build email lists.'; $this->registerAdminHooks(); // add_filter('fluentform/notifying_async_getgist', '__return_false'); } public function getGlobalFields($fields) { return [ 'logo' => $this->logo, 'menu_title' => __('GetGist Settings', 'fluentformpro'), 'menu_description' => $this->description, 'valid_message' => __('Your GetGist API Key is valid', 'fluentformpro'), 'invalid_message' => __('Your GetGist API Key is not valid', 'fluentformpro'), 'save_button_text' => __('Save Settings', 'fluentformpro'), 'fields' => [ 'apiKey' => [ 'type' => 'text', 'placeholder' => __('API Key', 'fluentformpro'), 'label_tips' => __("Enter your GetGist API Key, if you do not have
    Please log in to your GetGist account and go to
    Settings -> Integrations -> API key", 'fluentformpro'), 'label' => __('GetGist API Key', 'fluentformpro'), ] ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your GetGist API integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect GetGist', 'fluentformpro'), 'data' => [ 'apiKey' => '' ], 'show_verify' => true ] ]; } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'apiKey' => '', 'status' => '' ]; return wp_parse_args($globalSettings, $defaults); } public function saveGlobalSettings($settings) { if (!$settings['apiKey']) { $integrationSettings = [ 'apiKey' => '', 'status' => false ]; // Update the reCaptcha details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your settings has been updated', 'fluentformpro'), 'status' => false ], 200); } // Verify API key now try { $integrationSettings = [ 'apiKey' => sanitize_text_field($settings['apiKey']), 'status' => false ]; update_option($this->optionKey, $integrationSettings, 'no'); $api = new API($settings['apiKey']); $result = $api->auth_test(); if (!empty($result['error'])) { throw new \Exception($result['message']); } } catch (\Exception $exception) { wp_send_json_error([ 'message' => $exception->getMessage() ], 400); } // Integration key is verified now, Proceed now $integrationSettings = [ 'apiKey' => sanitize_text_field($settings['apiKey']), 'status' => true ]; // Update the reCaptcha details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your GetGist api key has been verified and successfully set', 'fluentformpro'), 'status' => true ], 200); } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => $this->title . ' Integration', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-getgist-settings'), 'configure_message' => __('GetGist is not configured yet! Please configure your GetGist api first', 'fluentformpro'), 'configure_button_text' => __('Set GetGist API', 'fluentformpro') ]; return $integrations; } public function getIntegrationDefaults($settings, $formId) { return [ 'name' => '', 'list_id' => '', 'fields' => (object)[], 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'resubscribe' => false, 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { return [ 'fields' => [ [ 'key' => 'name', 'label' => __('Feed Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'fields', 'label' => __('Map Fields', 'fluentformpro'), 'tips' => __('Select which Fluent Forms fields pair with their
    respective Gist fields.', 'fluentformpro'), 'component' => 'map_fields', 'field_label_remote' => __('Gist Field', 'fluentformpro'), 'field_label_local' => __('Form Field', 'fluentformpro'), 'primary_fileds' => [ [ 'key' => 'email', 'label' => __('Email Address', 'fluentformpro'), 'required' => true, 'input_options' => 'emails' ], [ 'key' => 'lead_name', 'label' => __('Name', 'fluentformpro'), 'required' => false ], [ 'key' => 'lead_phone', 'label' => __('Phone', 'fluentformpro'), 'required' => false ] ] ], [ 'key' => 'tags', 'label' => __('Lead Tags', 'fluentformpro'), 'required' => false, 'placeholder' => __('Tags', 'fluentformpro'), 'component' => 'value_text', 'inline_tip' => __('Use comma separated value. You can use smart tags here', 'fluentformpro') ], [ 'key' => 'landing_url', 'label' => __('Landing URL', 'fluentformpro'), 'tips' => __('When this option is enabled, FluentForm will pass the form page url to the gist lead', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable Landing URL', 'fluentformpro') ], [ 'key' => 'last_seen_ip', 'label' => __('Push IP Address', 'fluentformpro'), 'tips' => __('When this option is enabled, FluentForm will pass the last_seen_ip to gist', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable last IP address', 'fluentformpro') ], [ 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow Gist integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable This feed', 'fluentformpro') ] ], 'integration_title' => $this->title ]; } protected function getLists() { return []; } public function getMergeFields($list = false, $listId = false, $formId = false) { return []; } /* * Form Submission Hooks Here */ public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; $subscriber = [ 'name' => ArrayHelper::get($feedData, 'lead_name'), 'email' => ArrayHelper::get($feedData, 'email'), 'phone' => ArrayHelper::get($feedData, 'lead_phone'), 'created_at' => time(), 'last_seen_at' => time() ]; $tags = ArrayHelper::get($feedData, 'tags'); if($tags) { $tags = explode(',', $tags); $formtedTags = []; foreach ($tags as $tag) { $formtedTags[] = wp_strip_all_tags(trim($tag)); } $subscriber['tags'] = $formtedTags; } if(ArrayHelper::isTrue($feedData, 'landing_url')) { $subscriber['landing_url'] = $entry->source_url; } if(ArrayHelper::isTrue($feedData, 'last_seen_ip')) { $subscriber['last_seen_ip'] = $entry->ip; } $subscriber = array_filter($subscriber); if(!empty($subscriber['email']) && !is_email($subscriber['email'])) { $subscriber['email'] = ArrayHelper::get($formData, $subscriber['email']); } if(!is_email($subscriber['email'])) { do_action('fluentform/integration_action_result', $feed, 'failed', __('GetGist API called skipped because no valid email available', 'fluentformpro')); return; } $subscriber = apply_filters_deprecated( 'fluentform_integration_data_' . $this->integrationKey, [ $subscriber, $feed, $entry ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/integration_data_' . $this->integrationKey, 'Use fluentform/integration_data_' . $this->integrationKey . ' instead of fluentform_integration_data_' . $this->integrationKey ); $subscriber = apply_filters('fluentform/integration_data_' . $this->integrationKey, $subscriber, $feed, $entry); $api = $this->getRemoteClient(); $response = $api->subscribe($subscriber); if (is_wp_error($response)) { do_action('fluentform/integration_action_result', $feed, 'failed', $response->get_error_message()); } else { do_action('fluentform/integration_action_result', $feed, 'success', __('GetGist feed has been successfully initialed and pushed data', 'fluentformpro')); } } public function getRemoteClient() { $settings = $this->getGlobalSettings([]); return new API($settings['apiKey']); } } PK!Dέ src/Integrations/GetGist/API.phpnu[apiKey = $apiKey; } public function default_options() { return [ 'Authorization' => 'Bearer '.$this->apiKey, 'Content-Type' => 'application/json', 'Accept' => 'application/json' ]; } public function make_request($action, $options = array(), $method = 'GET') { /* Execute request based on method. */ switch ($method) { case 'POST': $headers = $this->default_options(); $endpointUrl = $this->apiUrl . $action; $args = [ 'headers' => $headers, 'body' => json_encode($options) ]; $response = wp_remote_post($endpointUrl, $args); break; case 'GET': $headers = $this->default_options(); $endpointUrl = $this->apiUrl . $action; $args = [ 'headers' => $headers ]; $response = wp_remote_get($endpointUrl, $args); break; } /* If WP_Error, die. Otherwise, return decoded JSON. */ if (is_wp_error($response) ) { return [ 'error' => 'API_Error', 'message' => $response->get_error_message() ]; } else if($response && $response['response']['code'] >= 300) { return [ 'error' => 'API_Error', 'message' => $response['response']['message'] ]; } else { return json_decode($response['body'], true); } } /** * Test the provided API credentials. * * @access public * @return bool */ public function auth_test() { return $this->make_request('leads', [], 'GET'); } public function subscribe($data) { $response = $this->make_request('leads', $data, 'POST'); if (!empty($response['error'])) { return new \WP_Error('api_error', $response['message']); } return $response; } /** * Get all Forms in the system. * * @access public * @return array */ public function getGroups() { $response = $this->make_request('groups', array(), 'GET'); if (empty($response['error'])) { return $response; } return []; } public function getCustomFields() { $response = $this->make_request('fields', array(), 'GET'); if (empty($response['error'])) { return $response; } return false; } } PK!Q݆33*src/Integrations/GetResponse/Bootstrap.phpnu[description = 'Build your email list with Fluent Forms and GetResponse. Create subscribe forms and collect leads.'; $this->logo = fluentFormMix('img/integrations/getresponse.png'); $this->registerAdminHooks(); // add_filter('fluentform/notifying_async_getresponse', '__return_false'); } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'apiKey' => '', 'status' => '' ]; return wp_parse_args($globalSettings, $defaults); } public function saveGlobalSettings($settings) { if (!$settings['apiKey']) { $integrationSettings = [ 'apiKey' => '', 'status' => false ]; // Update the reCaptcha details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your settings has been updated and discarded', 'fluentformpro'), 'status' => false ], 200); } try { $apiKey = $settings['apiKey']; update_option($this->optionKey, [ 'status' => false, 'apiKey' => $apiKey ], 'no'); $response = (new GetResponseApi($apiKey))->ping(); if (empty($response->codeDescription)) { update_option($this->optionKey, [ 'status' => true, 'apiKey' => $apiKey ], 'no'); wp_send_json_success([ 'status' => true, 'message' => __('Your settings has been updated!', 'fluentformpro') ], 200); } throw new \Exception($response->codeDescription, 400); } catch (\Exception $e) { wp_send_json_error([ 'status' => false, 'message' => $e->getMessage() ], $e->getCode()); } } public function getGlobalFields($fields) { return [ 'logo' => $this->logo, 'menu_title' => __('GetResponse API Settings', 'fluentformpro'), 'menu_description' => __('GetResponse is an email marketing platform. It enables you to send email newsletters, campaigns, online surveys and follow-up autoresponders. Simple, easy interface. Use Fluent Forms to collect customer information and automatically add it to your GetResponse list. If you don\'t have a GetResponse account, you can sign up for one here.', 'fluentformpro'), 'valid_message' => __('Your GetResponse configuration is valid', 'fluentformpro'), 'invalid_message' => __('Your GetResponse configuration is invalid', 'fluentformpro'), 'save_button_text' => __('Save Settings', 'fluentformpro'), 'fields' => [ 'apiKey' => [ 'type' => 'password', 'placeholder' => __('API Key', 'fluentformpro'), 'label_tips' => __("Enter your GetResponse API Key, if you do not have
    Please login to your GetResponse account and go to
    Integrations & API from main menu.", 'fluentformpro'), 'label' => __('GetResponse API Key', 'fluentformpro'), ] ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your GetResponse API integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect GetResponse', 'fluentformpro'), 'data' => [ 'apiKey' => '' ] ] ]; } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => $this->title . ' Integration', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-getresponse-settings'), 'configure_message' => __('GetResponse API Key is not configured yet! Please configure your GetResponse api first', 'fluentformpro'), 'configure_button_text' => __('Set GetResponse API', 'fluentformpro') ]; return $integrations; } public function getIntegrationDefaults($settings, $formId) { return [ 'name' => '', 'list_id' => '', 'fieldName' => '', 'fieldEmailAddress' => '', 'field_mappings' => (object)[], 'dayOfCycle' => '', 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { return [ 'fields' => [ [ 'key' => 'name', 'label' => __('Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'list_id', 'label' => __('GetResponse List', 'fluentformpro'), 'placeholder' => __('Select GetResponse List', 'fluentformpro'), 'tips' => __('Select the GetResponse List you would like to add your contacts to.', 'fluentformpro'), 'component' => 'list_ajax_options', 'options' => $this->getLists(), ], [ 'key' => 'field_mappings', 'require_list' => true, 'label' => __('Map Fields', 'fluentformpro'), 'tips' => __('Select which Fluent Forms fields pair with their
    respective GetResponse fields.', 'fluentformpro'), 'component' => 'map_fields', 'field_label_remote' => __('GetResponse Field', 'fluentformpro'), 'field_label_local' => __('Form Field', 'fluentformpro'), 'primary_fileds' => [ [ 'key' => 'fieldEmailAddress', 'label' => __('Email Address', 'fluentformpro'), 'required' => true, 'input_options' => 'emails' ], [ 'key' => 'fieldName', 'label' => __('Name', 'fluentformpro'), ] ] ], [ 'require_list' => true, 'key' => 'dayOfCycle', 'label' => __('Autoresponder Cycle', 'fluentformpro'), 'tips' => __('The day on which the contacts is in the Autoresponder cycle, keep empty to not include in autoresponder.', 'fluentformpro'), 'component' => 'number' ], [ 'require_list' => true, 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow GetResponse integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => true, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable This feed', 'fluentformpro'), ] ], 'button_require_list' => true, 'integration_title' => $this->title ]; } protected function getLists() { $api = $this->getApiClient(); if (!$api) { return []; } $lists = $api->getCampaigns(); $formattedLists = []; foreach ($lists as $list) { $formattedLists[$list->campaignId] = $list->name; } return $formattedLists; } public function getMergeFields($list, $listId, $formId) { $api = $this->getApiClient(); if (!$api) { return []; } $fields = $api->getCustomFields(); $formattedFields = []; foreach ($fields as $field) { $formattedFields[$field->customFieldId] = $field->name; } return $formattedFields; } /* * Handle Notification Broadcast here */ public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; if (!is_email($feedData['fieldEmailAddress'])) { $feedData['fieldEmailAddress'] = ArrayHelper::get($formData, $feedData['fieldEmailAddress']); } if (!is_email($feedData['fieldEmailAddress'])) { do_action('fluentform/integration_action_result', $feed, 'failed', __('GetResponse API call has been skipped because no valid email available', 'fluentformpro')); } $mainFields = ArrayHelper::only($feedData, [ 'fieldName', 'fieldEmailAddress' ]); $addData = [ 'email' => $mainFields['fieldEmailAddress'], 'campaign' => [ 'campaignId' => $feedData['list_id'] ] ]; if ($nameField = ArrayHelper::get($mainFields, 'fieldName')) { $addData['name'] = $nameField; } $dayOfCycle = (string) ArrayHelper::get($feed,'settings.dayOfCycle',''); if($dayOfCycle!=''){ $addData['dayOfCycle'] = $dayOfCycle; } $customValues = []; foreach ($feedData['field_mappings'] as $key => $value) { if($value) { $customValues[] = [ 'customFieldId' => $key, 'value' => [ $value ] ]; } } if($customValues) { $addData['customFieldValues'] = $customValues; } if($entry->ip) { $addData['ipAddress'] = $entry->ip; } $addData = apply_filters_deprecated( 'fluentform_integration_data_' . $this->integrationKey, [ $addData, $feed, $entry ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/integration_data_' . $this->integrationKey, 'Use fluentform/integration_data_' . $this->integrationKey . ' instead of fluentform_integration_data_' . $this->integrationKey ); $addData = apply_filters('fluentform/integration_data_' . $this->integrationKey, $addData, $feed, $entry); // Now let's prepare the data and push $api = $this->getApiClient(); $response = $api->addContact($addData); if($response->httpStatus === 400) { $error = !empty($response->context[0]->errorDescription) ? $response->context[0]->errorDescription : __('API Error when submitting Data', 'fluentformpro'); do_action('fluentform/integration_action_result', $feed, 'failed', $error); } else { do_action('fluentform/integration_action_result', $feed, 'success', __('GetResponse feed has been successfully initialed and pushed data', 'fluentformpro')); } } protected function getApiClient() { $settings = get_option($this->optionKey); return new GetResponseApi((string)$settings['apiKey']); } } PK!*0)A$$/src/Integrations/GetResponse/GetResponseApi.phpnu[, Robert Staddon * @copyright Copyright (c) 2010 Assembly Studios * @link http://www.assemblystudios.co.uk * @package GetResponsePHP * @version 0.1.1 */ /** * GetResponse Class * @package GetResponsePHP */ class GetResponseApi { private $api_key; private $api_url = 'https://api.getresponse.com/v3'; private $timeout = 8; public $http_status; /** * X-Domain header value if empty header will be not provided * @var string|null */ private $enterprise_domain = null; /** * X-APP-ID header value if empty header will be not provided * @var string|null */ private $app_id = null; /** * Set api key and optionally API endpoint * @param $api_key * @param null $api_url */ public function __construct($api_key, $api_url = null) { $this->api_key = $api_key; if (!empty($api_url)) { $this->api_url = $api_url; } } /** * We can modify internal settings * @param $key * @param $value */ function __set($key, $value) { $this->{$key} = $value; } /** * get account details * * @return mixed */ public function accounts() { return $this->call('accounts'); } /** * @return mixed */ public function ping() { return $this->accounts(); } /** * Return all campaigns * @return mixed */ public function getCampaigns() { return $this->call('campaigns'); } /** * get single campaign * @param string $campaign_id retrieved using API * @return mixed */ public function getCampaign($campaign_id) { return $this->call('campaigns/' . $campaign_id); } /** * adding campaign * @param $params * @return mixed */ public function createCampaign($params) { return $this->call('campaigns', 'POST', $params); } /** * list all RSS newsletters * @return mixed */ public function getRSSNewsletters() { $this->call('rss-newsletters', 'GET', null); } /** * send one newsletter * * @param $params * @return mixed */ public function sendNewsletter($params) { return $this->call('newsletters', 'POST', $params); } /** * @param $params * @return mixed */ public function sendDraftNewsletter($params) { return $this->call('newsletters/send-draft', 'POST', $params); } /** * add single contact into your campaign * * @param $params * @return mixed */ public function addContact($params) { return $this->call('contacts', 'POST', $params); } /** * retrieving contact by id * * @param string $contact_id - contact id obtained by API * @return mixed */ public function getContact($contact_id) { return $this->call('contacts/' . $contact_id); } /** * search contacts * * @param $params * @return mixed */ public function searchContacts($params = null) { return $this->call('search-contacts?' . $this->setParams($params)); } /** * retrieve segment * * @param $id * @return mixed */ public function getContactsSearch($id) { return $this->call('search-contacts/' . $id); } /** * add contacts search * * @param $params * @return mixed */ public function addContactsSearch($params) { return $this->call('search-contacts/', 'POST', $params); } /** * add contacts search * * @param $id * @return mixed */ public function deleteContactsSearch($id) { return $this->call('search-contacts/' . $id, 'DELETE'); } /** * get contact activities * @param $contact_id * @return mixed */ public function getContactActivities($contact_id) { return $this->call('contacts/' . $contact_id . '/activities'); } /** * retrieving contact by params * @param array $params * * @return mixed */ public function getContacts($params = array()) { return $this->call('contacts?' . $this->setParams($params)); } /** * updating any fields of your subscriber (without email of course) * @param $contact_id * @param array $params * * @return mixed */ public function updateContact($contact_id, $params = array()) { return $this->call('contacts/' . $contact_id, 'POST', $params); } /** * drop single user by ID * * @param string $contact_id - obtained by API * @return mixed */ public function deleteContact($contact_id) { return $this->call('contacts/' . $contact_id, 'DELETE'); } /** * retrieve account custom fields * @param array $params * * @return mixed */ public function getCustomFields($params = array()) { return $this->call('custom-fields?' . $this->setParams($params)); } /** * add custom field * * @param $params * @return mixed */ public function setCustomField($params) { return $this->call('custom-fields', 'POST', $params); } /** * retrieve single custom field * * @param string $cs_id obtained by API * @return mixed */ public function getCustomField($custom_id) { return $this->call('custom-fields/' . $custom_id, 'GET'); } /** * retrieving billing information * * @return mixed */ public function getBillingInfo() { return $this->call('accounts/billing'); } /** * get single web form * * @param int $w_id * @return mixed */ public function getWebForm($w_id) { return $this->call('webforms/' . $w_id); } /** * retrieve all webforms * @param array $params * * @return mixed */ public function getWebForms($params = array()) { return $this->call('webforms?' . $this->setParams($params)); } /** * get single form * * @param int $form_id * @return mixed */ public function getForm($form_id) { return $this->call('forms/' . $form_id); } /** * retrieve all forms * @param array $params * * @return mixed */ public function getForms($params = array()) { return $this->call('forms?' . $this->setParams($params)); } /** * Curl run request * * @param null $api_method * @param string $http_method * @param array $params * @return mixed * @throws Exception */ private function call($api_method = null, $http_method = 'GET', $params = array()) { if (empty($api_method)) { return (object)array( 'httpStatus' => '400', 'code' => '1010', 'codeDescription' => 'Error in external resources', 'message' => 'Invalid api method' ); } $params = json_encode($params); $url = $this->api_url . '/' . $api_method; $options = array( CURLOPT_URL => $url, CURLOPT_ENCODING => 'gzip,deflate', CURLOPT_FRESH_CONNECT => 1, CURLOPT_RETURNTRANSFER => 1, CURLOPT_TIMEOUT => $this->timeout, CURLOPT_HEADER => false, CURLOPT_USERAGENT => 'PHP GetResponse client 0.0.2', CURLOPT_HTTPHEADER => array('X-Auth-Token: api-key ' . $this->api_key, 'Content-Type: application/json') ); if (!empty($this->enterprise_domain)) { $options[CURLOPT_HTTPHEADER][] = 'X-Domain: ' . $this->enterprise_domain; } if (!empty($this->app_id)) { $options[CURLOPT_HTTPHEADER][] = 'X-APP-ID: ' . $this->app_id; } if ($http_method == 'POST') { $options[CURLOPT_POST] = 1; $options[CURLOPT_POSTFIELDS] = $params; } else if ($http_method == 'DELETE') { $options[CURLOPT_CUSTOMREQUEST] = 'DELETE'; } $curl = curl_init(); curl_setopt_array($curl, $options); $response = json_decode(curl_exec($curl)); $this->http_status = curl_getinfo($curl, CURLINFO_HTTP_CODE); curl_close($curl); return (object)$response; } /** * @param array $params * * @return string */ private function setParams($params = array()) { $result = array(); if (is_array($params)) { foreach ($params as $key => $value) { $result[$key] = $value; } } return http_build_query($result); } } PK!Z͔*src/Integrations/GoogleSheet/API/Sheet.phpnu[api = new API(); } public function getHeader($sheetId, $workSheetName) { $url = $this->baseUrl.$sheetId.'/values/'.$workSheetName.'!A1:Z1'; $headers = [ 'Authorization' => 'OAuth '.$this->api->getAccessToken() ]; return $this->api->makeRequest($url, [], 'GET', $headers); } public function insertHeader($sheetId, $workSheetName, $row, $range = 'auto') { $range = $workSheetName.'!A1:'.$this->getRangeKey(count($row)).'1'; $this->clear($sheetId, $range); $rowValues = array_values($row); $queryString = http_build_query([ 'valueInputOption' => 'RAW', 'includeValuesInResponse' => 'true', 'responseValueRenderOption' => 'UNFORMATTED_VALUE', 'responseDateTimeRenderOption' => 'FORMATTED_STRING', ]); $url = $this->baseUrl.$sheetId.'/values/'.htmlspecialchars($range).'?'.$queryString; return $this->api->makeRequest($url, [ 'values' => [$rowValues], 'majorDimension' => 'ROWS', 'range' => $range ], 'PUT', $this->getStandardHeader()); } public function insertRow($sheetId, $workSheetName, $row) { $range = $workSheetName.'!A1:'.$this->getRangeKey(count($row)).'1'; $queryString = http_build_query([ 'valueInputOption' => 'USER_ENTERED', 'includeValuesInResponse' => 'true', 'insertDataOption' => 'INSERT_ROWS', 'responseValueRenderOption' => 'UNFORMATTED_VALUE', 'responseDateTimeRenderOption' => 'SERIAL_NUMBER', ]); $url = $this->baseUrl.$sheetId.'/values/'.htmlspecialchars($range).':append?'.$queryString; $rowValues = array_values($row); $rowValues = array_map(function ($value) { if(is_numeric($value)) { $calcValue = ($value * 100) / 100; if(!is_infinite($calcValue)) { return $calcValue; } else { return $value; } } return $value; }, $rowValues); return $this->api->makeRequest($url, [ 'values' => [$rowValues] ], 'POST', $this->getStandardHeader()); } private function clear($sheetId, $range) { $url = $this->baseUrl.$sheetId.'/values/'.$range.':clear'; return $this->api->makeRequest($url, [], 'POST', $this->getStandardHeader()); } protected function getRangeKey($num) { $rounds = 1; $remaining = 0; $range = range('A', 'Z'); if ($num > 26) { $rounds = $num / 26; $remaining = $num % 26; $rounds = (round($rounds) + ($remaining ? 1 : 0) - 1); } foreach (range(0, $rounds) as $round) { foreach (range('A', 'Z') as $key => $char) { $range[] = $range[$round] . $char; } } $index = $num - 1; if (isset($range[$index])) { return $range[$index]; } return 'CZ'; } private function getStandardHeader() { return [ 'Accept' => 'application/json', 'Content-Type' => 'application/json', 'Authorization' => 'Bearer '.$this->api->getAccessToken() ]; } } PK!###(src/Integrations/GoogleSheet/API/API.phpnu[clientId = FF_GSHEET_CLIENT_ID; } if (defined('FF_GSHEET_CLIENT_SECRET')) { $this->clientSecret = FF_GSHEET_CLIENT_SECRET; } } public function makeRequest($url, $bodyArgs, $type = 'GET', $headers = false) { if (!$headers) { $headers = array( 'Content-Type' => 'application/http', 'Content-Transfer-Encoding' => 'binary', 'MIME-Version' => '1.0', ); } $args = [ 'headers' => $headers ]; if ($bodyArgs) { $args['body'] = json_encode($bodyArgs); } $args['method'] = $type; $request = wp_remote_request($url, $args); if (is_wp_error($request)) { $message = $request->get_error_message(); return new \WP_Error(423, $message); } $body = json_decode(wp_remote_retrieve_body($request), true); if (!empty($body['error'])) { $error = 'Unknown Error'; if (isset($body['error_description'])) { $error = $body['error_description']; } elseif (!empty($body['error']['message'])) { $error = $body['error']['message']; } return new \WP_Error(423, $error); } return $body; } public function generateAccessKey($token) { $body = [ 'code' => $token, 'grant_type' => 'authorization_code', 'redirect_uri' => $this->redirect, 'client_id' => $this->clientId, 'client_secret' => $this->clientSecret ]; return $this->makeRequest('https://accounts.google.com/o/oauth2/token', $body, 'POST'); } public function getAccessToken() { $tokens = get_option($this->optionKey); if (!$tokens) { return false; } if (($tokens['created_at'] + $tokens['expires_in'] - 30) < time()) { // It's expired so we have to re-issue again $refreshTokens = $this->refreshToken($tokens); if (!is_wp_error($refreshTokens)) { $tokens['access_token'] = $refreshTokens['access_token']; $tokens['expires_in'] = $refreshTokens['expires_in']; $tokens['created_at'] = time(); update_option($this->optionKey, $tokens, 'no'); } else { return false; } } return $tokens['access_token']; } public function getAUthUrl() { return 'https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=force&client_id=' . $this->clientId . '&redirect_uri=' . urlencode($this->redirect) . '&response_type=code&scope=https%3A%2F%2Fspreadsheets.google.com%2Ffeeds%2F'; } private function refreshToken($tokens) { $clientId = $this->clientId; $clientSecret = $this->clientSecret; // To support previous Google Authentication Process we must use the Previous App if (!isset($tokens['version'])) { $clientId = '157785030834-inhccvqk9nib57i6i326q3aaecgpnctl.apps.googleusercontent.com'; $clientSecret = 'Rnw-FlDRRXkp0QlFSV6h1HHs'; } $args = [ 'client_id' => $clientId, 'client_secret' => $clientSecret, 'refresh_token' => $tokens['refresh_token'], 'grant_type' => 'refresh_token' ]; return $this->makeRequest('https://accounts.google.com/o/oauth2/token', $args, 'POST'); } } PK!+#5#5*src/Integrations/GoogleSheet/Bootstrap.phpnu[logo = fluentFormMix('img/integrations/google-sheets.png'); $this->description = 'Add Fluent Forms Submission to Google sheets when a form is submitted.'; $this->registerAdminHooks(); // add_filter('fluentform/notifying_async_google_sheet', '__return_false'); add_filter('fluentform/save_integration_value_google_sheet', array($this, 'checkColumnSlugs'), 10, 2); } public function getGlobalFields($fields) { $api = new API(); return [ 'logo' => $this->logo, 'menu_title' => __('Google Sheets', 'fluentformpro'), 'menu_description' => __('Copy that Google Access Code from other window and paste it here, then click on Verify Code button.', 'fluentformpro'), 'valid_message' => __('Your Google Access Code is valid', 'fluentformpro'), 'invalid_message' => __('Your Google Access Code is not valid', 'fluentformpro'), 'save_button_text' => __('Verify Code', 'fluentformpro'), 'fields' => [ 'access_code' => [ 'type' => 'text', 'placeholder' => __('Access Code', 'fluentformpro'), 'label_tips' => __("Enter Google Access Code. Please find this by clicking 'Get Google Sheet Access Code' Button", 'fluentformpro'), 'label' => __('Access Code', 'fluentformpro'), ], 'button_link' => [ 'type' => 'link', 'link_text' => __('Get Google Sheet Access Code', 'fluentformpro'), 'link' => $api->getAUthUrl(), 'target' => '_blank', 'tips' => __('Please click on this link get get Access Code From Google', 'fluentformpro'), ] ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your Google Sheet integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect Google Sheet', 'fluentformpro'), 'data' => [ 'access_code' => '' ], 'show_verify' => false ] ]; } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'access_code' => '' ]; return wp_parse_args($globalSettings, $defaults); } public function saveGlobalSettings($settings) { if (empty($settings['access_code'])) { $integrationSettings = [ 'access_code' => '', 'status' => false ]; // Update the reCaptcha details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your settings has been updated', 'fluentformpro'), 'status' => false ], 200); } // Verify API key now try { $accessCode = sanitize_textarea_field($settings['access_code']); $api = new API(); $result = $api->generateAccessKey($accessCode); if (is_wp_error($result)) { throw new \Exception($result->get_error_message()); } $result['access_code'] = $accessCode; $result['created_at'] = time(); $result['status'] = true; $result['version'] = 'latest'; update_option($this->optionKey, $result, 'no'); } catch (\Exception $exception) { wp_send_json_error([ 'message' => $exception->getMessage() ], 400); } wp_send_json_success([ 'message' => __('Your Google Sheet api key has been verified and successfully set', 'fluentformpro'), 'status' => true ], 200); } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => 'Google Sheet', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-google_sheet-settings'), 'configure_message' => __('Google Sheet is not configured yet! Please configure your Google Sheet api first', 'fluentformpro'), 'configure_button_text' => __('Set Google Sheet API', 'fluentformpro') ]; return $integrations; } public function getIntegrationDefaults($settings, $formId) { return [ 'name' => '', 'spreadsheet_id' => '', 'work_sheet_id' => '', 'meta_fields' => [ (object)array() ], 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { return [ 'fields' => [ [ 'key' => 'name', 'label' => __('Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'spreadsheet_id', 'label' => __('Spreadsheet ID', 'fluentformpro'), 'required' => true, 'placeholder' => __('Spreadsheet ID', 'fluentformpro'), 'component' => 'text', 'inline_tip' => __('Check documentation for how to find google Spreadsheet ID', 'fluentformpro') ], [ 'key' => 'work_sheet_id', 'label' => __('Worksheet Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Worksheet Name', 'fluentformpro'), 'component' => 'text', 'inline_tip' => __('Check documentation for how to find google Worksheet Name', 'fluentformpro') ], [ 'key' => 'meta_fields', 'label' => __('Spreadsheet Fields', 'fluentformpro'), 'sub_title' => __('Please specify the meta ', 'fluentformpro'), 'required' => true, 'component' => 'dropdown_label_repeater', ], [ 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Push data to google sheet conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => false, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable This feed', 'fluentformpro') ] ], 'button_require_list' => false, 'integration_title' => $this->title ]; } public function checkColumnSlugs($settings, $integrationId) { $message = 'Validation Failed'; // Validate First $errors = []; if (empty($settings['spreadsheet_id'])) { $errors['spreadsheet_id'] = [__('Please Provide spreadsheet ID', 'fluentformpro')]; } if (empty($settings['work_sheet_id'])) { $errors['work_sheet_id'] = [__('Please Provide Worksheet Name', 'fluentformpro')]; } if (empty($settings['meta_fields'])) { $errors['meta_fields'] = [__('Please Provide Meta Fields Values', 'fluentformpro')]; } if (count($settings['meta_fields']) > 208) { $errors['meta_fields'] = [__('Spreadsheet Fields can not bet greater than 104', 'fluentformpro')]; $message = __('Spreadsheet Fields can not bet greater than 104', 'fluentformpro'); } if ($errors) { wp_send_json_error([ 'message' => $message, 'errors' => $errors ], 423); } $keys = []; foreach ($settings['meta_fields'] as $index => $meta) { if (empty($meta['slug'])) { $slug = sanitize_title($meta['label'], 'column_' . $index, 'display'); if (isset($keys[$slug])) { $slug = $slug . '_' . time() . '_' . mt_rand(1, 100); } $settings['meta_fields'][$index]['slug'] = $slug; $keys[$slug] = $meta['label']; } else { $keys[$meta['slug']] = $meta['label']; } } // Let's get the sheet Header Now $sheet = new Sheet(); $sheetId = $settings['spreadsheet_id']; $workId = $settings['work_sheet_id']; $response = $sheet->insertHeader($sheetId, $workId, $keys); if (is_wp_error($response)) { wp_send_json_error([ 'message' => $response->get_error_message(), 'errors' => $response ], 423); } // we are done here return $settings; } public function getMergeFields($list, $listId, $formId) { return []; } /* * Form Submission Hooks Here */ public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; $row = []; $metaFields = $feedData['meta_fields']; $metaFieldsFeedSettings = ArrayHelper::get($feed, 'settings.meta_fields'); if (!$metaFields) { do_action('fluentform/integration_action_result', $feed, 'failed', __('No meta fields found', 'fluentformpro')); } $inputs = FormFieldsParser::getEntryInputs($form, ['raw']); foreach ($metaFields as $index => $field) { if ($metaFieldsFeedSettings && $fieldFeedSetting = ArrayHelper::get($metaFieldsFeedSettings, $index)){ $name = Helper::getInputNameFromShortCode(ArrayHelper::get($fieldFeedSetting, 'item_value')); if ($name && $element = ArrayHelper::get($inputs, $name)) { if ( 'tabular_grid' == $element['element'] && $value = Helper::getTabularGridFormatValue($formData[$name], $element, "\n", ", ") ) { $row[] = $value; continue; } elseif ("repeater_field" == $element['element']) { $value = wp_unslash(sanitize_textarea_field(ArrayHelper::get($field, 'item_value'))); $row[] = str_replace(' ', '', $value); continue; } } } $row[] = wp_unslash(sanitize_textarea_field(ArrayHelper::get($field, 'item_value'))); } $row = apply_filters_deprecated( 'fluentform_integration_data_' . $this->integrationKey, [ $row, $feed, $entry ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/integration_data_' . $this->integrationKey, 'Use fluentform/integration_data_' . $this->integrationKey . ' instead of fluentform_integration_data_' . $this->integrationKey ); $row = apply_filters('fluentform/integration_data_' . $this->integrationKey, $row, $feed, $entry); $sheet = new Sheet(); $response = $sheet->insertRow($feedData['spreadsheet_id'], $feedData['work_sheet_id'], $row); if (is_wp_error($response)) { do_action('fluentform/integration_action_result', $feed, 'failed', $response->get_error_message()); } else { do_action('fluentform/integration_action_result', $feed, 'success', __('Pushed data to Google Sheet', 'fluentformpro')); } } } PK!/|EE&src/Integrations/Hubspot/Bootstrap.phpnu[logo = fluentFormMix('img/integrations/hubspot.png'); // add_filter('fluentform/notifying_async_hubspot', '__return_false'); $this->description = 'Connect HubSpot with Fluent Forms and subscribe a contact when a form is submitted.'; $this->registerAdminHooks(); } public function getGlobalFields($fields) { return [ 'logo' => $this->logo, 'menu_title' => __('Hubspot API Settings', 'fluentformpro'), 'menu_description' => __('Hubspot is a CRM software. Use Fluent Forms to collect customer information and automatically add to Hubspot. Please login to your Hubspot account and Create a new private app with scope crm.schemas.contacts.read and copy your token, check this link for details. If you have pro version also check contacts-lists-access scope', 'fluentformpro'), 'valid_message' => __('Your Hubspot access token is valid', 'fluentformpro'), 'invalid_message' => __('Your Hubspot access token is not valid', 'fluentformpro'), 'save_button_text' => __('Save Settings', 'fluentformpro'), 'fields' => [ 'accessToken' => [ 'type' => 'password', 'placeholder' => __('Access Token', 'fluentformpro'), 'label_tips' => __("Enter your Hubspot access Token, if you do not have
    Please login to your Hubspot account and
    Create a new private app with scope contacts-lists-access and copy your token", 'fluentformpro'), 'label' => __('Hubspot Access Token', 'fluentformpro'), ] ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your HubSpot API integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect HubSpot', 'fluentformpro'), 'data' => [ 'accessToken' => '' ] ] ]; } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'accessToken' => '', 'apiKey' => '', 'status' => '' ]; return wp_parse_args($globalSettings, $defaults); } public function saveGlobalSettings($settings) { if (!$settings['accessToken']) { $integrationSettings = [ 'accessToken' => '', 'apiKey' => '', 'status' => false ]; update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your settings has been updated and discarded', 'fluentformpro'), 'status' => false ], 200); } // Verify API key now try { $integrationSettings = [ 'accessToken' => sanitize_text_field($settings['accessToken']), 'apiKey' => '', 'status' => false ]; update_option($this->optionKey, $integrationSettings, 'no'); $api = new API($settings['apiKey'],$settings['accessToken']); $result = $api->auth_test(); if (is_wp_error($result)) { throw new \Exception($result->get_error_message()); } if (!empty($result['message'])) { throw new \Exception($result['message']); } } catch (\Exception $exception) { wp_send_json_error([ 'message' => $exception->getMessage() ], 400); } // Integration key is verified now, Proceed now $integrationSettings = [ 'accessToken' => sanitize_text_field($settings['accessToken']), 'apiKey' => '', 'status' => true ]; // Update the reCaptcha details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your HubSport API has been verified and successfully set', 'fluentformpro'), 'status' => true ], 200); } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => $this->title . ' Integration', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-hubspot-settings'), 'configure_message' => __('HubSpot is not configured yet! Please configure your HubSpot api first', 'fluentformpro'), 'configure_button_text' => __('Set HubSpot API', 'fluentformpro') ]; return $integrations; } public function getIntegrationDefaults($settings, $formId) { return [ 'name' => '', 'list_id' => '', 'email' => '', 'firstname' => '', 'lastname' => '', 'website' => '', 'company' => '', 'phone' => '', 'address' => '', 'city' => '', 'state' => '', 'zip' => '', 'fields' => (object)[], 'other_fields_mapping' => [ [ 'item_value' => '', 'label' => '' ] ], 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'contact_update' => false, 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { return [ 'fields' => [ [ 'key' => 'name', 'label' => __('Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'list_id', 'label' => __('HubSpot List(HubSpot Pro)', 'fluentformpro'), 'placeholder' => __('Select HubSpot Mailing List', 'fluentformpro'), 'tips' => __('HubSpot just restricted this for Pro Users. Select the HubSpot Mailing List you would like to add your contacts to.', 'fluentformpro'), 'component' => 'list_ajax_options', 'options' => $this->getLists(), ], [ 'key' => 'fields', 'require_list' => false, 'label' => __('Map Fields', 'fluentformpro'), 'tips' => __('Select which Fluent Forms fields pair with their
    respective HubSpot fields.', 'fluentformpro'), 'component' => 'map_fields', 'field_label_remote' => __('HubSpot Field', 'fluentformpro'), 'field_label_local' => __('Form Field', 'fluentformpro'), 'primary_fileds' => [ [ 'key' => 'email', 'label' => __('Email Address', 'fluentformpro'), 'required' => true, 'input_options' => 'emails' ], [ 'key' => 'firstname', 'label' => __('First Name', 'fluentformpro') ], [ 'key' => 'lastname', 'label' => __('Last Name', 'fluentformpro') ], [ 'key' => 'website', 'label' => __('Website', 'fluentformpro') ], [ 'key' => 'company', 'label' => __('Company', 'fluentformpro') ], [ 'key' => 'phone', 'label' => __('Phone', 'fluentformpro') ], [ 'key' => 'address', 'label' => __('Address', 'fluentformpro') ], [ 'key' => 'city', 'label' => __('City', 'fluentformpro') ], [ 'key' => 'state', 'label' => __('State', 'fluentformpro') ], [ 'key' => 'zip', 'label' => __('Zip', 'fluentformpro') ], ] ], [ 'key' => 'other_fields_mapping', 'require_list' => false, 'label' => __('Other Fields', 'fluentformpro'), 'tips' => __('Select which Fluent Forms fields pair with their
    respective HubSpot fields.', 'fluentformpro'), 'component' => 'dropdown_many_fields', 'field_label_remote' => __('HubSpot Field', 'fluentformpro'), 'field_label_local' => __('Form Field', 'fluentformpro'), 'options' => $this->getOtherFields() ], [ 'require_list' => false, 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow HubSpot integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => false, 'key' => 'contact_update', 'label' => __('Update', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable Contact Update', 'fluentformpro') ], [ 'require_list' => false, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable This feed', 'fluentformpro') ] ], 'button_require_list' => false, 'integration_title' => $this->title ]; } protected function getLists() { $api = $this->getRemoteClient(); $lists = $api->getLists(); $formattedLists = []; foreach ($lists as $list) { $formattedLists[$list['listId']] = $list['name']; } return $formattedLists; } public function getMergeFields($list, $listId, $formId) { return []; } public function getRemoteClient() { $settings = $this->getGlobalSettings([]); return new API($settings['apiKey'],$settings['accessToken']); } public function getOtherFields() { $api = $this->getRemoteClient(); $fields = $api->getAllFields(); $customFormattedFields = []; $customFields = $api->getCustomFields(); foreach ($customFields as $customField) { $customFormattedFields[$customField['name'] . '*_ff_*' . $customField['fieldType']] = $customField['label']; } $formattedFields = []; $unacceptedFields = [ 'email', 'firstname', 'lastname', 'website', 'company', 'phone', 'address', 'city', 'state', 'zip' ]; foreach ($fields as $field) { if (!in_array($field['name'], $unacceptedFields)) { $formattedFields[$field['name'] . '*_ff_*' . $field['fieldType']] = $field['label']; } } $formattedFields = array_merge($formattedFields, $customFormattedFields); return $formattedFields; } private function isDate($value) { if (!$value) { return false; } try { new \DateTime($value); return true; } catch (\Exception $e) { return false; } } /* * Notification Handler */ public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; if (!is_email($feedData['email'])) { $feedData['email'] = ArrayHelper::get($formData, $feedData['email']); } if (!is_email($feedData['email'])) { do_action('fluentform/integration_action_result', $feed, 'failed', __('Hubspot API call has been skipped because no valid email available', 'fluentformpro')); } $mainFields = ArrayHelper::only($feedData, [ 'email', 'firstname', 'lastname', 'website', 'company', 'phone', 'address', 'city', 'state', 'zip' ]); $fields = array_filter(array_merge($mainFields, ArrayHelper::get($feedData, 'fields', []))); if(!empty($feedData['other_fields_mapping'])) { foreach ($feedData['other_fields_mapping'] as $field) { if (!empty($field['item_value'])) { $fieldName = $field['label']; $fieldType = null; $fieldValue = $field['item_value']; if (strpos($field['label'], '*_ff_*') !== false) { $fieldWithSeparator = Str::separateString($field['label'], '*_ff_*'); if (!empty($fieldWithSeparator)) { $fieldName = $fieldWithSeparator[0]; $fieldType = $fieldWithSeparator[1]; } } if ($fieldType) { if ($fieldType == 'checkbox') { if (strpos($fieldValue, ',') !== false) { $separateValues = Str::separateString($fieldValue, ','); $checkboxValue = ''; foreach ($separateValues as $separateString) { $checkboxValue .= ';' . $separateString; } $fieldValue = $checkboxValue; } } } $fields[$fieldName] = $fieldValue; $dateField = $this->isDate($fieldValue); if ($dateField) { $fields[$fieldName] = strtotime($fieldValue)*1000; } } } } $fields = apply_filters_deprecated( 'fluentform_hubspot_field_data', [ $fields, $feed, $entry, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/hubspot_field_data', 'Use fluentform/hubspot_field_data instead of fluentform_hubspot_field_data' ); $fields = apply_filters('fluentform/hubspot_field_data', $fields, $feed, $entry, $form); $fields = apply_filters_deprecated( 'fluentform_integration_data_' . $this->integrationKey, [ $fields, $feed, $entry ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/integration_data_' . $this->integrationKey, 'Use fluentform/integration_data_' . $this->integrationKey . ' instead of fluentform_integration_data_' . $this->integrationKey ); $fields = apply_filters('fluentform/integration_data_' . $this->integrationKey, $fields, $feed, $entry); // Now let's prepare the data and push to hubspot $api = $this->getRemoteClient(); $updateContact = ArrayHelper::get ($feedData,'contact_update'); $response = $api->subscribe($feedData['list_id'], $fields , $updateContact); if (is_wp_error($response)) { do_action('fluentform/integration_action_result', $feed, 'failed', $response->get_error_message()); } else { do_action('fluentform/integration_action_result', $feed, 'success', __('Hubspot feed has been successfully initialed and pushed data', 'fluentformpro')); } } } PK!g  src/Integrations/Hubspot/API.phpnu[apiKey = $apiKey; $this->accessToken = $accessToken; } public function default_options() { return array( 'hapikey' => $this->apiKey ); } public function make_request($action, $options = array(), $method = 'GET') { /* Build request options string. */ $request_options = $this->default_options(); $request_options = wp_parse_args($options, $request_options); $options_string = http_build_query($request_options); /* Build request URL. */ $request_url = $this->apiUrl . $action . '?' . $options_string; if ($this->accessToken) { $request_url = $this->apiUrl . $action; } /* Execute request based on method. */ switch ($method) { case 'POST': $args = array( 'body' => json_encode($options), 'headers' => [ 'Content-Type' => 'application/json' ] ); if ($this->accessToken) { $args['headers']['Authorization'] = 'Bearer ' . $this->accessToken; } $response = wp_remote_post($request_url, $args); break; case 'GET': $args = []; if ($this->accessToken) { $args['headers'] = [ 'Content-Type' => 'application/json', 'Authorization' => 'Bearer ' . $this->accessToken, ]; } $response = wp_remote_get($request_url, $args); break; } /* If WP_Error, die. Otherwise, return decoded JSON. */ if (is_wp_error($response)) { return new \WP_Error(400, $response->get_error_message()); } return \json_decode($response['body'], true); } /** * Test the provided API credentials. * * @access public * @return bool */ public function auth_test() { return $this->make_request('contacts/v1/lists/all/contacts/all', [], 'GET'); } public function subscribe($listId, $values, $updateContact = false) { $values = array_filter($values); $properties = []; foreach ($values as $property => $value) { $properties[$property] = [ 'property' => $property, 'value' => $value ]; } $properties = [ 'properties' => array_values($properties) ]; if ($updateContact) { $response = $this->make_request('contacts/v1/contact/createOrUpdate/email/' . $values['email'], $properties, 'POST'); } else { $response = $this->make_request('contacts/v1/contact/', $properties, 'POST'); } if (is_wp_error($response)) { return $response; } if (!empty($response['error'])) { return new \WP_Error('api_error', $response['error']); } if ('error' == ArrayHelper::get($response, 'status')) { return new \WP_Error('error', ArrayHelper::get($response, 'message', 'Values were not valid')); } if (!empty($response['error']) && $response['error'] == 'CONTACT_EXISTS') { $contactId = $response['identityProfile']['vid']; } else { $contactId = $response['vid']; } $data = [ 'vids' => [$contactId] ]; // We have the contact ID now. Let's add the list to that contact $updateResponse = $this->make_request('contacts/v1/lists/' . $listId . '/add', $data, 'POST'); if (is_wp_error($updateResponse)) { return $updateResponse; } if (!empty($updateResponse['error'])) { return new \WP_Error('api_error', $updateResponse['error']); } elseif (!$updateResponse) { return new \WP_Error('api_error', 'HubSpot API Request Failed'); } return $contactId; } /** * Get all Forms in the system. * * @access public * @return array */ public function getLists() { $response = $this->make_request('contacts/v1/lists/static', array(), 'GET'); if (is_wp_error($response)) { return []; } if (!empty($response['lists'])) { return $response['lists']; } return []; } /** * Get all Tags in the system. * * @access public * @return array */ public function getTags() { $response = $this->make_request('tags', array(), 'GET'); if (is_wp_error($response)) { return false; } if (empty($response['error'])) { return $response['tags']; } return false; } public function getAllFields() { $lists = $this->make_request('contacts/v1/properties', array(), 'GET'); if (is_wp_error($lists)) { return []; } $fields = array_filter($lists, function ($item) { return ArrayHelper::get($item, 'formField') && ArrayHelper::get($item, 'hubspotDefined'); }); return $fields; } public function getCustomFields() { $lists = $this->make_request('contacts/v1/properties', array(), 'GET'); if (is_wp_error($lists)) { return []; } $customFields = array_filter($lists, function ($item) { return empty($item['hubspotDefined']); }); return $customFields; } } PK!c)L)L'src/Integrations/IContact/Bootstrap.phpnu[logo = fluentFormMix('img/integrations/icontact.png'); $this->description = 'Connect iContact with Fluent Forms and subscribe a contact when a form is submitted.'; $this->registerAdminHooks(); // add_filter('fluentform/notifying_async_icontact', '__return_false'); } public function getGlobalFields($fields) { return [ 'logo' => $this->logo, 'menu_title' => __('iContact API Settings', 'fluentformpro'), 'menu_description' => __('iContact is an email marketing platform to send email newsletters to your customers, manage your
    subscriber lists, and track campaign performance. Use Fluent Forms to collect customer information
    and automatically add it to your iContact list. If you don\'t have an iContact account,
    you can sign up for one here.', 'fluentformpro'), 'valid_message' => __('Your iContact configuration is valid', 'fluentformpro'), 'invalid_message' => __('Your iContact configuration is invalid', 'fluentformpro'), 'save_button_text' => __('Save Settings', 'fluentformpro'), 'config_instruction' => __("

    Fluent Forms iContact Add-On requires your Application ID, API username and API password. To obtain an application ID, follow the steps described below:

    1. Visit iContact's application registration page
    2. Set an application name and description for your application.
    3. Choose to show information for API 2.0.
    4. Copy the provided API-AppId into the Application ID setting field below.
    5. Click \"Enable this AppId for your account\".
    6. Create a password for your application and click save.
    7. Enter your API password, along with your iContact account username, into the fields below.
    ", 'fluentformpro'), 'fields' => [ 'appKey' => [ 'type' => 'password', 'placeholder' => __('Application Key', 'fluentformpro'), 'label_tips' => __("Enter your iContact Application Key", 'fluentformpro'), 'label' => __('Application Key', 'fluentformpro'), ], 'username' => [ 'type' => 'text', 'placeholder' => __('Account Email Address', 'fluentformpro'), 'label_tips' => __("Enter your iContact Account Email Address", 'fluentformpro'), 'label' => __('Account Email Address', 'fluentformpro'), ], 'apiPassword' => [ 'type' => 'password', 'placeholder' => __('API Password', 'fluentformpro'), 'label_tips' => __("Enter your iContact API Password", 'fluentformpro'), 'label' => __('API Password', 'fluentformpro'), ], 'AccountID' => [ 'type' => 'text', 'placeholder' => __('Account ID', 'fluentformpro'), 'label_tips' => __("Enter your Account ID. It's a numeric value. You will get in the api settings", 'fluentformpro'), 'label' => __('Account ID', 'fluentformpro'), ], 'clientFolderId' => [ 'type' => 'text', 'placeholder' => __('Client Folder ID', 'fluentformpro'), 'label_tips' => __("Enter your Client Folder ID", 'fluentformpro'), 'label' => __('Client Folder ID', 'fluentformpro'), ] ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your iContact API integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect iContact', 'fluentformpro'), 'data' => [ 'appKey' => '' ], 'show_verify' => true ] ]; } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'appKey' => '', 'username' => '', 'apiPassword' => '', 'clientFolderId ' => '', 'AccountID' => '', 'status' => '' ]; return wp_parse_args($globalSettings, $defaults); } public function saveGlobalSettings($settings) { if (!$settings['appKey']) { $integrationSettings = [ 'appKey' => '', 'username' => '', 'apiPassword' => '', 'status' => false ]; // Update the reCaptcha details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your API settings has been updated and discarded', 'fluentformpro'), 'status' => false ], 200); } try { $emptyAppKey = empty($settings['appKey']); $emptyUsername = empty($settings['username']); $emptyApiPassword = empty($settings['apiPassword']); if ($emptyAppKey || $emptyUsername || $emptyApiPassword) { throw new \Exception(__('Invalid request, missing required fields.', 'fluentformpro'), 400); } $settings['status'] = false; $settings['appKey'] = sanitize_text_field($settings['appKey']); $settings['username'] = sanitize_text_field($settings['username']); $settings['apiPassword'] = sanitize_text_field($settings['apiPassword']); update_option($this->optionKey, $settings, 'no'); $this->getFolders($settings); $settings['status'] = true; update_option($this->optionKey, $settings, 'no'); wp_send_json_success([ 'status' => true, 'message' => __('Your API key settings has been verified and updated. All good!', 'fluentformpro') ], 200); } catch (\Exception $e) { wp_send_json_error([ 'status' => false, 'message' => $e->getMessage() ], 423); } } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => $this->title . ' Integration', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-icontact-settings'), 'configure_message' => __('iContact API Key is not configured yet! Please configure your iContact api first', 'fluentformpro'), 'configure_button_text' => __('Set iContact API', 'fluentformpro') ]; return $integrations; } public function getIntegrationDefaults($settings, $formId) { return [ 'name' => '', 'list_id' => '', 'fieldName' => '', 'fieldEmailAddress' => '', 'default_fields' => (object)[], 'custom_field_mappings' => (object)[], 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { return [ 'fields' => [ [ 'key' => 'name', 'label' => __('Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'list_id', 'label' => __('iContact List', 'fluentformpro'), 'placeholder' => __('Select iContact List', 'fluentformpro'), 'tips' => __('Select the iContact List you would like to add your contacts to.', 'fluentformpro'), 'component' => 'list_ajax_options', 'options' => $this->getLists(), ], [ 'key' => 'custom_field_mappings', 'require_list' => true, 'label' => __('Map Fields', 'fluentformpro'), 'tips' => __('Select which Fluent Forms fields pair with their
    respective iContact fields.', 'fluentformpro'), 'component' => 'map_fields', 'field_label_remote' => __('iContact Field', 'fluentformpro'), 'field_label_local' => __('Form Field', 'fluentformpro'), 'primary_fileds' => [ [ 'key' => 'fieldEmailAddress', 'label' => __('Email Address', 'fluentformpro'), 'required' => true, 'input_options' => 'emails' ] ], 'default_fields' => array( array( 'name' => 'prefix', 'label' => esc_html__('Prefix', 'fluentformpro') ), array( 'name' => 'firstName', 'label' => esc_html__('First Name', 'fluentformpro') ), array( 'name' => 'lastName', 'label' => esc_html__('Last Name', 'fluentformpro') ), array( 'name' => 'suffix', 'label' => esc_html__('Suffix', 'fluentformpro') ), array( 'name' => 'street', 'label' => esc_html__('Address: Line 1', 'fluentformpro') ), array( 'name' => 'street2', 'label' => esc_html__('Address: Line 2', 'fluentformpro') ), array( 'name' => 'city', 'label' => esc_html__('Address: City', 'fluentformpro') ), array( 'name' => 'state', 'label' => esc_html__('Address: State', 'fluentformpro') ), array( 'name' => 'postalCode', 'label' => esc_html__('Address: Postal Code', 'fluentformpro') ), array( 'name' => 'phone', 'label' => esc_html__('Phone Number', 'fluentformpro') ), array( 'name' => 'fax', 'label' => esc_html__('Fax Number', 'fluentformpro') ), array( 'name' => 'business', 'label' => esc_html__('Business Number', 'fluentformpro') ) ) ], [ 'require_list' => true, 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow iContact integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => true, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable This feed', 'fluentformpro') ] ], 'button_require_list' => true, 'integration_title' => $this->title ]; } protected function getLists() { $api = $this->getApiClient(); $lists = $api->get_lists(); $formattedLists = []; foreach ($lists as $list) { $formattedLists[$list['listId']] = $list['name']; } return $formattedLists; } public function getMergeFields($list, $listId, $formId) { $api = $this->getApiClient(); if (!$api) { return []; } $customFields = $api->get_custom_fields(); $formattedFields = []; foreach ($customFields as $customField) { $formattedFields[$customField['customFieldId']] = $customField['publicName']; } return $formattedFields; } protected function getFolders($settings) { $api = new IContactApi( $settings['appKey'], $settings['username'], $settings['apiPassword'], $settings['clientFolderId'], $settings['AccountID'] ); $folders = []; $clientFolders = $api->get_client_folders(); foreach ($clientFolders as $folder) { $folders[] = [ 'label' => isset($folder['name']) ? $folder['name'] : esc_html__('Default Client Folder', 'fluentformicontact'), 'value' => $folder['clientFolderId'] ]; } return $folders; } /* * Handle Notifications here */ /* * Form Submission Hooks Here */ public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; if (!is_email($feedData['fieldEmailAddress'])) { $feedData['fieldEmailAddress'] = ArrayHelper::get($formData, $feedData['fieldEmailAddress']); } if (!is_email($feedData['fieldEmailAddress'])) { do_action('fluentform/integration_action_result', $feed, 'failed', __('iContact API call has been skipped because no valid email available', 'fluentformpro')); return; } $subscriber = [ 'email' => $feedData['fieldEmailAddress'] ]; $defaultFields = ArrayHelper::get($feedData, 'default_fields', []); foreach ($defaultFields as $fieldKey => $fieldValue) { if (!$fieldValue) { continue; } $subscriber[$fieldKey] = $fieldValue; } $cutomFields = ArrayHelper::get($feedData, 'custom_field_mappings', []); foreach ($cutomFields as $fieldKey => $fieldValue) { if (!$fieldValue) { continue; } $subscriber[$fieldKey] = $fieldValue; } $subscriber = array_filter($subscriber); $subscriber = apply_filters_deprecated( 'fluentform_integration_data_' . $this->integrationKey, [ $subscriber, $feed, $entry ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/integration_data_' . $this->integrationKey, 'Use fluentform/integration_data_' . $this->integrationKey . ' instead of fluentform_integration_data_' . $this->integrationKey ); $subscriber = apply_filters('fluentform/integration_data_' . $this->integrationKey, $subscriber, $feed, $entry); $contactId = false; try { $contactId = $this->syncContact($subscriber); } catch (\Exception $exception) { do_action('fluentform/integration_action_result', $feed, 'failed', $exception->getMessage()); return; } if (is_wp_error($contactId)) { do_action('fluentform/integration_action_result', $feed, 'failed', $contactId->get_error_message()); } if ($contactId) { do_action('fluentform/integration_action_result', $feed, 'success', __('iContact feed has been successfully initialed and pushed the contact', 'fluentformpro')); try { $this->addSubscription($contactId, $feedData['list_id']); } catch (\Exception $exception) { // } return; } } private function syncContact($contact) { $api = $this->getApiClient(); /* Check to see if we're adding a new contact. */ $find_contact = $api->get_contact_by_email($contact['email']); $is_new_contact = empty($find_contact); if ($is_new_contact) { try { $response = $api->add_contact($contact); return $response['contactId']; } catch (\Exception $e) { return new \WP_Error('broke', $e->getMessage()); } } else { try { $contact_id = $find_contact[0]['contactId']; /* Update the contact. */ $api->update_contact($contact_id, $contact); return $contact_id; } catch (\Exception $e) { return new \WP_Error('broke', $e->getMessage()); } } } private function addSubscription($contactId, $listId) { try { $api = $this->getApiClient(); /* Subscribe the contact to the list. */ $subscription = $api->add_contact_to_list($contactId, $listId); /* Log whether or not contact was subscribed to list. */ if (empty ($subscription)) { return new \WP_Error('broke', __('Add subscription failed', 'fluentformpro')); } else { return true; } } catch (\Exception $e) { return new \WP_Error('broke', $e->getMessage()); } } protected function getApiClient($settings = null) { if (!$settings) { $settings = $this->getGlobalSettings([]); } return new IContactApi( $settings['appKey'], $settings['username'], $settings['apiPassword'], isset($settings['clientFolderId']) ? $settings['clientFolderId'] : '', isset($settings['AccountID']) ? $settings['AccountID'] : '' ); } } PK!*L=VV)src/Integrations/IContact/IContactApi.phpnu[app_id = $app_id; $this->api_username = $api_username; $this->api_password = $api_password; $this->client_folder_id = $client_folder_id; $this->account_id = $account_id; } /** * Get base path of API requests. * * @access public * @return void */ public function get_url_base() { return $this->set_account_id() .'/c/'. $this->client_folder_id .'/'; } /** * Get array of headers needed for every API request. * * @access public * @return array */ public function request_headers() { return array( 'Expect' => '', 'Accept' => 'application/json', 'Content-type' => 'application/json', 'Api-Version' => '2.2', 'Api-AppId' => $this->app_id, 'Api-Username' => $this->api_username, 'Api-Password' => $this->api_password ); } /** * Make API request. * * @access public * @param string $action * @param array $options (default: array()) * @param string $method (default: 'GET') * @return \WP_Error | array | \Exception */ public function make_request( $action = null, $options = array(), $method = 'GET', $return_key = null ) { $options = apply_filters_deprecated( 'fluentform_icontact_request_args', [ $options, $action, $method, $return_key ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/icontact_request_args', 'Use fluentform/icontact_request_args instead of fluentform_icontact_request_args.' ); $options = apply_filters( 'fluentform/icontact_request_args', $options, $action, $method, $return_key ); // Build request options string. $request_options = ( $method == 'GET' && ! empty( $options ) ) ? '?' . http_build_query( $options ) : ''; // Build request URL. $request_url = $this->api_url . $action . $request_options; // Prepare request and execute. $args = array( 'headers' => $this->request_headers(), 'method' => $method ); if ( $method == 'POST' ) { $args['body'] = json_encode( $options ); } $response = wp_remote_request( $request_url, $args ); // If WP_Error, die. Otherwise, return decoded JSON. if ( is_wp_error( $response ) ) { return $response; } else { $response = json_decode( $response['body'], true ); if (isset( $response['errors'])) { if (isset($response['errors'][0]) && is_string($response['errors'][0])) { throw new Exception( $response['errors'][0] ); } } if (isset($response['warnings'])) { if (isset($response['warnings'][0]) && is_string($response['warnings'][0])) { throw new Exception( $response['warnings'][0] ); } } return empty( $return_key ) ? $response : $response[$return_key]; } } /** * Fetch the Account ID. * * @access public * @return void */ public function set_account_id() { if ( empty( $this->account_id ) ) { $accounts = $this->make_request('/'); if ( isset( $accounts['errors'] ) ) throw new Exception( $accounts['errors'][0] ); $account = $accounts['accounts'][0]; if ( $account['enabled'] == 1 ) { $this->account_id = $account['accountId']; } else { throw new Exception(__('Your account has been disabled.', 'fluentformpro')); } } return $this->account_id; } /** * Add a new contact. * * @access public * @param array $contact * @return array */ public function add_contact( $contact ) { $contacts = $this->make_request( $this->get_url_base() . 'contacts', array( $contact ), 'POST', 'contacts' ); return $contacts[0]; } /** * Add a contact to a list. * * @access public * @param int $contact_id * @param int $list_id * @param string $status (default: 'normal') * @return void */ public function add_contact_to_list( $contact_id, $list_id, $status = 'normal' ) { $subscription = array( 'contactId' => $contact_id, 'listId' => $list_id, 'status' => $status ); $new_subscription = $this->make_request( $this->get_url_base() . 'subscriptions', array( $subscription ), 'POST', 'subscriptions' ); return $new_subscription; } /** * Add new custom field to account. * * @access public * @param mixed $custom_field * @return void */ public function add_custom_field( $custom_field ) { return $this->make_request( $this->get_url_base() . 'customfields', array( $custom_field ), 'POST', 'customfields' ); } /** * Get available client folders. * * @access public * @return array $folders */ public function get_client_folders() { /* If the account ID isn't set, go set it. */ if ( empty( $this->account_id ) ) { $this->set_account_id(); } $clients = $this->make_request( $this->account_id . '/c/', array( 'limit' => 999 ) ); if ( isset( $clients['errors'] ) ) { throw new Exception(__('No client folders were found for this account.', 'fluentformpro')); } return $clients['clientfolders']; } /** * Fetch all contacts associated with this account. * * @access public * @return void */ public function get_contacts() { return $this->make_request( $this->get_url_base() . 'contacts', array(), 'GET', 'contacts' ); } /** * Fetch contact by email address. * * @access public * @return void */ public function get_contact_by_email( $email ) { return $this->make_request( $this->get_url_base() . 'contacts', array( 'email' => $email ), 'GET', 'contacts' ); } /** * Fetch custom fields for associated with this account. * * @access public * @return void */ public function get_custom_fields() { return $this->make_request( $this->get_url_base() . 'customfields', array(), 'GET', 'customfields' ); } /** * Fetch all lists associated with this account. * * @access public * @return void */ public function get_lists() { return $this->make_request( $this->get_url_base() . 'lists', array( 'limit' => 999 ), 'GET', 'lists' ); } /** * Fetch a specific list associated with this account. * * @access public * @param mixed $list_id * @return void */ public function get_list( $list_id ) { return $this->make_request( $this->get_url_base() . 'lists/' . $list_id, array(), 'GET', 'list' ); } /** * Checks to see if a client folder has been selected. * * @access public * @return bool */ public function is_client_folder_set() { return ! empty( $this->client_folder_id ); } /** * Update an existing contact. * * @access public * @param int $contact_id * @param array $contact * @return void */ public function update_contact( $contact_id, $contact ) { return $this->make_request( $this->get_url_base() . 'contacts/'. $contact_id, $contact, 'POST', 'contact' ); } } PK!/G6}}(src/Integrations/Insightly/Bootstrap.phpnu[logo = fluentFormMix('img/integrations/insightly.png'); $this->description = 'With Insightly CRM, you can tailor the standard sales processes of contact, lead and opportunity management.'; $this->registerAdminHooks(); add_filter( 'fluentform/get_integration_values_' . $this->integrationKey, [$this, 'resolveIntegrationSettings'], 10, 3 ); add_filter( 'fluentform/save_integration_value_' . $this->integrationKey, [$this, 'validate'], 10, 3 ); } public function resolveIntegrationSettings($settings, $feed, $formId) { $serviceName = $this->app->request->get('serviceName', ''); $serviceId = $this->app->request->get('serviceId', ''); if ($serviceName) { $settings['name'] = $serviceName; } if ($serviceId) { $settings['list_id'] = $serviceId; } return $settings; } public function validate($settings, $integrationId, $formId) { $error = false; $errors = []; foreach ($this->getFields($settings['list_id']) as $field) { if ($field['required'] && empty($settings[$field['key']])) { $error = true; $errors[$field['key']] = [__($field['label'] . ' is required', 'fluentformpro')]; } } if ($error) { wp_send_json_error([ 'message' => __('Validation Failed', 'fluentformpro'), 'errors' => $errors ], 423); } return $settings; } public function getRemoteClient() { $settings = $this->getGlobalSettings([]); return new API($settings); } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'url' => '', 'api_key' => '', 'status' => false, ]; return wp_parse_args($globalSettings, $defaults); } public function getGlobalFields($fields) { return [ 'logo' => $this->logo, 'menu_title' => __('Insightly Settings', 'fluentformpro'), 'menu_description' => $this->description, 'valid_message' => __('Your Insightly Integration Key is valid', 'fluentformpro'), 'invalid_message' => __('Your Insightly Integration Key is not valid', 'fluentformpro'), 'save_button_text' => __('Save Settings', 'fluentformpro'), 'config_instruction' => __($this->getConfigInstructions(), 'fluentformpro'), 'fields' => [ 'url' => [ 'type' => 'text', 'placeholder' => __('Insightly API URL', 'fluentformpro'), 'label_tips' => __('Enter your Insightly API URL', 'fluentformpro'), 'label' => __('Insightly API URL', 'fluentformpro'), ], 'api_key' => [ 'type' => 'password', 'placeholder' => __('Insightly API Key', 'fluentformpro'), 'label_tips' => __('Enter your Insightly API Key', 'fluentformpro'), 'label' => __('Insightly API Key', 'fluentformpro'), ] ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your Insightly API integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect Insightly', 'fluentformpro'), 'data' => [ 'url' => '', 'api_key' => '' ], 'show_verify' => true ] ]; } protected function getConfigInstructions() { ob_start(); ?>
    1. Go Here and copy your API URL with https:// and Secret Key after that Paste here.
    '', 'api_key' => '', 'status' => false ]; update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_error([ 'message' => __('Please provide all fields to integrate', 'fluentformpro'), 'status' => false ], 423); } try { $client = new API($settings); $result = $client->checkAuth(); if (is_wp_error($result)) { throw new \Exception($result->get_error_message(), $result->get_error_code()); } } catch (\Exception $exception) { wp_send_json_error([ 'message' => $exception->getMessage(), 'status' => false ], $exception->getCode()); } $integrationSettings = [ 'url' => $settings['url'], 'api_key' => $settings['api_key'], 'status' => true ]; update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your Insightly API key has been verified and successfully set', 'fluentformpro'), 'status' => true ], 200); } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => $this->title . ' Integration', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-insightly-settings'), 'configure_message' => __('Insightly is not configured yet! Please configure your Insightly API first', 'fluentformpro'), 'configure_button_text' => __('Set Insightly API', 'fluentformpro') ]; return $integrations; } public function getIntegrationDefaults($settings, $formId) { $listId = $this->app->request->get('serviceId'); return [ 'name' => '', 'list_id' => $listId, 'fields' => [ [ 'item_value' => '', 'label' => '' ] ], 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { $fieldSettings = [ 'fields' => [ [ 'key' => 'name', 'label' => __('Feed Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'list_id', 'label' => __('Insightly Services', 'fluentformpro'), 'placeholder' => __('Select Insightly Service', 'fluentformpro'), 'required' => true, 'component' => 'refresh', 'options' => $this->getLists() ], ], 'button_require_list' => false, 'integration_title' => $this->title ]; $listId = $this->app->request->get('serviceId', ArrayHelper::get($settings, 'list_id')); if ($listId) { $fields = $this->getFields($listId); if (empty($fields)) { wp_send_json_error([ 'message' => __("The selected service doesn't have any field settings.", 'fluentformpro'), ], 423); } $fields = array_merge($fieldSettings['fields'], $fields); $fieldSettings['fields'] = $fields; } $fieldSettings['fields'] = array_merge($fieldSettings['fields'], [ [ 'require_list' => false, 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow this integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => false, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable this feed', 'fluentformpro') ] ]); return $fieldSettings; } protected function getLists() { return [ 'contacts' => 'Contact', 'opportunities' => 'Opportunity', 'leads' => 'Lead', 'organisations' => 'Organisations', 'projects' => 'Project', 'tasks' => 'Task', ]; } public function getMergeFields($list, $listId, $formId) { return false; } public function getFields($listId) { $mergedFields = []; switch ($listId) { case 'contacts': $mergedFields = [ [ 'key' => 'EMAIL_ADDRESS', 'placeholder' => __('Enter Email', 'fluentformpro'), 'label' => __('Email', 'fluentformpro'), 'required' => false, 'tips' => __('Email is a email type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'SALUTATION', 'placeholder' => __('Enter Salutation', 'fluentformpro'), 'label' => __('Salutation', 'fluentformpro'), 'required' => false, 'tips' => __('Salutation is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'FIRST_NAME', 'placeholder' => __('Enter First Name', 'fluentformpro'), 'label' => __('First Name', 'fluentformpro'), 'required' => true, 'tips' => __('First Name is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'LAST_NAME', 'placeholder' => __('Enter Last Name', 'fluentformpro'), 'label' => __('Last Name', 'fluentformpro'), 'required' => false, 'tips' => __('Last Name is a string type field.', 'fluentformpro'), 'component' => 'value_text' ] ]; $organisations = $this->getOrganisations(); $mergedFields[] = array_merge($mergedFields, $organisations); $mergedFields = array_merge($mergedFields, [ [ 'key' => 'TITLE', 'placeholder' => __('Enter Organisation Title', 'fluentformpro'), 'label' => __('Organisation Title', 'fluentformpro'), 'required' => false, 'tips' => __('Organisation Title is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'SOCIAL_LINKEDIN', 'placeholder' => __('Enter LinkedIn URL', 'fluentformpro'), 'label' => __('LinkedIn URL', 'fluentformpro'), 'required' => false, 'tips' => __('LinkedIn URL is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'SOCIAL_TWITTER', 'placeholder' => __('Enter Twitter URL', 'fluentformpro'), 'label' => __('Twitter URL', 'fluentformpro'), 'required' => false, 'tips' => __('Twitter URL is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'date*DATE_OF_BIRTH', 'placeholder' => __('Enter Date Of Birth', 'fluentformpro'), 'label' => __('Date Of Birth', 'fluentformpro'), 'required' => false, 'tips' => __('Date Of Birth is a date type field on y-m-d.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'PHONE', 'placeholder' => __('Enter Phone', 'fluentformpro'), 'label' => __('Phone', 'fluentformpro'), 'required' => false, 'tips' => __('Phone is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'PHONE_HOME', 'placeholder' => __('Enter Home Phone', 'fluentformpro'), 'label' => __('Home Phone', 'fluentformpro'), 'required' => false, 'tips' => __('Home Phone is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'PHONE_MOBILE', 'placeholder' => __('Enter Mobile Phone', 'fluentformpro'), 'label' => __('Mobile Phone', 'fluentformpro'), 'required' => false, 'tips' => __('Mobile Phone is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'PHONE_OTHER', 'placeholder' => __('Enter Other Phone', 'fluentformpro'), 'label' => __('Other Phone', 'fluentformpro'), 'required' => false, 'tips' => __('Other Phone is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'PHONE_FAX', 'placeholder' => __('Enter FAX Phone', 'fluentformpro'), 'label' => __('FAX Phone', 'fluentformpro'), 'required' => false, 'tips' => __('FAX Phone is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'ASSISTANT_NAME', 'placeholder' => __('Enter Assistant Name', 'fluentformpro'), 'label' => __('Assistant Name', 'fluentformpro'), 'required' => false, 'tips' => __('Assistant Name is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'PHONE_ASSISTANT', 'placeholder' => __('Enter Assistant Phone', 'fluentformpro'), 'label' => __('Assistant Phone', 'fluentformpro'), 'required' => false, 'tips' => __('Assistant Phone is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'ADDRESS_MAIL_STREET', 'placeholder' => __('Enter Street Address', 'fluentformpro'), 'label' => __('Street Address', 'fluentformpro'), 'required' => false, 'tips' => __('Street Address is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'ADDRESS_MAIL_CITY', 'placeholder' => __('Enter City', 'fluentformpro'), 'label' => __('City', 'fluentformpro'), 'required' => false, 'tips' => __('City is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'ADDRESS_MAIL_STATE', 'placeholder' => __('Enter State', 'fluentformpro'), 'label' => __('State', 'fluentformpro'), 'required' => false, 'tips' => __('State is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'ADDRESS_MAIL_POSTCODE', 'placeholder' => __('Enter Post Code', 'fluentformpro'), 'label' => __('Post Code', 'fluentformpro'), 'required' => false, 'tips' => __('Post Code is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'ADDRESS_MAIL_COUNTRY', 'placeholder' => __('Enter Country', 'fluentformpro'), 'label' => __('Country', 'fluentformpro'), 'required' => false, 'tips' => __('Country is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'ADDRESS_OTHER_STREET', 'placeholder' => __('Enter Other Street Address', 'fluentformpro'), 'label' => __('Other Street Address', 'fluentformpro'), 'required' => false, 'tips' => __('Other Street Address is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'ADDRESS_OTHER_CITY', 'placeholder' => __('Enter Other City', 'fluentformpro'), 'label' => __('Other City', 'fluentformpro'), 'required' => false, 'tips' => __('Other City is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'ADDRESS_OTHER_STATE', 'placeholder' => __('Enter Other State', 'fluentformpro'), 'label' => __('Other State', 'fluentformpro'), 'required' => false, 'tips' => __('Other State is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'ADDRESS_OTHER_POSTCODE', 'placeholder' => __('Enter Other Post Code', 'fluentformpro'), 'label' => __('Other Post Code', 'fluentformpro'), 'required' => false, 'tips' => __('Other Post Code is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'ADDRESS_OTHER_COUNTRY', 'placeholder' => __('Enter Other Country', 'fluentformpro'), 'label' => __('Other Country', 'fluentformpro'), 'required' => false, 'tips' => __('Other Country is a string type field.', 'fluentformpro'), 'component' => 'value_text' ] ]); break; case 'opportunities': $mergedFields = [ [ 'key' => 'OPPORTUNITY_NAME', 'placeholder' => __('Opportunity Name', 'fluentformpro'), 'label' => __('Opportunity Name', 'fluentformpro'), 'required' => true, 'tips' => __('Opportunity Name is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'OPPORTUNITY_DETAILS', 'placeholder' => __('Opportunity Details', 'fluentformpro'), 'label' => __('Opportunity Details', 'fluentformpro'), 'required' => false, 'tips' => __('Opportunity Details is a string type field.', 'fluentformpro'), 'component' => 'value_text' ] ]; $organisations = $this->getOrganisations(); $mergedFields[] = array_merge($mergedFields, $organisations); $categories = $this->getProjectCategories(); $mergedFields[] = array_merge($mergedFields, $categories); $mergedFields = array_merge($mergedFields, [ [ 'key' => 'PROBABILITY', 'placeholder' => __('Enter Probability Of Winning', 'fluentformpro'), 'label' => __('Probability Of Winning', 'fluentformpro'), 'required' => false, 'tips' => __('Probability Of Winning is a integer type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'date*FORECAST_CLOSE_DATE', 'placeholder' => __('Enter Forecast Close Date', 'fluentformpro'), 'label' => __('Forecast Close Date', 'fluentformpro'), 'required' => false, 'tips' => __('Forecast Close Date is a date type field on y-m-d.', 'fluentformpro'), 'component' => 'value_text', ], [ 'key' => 'date*ACTUAL_CLOSE_DATE', 'placeholder' => __('Enter Actual Close Date', 'fluentformpro'), 'label' => __('Actual Close Date', 'fluentformpro'), 'required' => false, 'tips' => __('Actual Close Date is a date type field on y-m-d.', 'fluentformpro'), 'component' => 'value_text' ] ]); $users = $this->getUsers('RESPONSIBLE_USER_ID'); $mergedFields[] = array_merge($mergedFields, $users); $mergedFields = array_merge($mergedFields, [ [ 'key' => 'BID_AMOUNT', 'placeholder' => __('Enter Bid Amount', 'fluentformpro'), 'label' => __('Bid Amount', 'fluentformpro'), 'required' => false, 'tips' => __('Bid Amount is a number type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'BID_TYPE', 'placeholder' => __('Enter Bid Type', 'fluentformpro'), 'label' => __('Bid Type', 'fluentformpro'), 'required' => false, 'tips' => __('Bid Amount is a number type field.', 'fluentformpro'), 'component' => 'select', 'options' => [ 'Fixed Bid' => __('Fixed Bid', 'fluentformpro'), 'Per Hour' => __('Per Hour', 'fluentformpro'), 'Per Day' => __('Per Day', 'fluentformpro'), 'Per week' => __('Per Week', 'fluentformpro'), 'Per Month' => __('Per Month', 'fluentformpro'), 'Per Year' => __('Per Year', 'fluentformpro') ] ], ]); $pipelines = $this->getPipelines(); $mergedFields[] = array_merge($mergedFields, $pipelines); $pipelineStages = $this->getPipelineStages(); $mergedFields[] = array_merge($mergedFields, $pipelineStages); break; case 'leads': $mergedFields = [ [ 'key' => 'SALUTATION', 'placeholder' => __('Enter Salutation', 'fluentformpro'), 'label' => __('Salutation', 'fluentformpro'), 'required' => false, 'tips' => __('Salutation is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'FIRST_NAME', 'placeholder' => __('Enter First Name', 'fluentformpro'), 'label' => __('First Name', 'fluentformpro'), 'required' => true, 'tips' => __('First Name is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'LAST_NAME', 'placeholder' => __('Enter Last Name', 'fluentformpro'), 'label' => __('Last Name', 'fluentformpro'), 'required' => false, 'tips' => __('Last Name is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], ]; $leadStatuses = $this->getLeadStatuses(); $leadSources = $this->getLeadSources(); $users = $this->getUsers('RESPONSIBLE_USER_ID'); $mergedFields[] = array_merge($mergedFields, $leadStatuses); $mergedFields[] = array_merge($mergedFields, $leadSources); $mergedFields[] = array_merge($mergedFields, $users); $mergedFields = array_merge($mergedFields, [ [ 'key' => 'TITLE', 'placeholder' => __('Enter Title', 'fluentformpro'), 'label' => __('Title', 'fluentformpro'), 'required' => false, 'tips' => __('Title is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'ORGANISATION_NAME', 'placeholder' => __('Enter Organisation Name', 'fluentformpro'), 'label' => __('Organisation Name', 'fluentformpro'), 'required' => false, 'tips' => __('Organisation Name is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'EMAIL', 'placeholder' => __('Enter Email', 'fluentformpro'), 'label' => __('Email', 'fluentformpro'), 'required' => false, 'tips' => __('Email is a email type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'FAX', 'placeholder' => __('Enter Fax', 'fluentformpro'), 'label' => __('Fax', 'fluentformpro'), 'required' => false, 'tips' => __('Fax is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'INDUSTRY', 'placeholder' => __('Enter Industry', 'fluentformpro'), 'label' => __('Industry', 'fluentformpro'), 'required' => false, 'tips' => __('Industry is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'LEAD_DESCRIPTION', 'placeholder' => __('Enter Lead Description', 'fluentformpro'), 'label' => __('Lead Description', 'fluentformpro'), 'required' => false, 'tips' => __('Lead Description is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'LEAD_RATING', 'placeholder' => __('Enter Lead Rating', 'fluentformpro'), 'label' => __('Lead Rating', 'fluentformpro'), 'required' => false, 'tips' => __('Lead Rating is a number type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'MOBILE', 'placeholder' => __('Enter Mobile', 'fluentformpro'), 'label' => __('Mobile', 'fluentformpro'), 'required' => false, 'tips' => __('Mobile is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'PHONE', 'placeholder' => __('Enter Phone', 'fluentformpro'), 'label' => __('Phone', 'fluentformpro'), 'required' => false, 'tips' => __('Phone is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'WEBSITE', 'placeholder' => __('Enter Website', 'fluentformpro'), 'label' => __('Website', 'fluentformpro'), 'required' => false, 'tips' => __('Website is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'EMPLOYEE_COUNT', 'placeholder' => __('Enter Number Of Employees', 'fluentformpro'), 'label' => __('Number Of Employees', 'fluentformpro'), 'required' => false, 'tips' => __('Number Of Employees is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'ADDRESS_STREET', 'placeholder' => __('Enter Street Address', 'fluentformpro'), 'label' => __('Street Address', 'fluentformpro'), 'required' => false, 'tips' => __('Street Address is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'ADDRESS_CITY', 'placeholder' => __('Enter City', 'fluentformpro'), 'label' => __('City', 'fluentformpro'), 'required' => false, 'tips' => __('City is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'ADDRESS_STATE', 'placeholder' => __('Enter State', 'fluentformpro'), 'label' => __('State', 'fluentformpro'), 'required' => false, 'tips' => __('State is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'ADDRESS_POSTCODE', 'placeholder' => __('Enter Post Code', 'fluentformpro'), 'label' => __('Post Code', 'fluentformpro'), 'required' => false, 'tips' => __('Post Code is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'ADDRESS_COUNTRY', 'placeholder' => __('Enter Country', 'fluentformpro'), 'label' => __('Country', 'fluentformpro'), 'required' => false, 'tips' => __('Country is a string type field.', 'fluentformpro'), 'component' => 'value_text' ] ]); break; case 'organisations': $mergedFields = [ [ 'key' => 'ORGANISATION_NAME', 'placeholder' => __('Enter Organisation Name', 'fluentformpro'), 'label' => __('Organisation Name', 'fluentformpro'), 'required' => true, 'tips' => __('Organisation Name is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'BACKGROUND', 'placeholder' => __('Enter Background', 'fluentformpro'), 'label' => __('Background', 'fluentformpro'), 'required' => false, 'tips' => __('Background is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'PHONE', 'placeholder' => __('Enter Phone', 'fluentformpro'), 'label' => __('Phone', 'fluentformpro'), 'required' => false, 'tips' => __('Phone is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'PHONE_FAX', 'placeholder' => __('Enter FAX', 'fluentformpro'), 'label' => __('FAX', 'fluentformpro'), 'required' => false, 'tips' => __('FAX is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'WEBSITE', 'placeholder' => __('Enter Website', 'fluentformpro'), 'label' => __('Website', 'fluentformpro'), 'required' => false, 'tips' => __('Website is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'ADDRESS_BILLING_STREET', 'placeholder' => __('Enter Billing Address Street', 'fluentformpro'), 'label' => __('Billing Address Street', 'fluentformpro'), 'required' => false, 'tips' => __('Billing Address Street is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'ADDRESS_BILLING_CITY', 'placeholder' => __('Enter Billing Address City', 'fluentformpro'), 'label' => __('Billing Address City', 'fluentformpro'), 'required' => false, 'tips' => __('Billing Address City is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'ADDRESS_BILLING_STATE', 'placeholder' => __('Enter Billing Address State', 'fluentformpro'), 'label' => __('Billing Address State', 'fluentformpro'), 'required' => false, 'tips' => __('Billing Address State is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'ADDRESS_BILLING_COUNTRY', 'placeholder' => __('Enter Billing Address Country', 'fluentformpro'), 'label' => __('Billing Address Country', 'fluentformpro'), 'required' => false, 'tips' => __('Billing Address Country is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'ADDRESS_BILLING_POSTCODE', 'placeholder' => __('Enter Billing Address Postcode', 'fluentformpro'), 'label' => __('Billing Address Postcode', 'fluentformpro'), 'required' => false, 'tips' => __('Billing Address Postcode is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'ADDRESS_SHIP_STREET', 'placeholder' => __('Enter Shipping Address Street', 'fluentformpro'), 'label' => __('Shipping Address Street', 'fluentformpro'), 'required' => false, 'tips' => __('Shipping Address Street is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'ADDRESS_SHIP_CITY', 'placeholder' => __('Enter Shipping Address City', 'fluentformpro'), 'label' => __('Shipping Address City', 'fluentformpro'), 'required' => false, 'tips' => __('Shipping Address City is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'ADDRESS_SHIP_STATE', 'placeholder' => __('Enter Shipping Address State', 'fluentformpro'), 'label' => __('Shipping Address State', 'fluentformpro'), 'required' => false, 'tips' => __('Shipping Address State is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'ADDRESS_SHIP_POSTCODE', 'placeholder' => __('Enter Shipping Address Postcode', 'fluentformpro'), 'label' => __('Shipping Address Postcode', 'fluentformpro'), 'required' => false, 'tips' => __('Shipping Address Postcode is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'ADDRESS_SHIP_COUNTRY', 'placeholder' => __('Enter Shipping Address Country', 'fluentformpro'), 'label' => __('Shipping Address Country', 'fluentformpro'), 'required' => false, 'tips' => __('Shipping Address Country is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'SOCIAL_LINKEDIN', 'placeholder' => __('Enter LinkedIn', 'fluentformpro'), 'label' => __('LinkedIn', 'fluentformpro'), 'required' => false, 'tips' => __('LinkedIn is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'SOCIAL_FACEBOOK', 'placeholder' => __('Enter Facebook', 'fluentformpro'), 'label' => __('Facebook', 'fluentformpro'), 'required' => false, 'tips' => __('Facebook is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'SOCIAL_TWITTER', 'placeholder' => __('Enter Twitter', 'fluentformpro'), 'label' => __('Twitter', 'fluentformpro'), 'required' => false, 'tips' => __('Twitter is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], ]; break; case 'projects': $mergedFields = [ [ 'key' => 'PROJECT_NAME', 'placeholder' => __('Enter Project Name', 'fluentformpro'), 'label' => __('Project Name', 'fluentformpro'), 'required' => true, 'tips' => __('Project Name is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'PROJECT_DETAILS', 'placeholder' => __('Enter Project Details', 'fluentformpro'), 'label' => __('Project Details', 'fluentformpro'), 'required' => false, 'tips' => __('Project Details is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'STATUS', 'placeholder' => __('Select Project Status', 'fluentformpro'), 'label' => __('Project Status', 'fluentformpro'), 'required' => true, 'tips' => __('Project Status is a string type field.', 'fluentformpro'), 'component' => 'select', 'options' => [ 'IN PROGRESS' => 'In Progress', 'DEFERRED' => 'Deferred', 'CANCELLED' => 'Cancelled', 'ABANDONED' => 'Abandoned', 'COMPLETED' => 'Completed' ] ] ]; $opportunities = $this->getOpportunities(); $projectCategories = $this->getProjectCategories(); $pipelines = $this->getPipelines(); $pipelineStages = $this->getPipelineStages(); $users = $this->getUsers('RESPONSIBLE_USER_ID'); $mergedFields[] = array_merge($mergedFields, $opportunities); $mergedFields[] = array_merge($mergedFields, $projectCategories); $mergedFields[] = array_merge($mergedFields, $pipelines); $mergedFields[] = array_merge($mergedFields, $pipelineStages); $mergedFields[] = array_merge($mergedFields, $users); break; case 'tasks': $mergedFields = [ [ 'key' => 'TITLE', 'placeholder' => __('Enter Task Name', 'fluentformpro'), 'label' => __('Task Name', 'fluentformpro'), 'required' => true, 'tips' => __('Task Name is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], ]; $taskCategories = $this->getTaskCategories(); $mergedFields[] = array_merge($mergedFields, $taskCategories); $responsibleUser = $this->getUsers('RESPONSIBLE_USER_ID'); $mergedFields[] = array_merge($mergedFields, $responsibleUser); $mergedFields = array_merge($mergedFields, [ [ 'key' => 'date*DUE_DATE', 'placeholder' => __('Due Date', 'fluentformpro'), 'label' => __('Due date', 'fluentformpro'), 'required' => false, 'tips' => __('Due date is a date type field on y-m-d.', 'fluentformpro'), 'component' => 'value_text', ], [ 'key' => 'date*START_DATE', 'placeholder' => __('Start Date', 'fluentformpro'), 'label' => __('Start date', 'fluentformpro'), 'required' => false, 'tips' => __('Start date is a date type field on y-m-d.', 'fluentformpro'), 'component' => 'value_text', ], [ 'key' => 'date*REMINDER_DATE_UTC', 'placeholder' => __('Remainder Due Date', 'fluentformpro'), 'label' => __('Remainder Due date', 'fluentformpro'), 'required' => false, 'tips' => __('Remainder Due date is a date type field on y-m-d.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'PERCENT_COMPLETE', 'placeholder' => __('Progress in Percentage', 'fluentformpro'), 'label' => __('Progress', 'fluentformpro'), 'required' => false, 'tips' => __('Progress is a number type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'PRIORITY', 'placeholder' => __('Priority', 'fluentformpro'), 'label' => __('Priority', 'fluentformpro'), 'required' => false, 'tips' => __('Priority is a select type field.', 'fluentformpro'), 'component' => 'select', 'options' => [ '0' => __('Low', 'fluentformpro'), '1' => __('Medium', 'fluentformpro'), '2' => __('High', 'fluentformpro') ] ], [ 'key' => 'STATUS', 'placeholder' => __('Status', 'fluentformpro'), 'label' => __('Status', 'fluentformpro'), 'required' => false, 'tips' => __('Status is a select type field.', 'fluentformpro'), 'component' => 'select', 'options' => [ 'IN PROGRESS' => __('In Progress', 'fluentformpro'), 'COMPLETED' => __('Completed', 'fluentformpro'), 'DEFERRED' => __('Deferred', 'fluentformpro'), 'WAITING' => __('Waiting', 'fluentformpro') ] ], [ 'key' => 'DETAILS', 'placeholder' => __('Description', 'fluentformpro'), 'label' => __('Description', 'fluentformpro'), 'required' => false, 'tips' => __('Description is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], ]); $opportunities = $this->getOpportunities(); $projects = $this->getProjects(); $mergedFields[] = array_merge($mergedFields, $opportunities); $mergedFields[] = array_merge($mergedFields, $projects); $mergedFields = array_merge($mergedFields, [ ]); break; default: $mergedFields = []; } $customFields = $this->getCustomFields($listId); return array_merge($mergedFields, $customFields); } protected function getCustomFields($listId) { $client = $this->getRemoteClient(); $customFields = $client->makeRequest($client->url . '/v3.1/customfields/' . $listId, null); if (is_wp_error($customFields)) { wp_send_json_error([ 'message' => __($customFields->get_error_message(), 'fluentformpro'), ], 423); } $customFormattedFields = []; foreach ($customFields as $fieldValue) { $customFormattedFields[] = [ 'key' => 'custom*' . $fieldValue['FIELD_NAME'], 'placeholder' => __('Enter ' . $fieldValue['FIELD_LABEL'], 'fluentformpro'), 'label' => __($fieldValue['FIELD_LABEL'], 'fluentformpro'), 'required' => false, 'tips' => __($fieldValue['FIELD_LABEL'] . ' is a ' . $fieldValue['FIELD_TYPE'] . ' type field.', 'fluentformpro'), 'component' => 'value_text' ]; } return $customFormattedFields; } protected function getLeadStatuses() { $client = $this->getRemoteClient(); $leadStatuses = $client->makeRequest($client->url . '/v3.1/leadstatuses', null); if (is_wp_error($leadStatuses)) { wp_send_json_error([ 'message' => __($leadStatuses->get_error_message(), 'fluentformpro'), ], 423); } $data = [ 'key' => 'LEAD_STATUS_ID', 'placeholder' => __('Select Lead Status', 'fluentformpro'), 'label' => __('Lead Status', 'fluentformpro'), 'required' => true, 'tips' => __('Lead Status is a required select type field.', 'fluentformpro'), 'component' => 'select' ]; $options = []; foreach ($leadStatuses as $option) { $options[$option['LEAD_STATUS_ID']] = $option['LEAD_STATUS']; } $data['options'] = $options; return $data; } protected function getLeadSources() { $client = $this->getRemoteClient(); $leadSources = $client->makeRequest($client->url . '/v3.1/leadsources', null); if (is_wp_error($leadSources)) { wp_send_json_error([ 'message' => __($leadSources->get_error_message(), 'fluentformpro'), ], 423); } $data = [ 'key' => 'LEAD_SOURCE_ID', 'placeholder' => __('Select Lead Source', 'fluentformpro'), 'label' => __('Lead Source', 'fluentformpro'), 'required' => true, 'tips' => __('Lead Source is a required select type field.', 'fluentformpro'), 'component' => 'select' ]; $options = []; foreach ($leadSources as $option) { $options[$option['LEAD_SOURCE_ID']] = $option['LEAD_SOURCE']; } $data['options'] = $options; return $data; } protected function getOpportunities() { $client = $this->getRemoteClient(); $opportunities = $client->makeRequest($client->url . '/v3.1/opportunities', null); if (is_wp_error($opportunities)) { wp_send_json_error([ 'message' => __($opportunities->get_error_message(), 'fluentformpro'), ], 423); } $data = [ 'key' => 'OPPORTUNITY_ID', 'placeholder' => __('Select Opportunity Category', 'fluentformpro'), 'label' => __('Opportunity Category', 'fluentformpro'), 'required' => false, 'tips' => __('Opportunity Category is a select type field.', 'fluentformpro'), 'component' => 'select' ]; $options = []; foreach ($opportunities as $option) { $options[$option['OPPORTUNITY_ID']] = $option['OPPORTUNITY_NAME']; } $data['options'] = $options; return $data; } protected function getProjects() { $client = $this->getRemoteClient(); $projects = $client->makeRequest($client->url . '/v3.1/projects', null); if (is_wp_error($projects)) { wp_send_json_error([ 'message' => __($projects->get_error_message(), 'fluentformpro'), ], 423); } $data = [ 'key' => 'PROJECT_ID', 'placeholder' => __('Select Project', 'fluentformpro'), 'label' => __('Project', 'fluentformpro'), 'required' => false, 'tips' => __('Project is a select type field.', 'fluentformpro'), 'component' => 'select' ]; $options = []; foreach ($projects as $option) { $options[$option['PROJECT_ID']] = $option['PROJECT_NAME']; } $data['options'] = $options; return $data; } protected function getOpportunityCategories() { $client = $this->getRemoteClient(); $opportunityCategories = $client->makeRequest($client->url . '/v3.1/opportunitycategories', null); if (is_wp_error($opportunityCategories)) { wp_send_json_error([ 'message' => __($opportunityCategories->get_error_message(), 'fluentformpro'), ], 423); } $data = [ 'key' => 'CATEGORY_ID', 'placeholder' => __('Select Category', 'fluentformpro'), 'label' => __('Category', 'fluentformpro'), 'required' => false, 'tips' => __('Category is a select type field.', 'fluentformpro'), 'component' => 'select' ]; $options = []; foreach ($opportunityCategories as $option) { $options[$option['CATEGORY_ID']] = $option['CATEGORY_NAME']; } $data['options'] = $options; return $data; } protected function getUsers($key) { $client = $this->getRemoteClient(); $users = $client->makeRequest($client->url . '/v3.1/users', null); if (is_wp_error($users)) { wp_send_json_error([ 'message' => __($users->get_error_message(), 'fluentformpro'), ], 423); } if ($key == 'RESPONSIBLE_USER_ID') { $data = [ 'key' => $key, 'placeholder' => __('Select Responsible User', 'fluentformpro'), 'label' => __('Responsible User', 'fluentformpro'), 'required' => false, 'tips' => __('Responsible User is a select type field.', 'fluentformpro'), 'component' => 'select' ]; } else { $data = [ 'key' => $key, 'placeholder' => __('Select Owner User', 'fluentformpro'), 'label' => __('Owner User', 'fluentformpro'), 'required' => false, 'tips' => __('Owner User is a select type field.', 'fluentformpro'), 'component' => 'select' ]; } $options = []; foreach ($users as $option) { $options[$option['USER_ID']] = $option['FIRST_NAME'] . ' ' . $option['LAST_NAME']; } $data['options'] = $options; return $data; } protected function getPipelines() { $client = $this->getRemoteClient(); $pipelines = $client->makeRequest($client->url . '/v3.1/pipelines', null); if (is_wp_error($pipelines)) { wp_send_json_error([ 'message' => __($pipelines->get_error_message(), 'fluentformpro'), ], 423); } $data = [ 'key' => 'PIPELINE_ID', 'placeholder' => __('Select Pipeline', 'fluentformpro'), 'label' => __('Pipeline', 'fluentformpro'), 'required' => false, 'tips' => __('Pipeline is a select type field.', 'fluentformpro'), 'component' => 'select' ]; $options = []; foreach ($pipelines as $option) { $options[$option['PIPELINE_ID']] = $option['PIPELINE_NAME']; } $data['options'] = $options; return $data; } protected function getPipelineStages() { $client = $this->getRemoteClient(); $pipelineStages = $client->makeRequest($client->url . '/v3.1/pipelinestages', null); if (is_wp_error($pipelineStages)) { wp_send_json_error([ 'message' => __($pipelineStages->get_error_message(), 'fluentformpro'), ], 423); } $data = [ 'key' => 'STAGE_ID', 'placeholder' => __('Select Pipeline Stage', 'fluentformpro'), 'label' => __('Pipeline Stage', 'fluentformpro'), 'required' => false, 'tips' => __('Pipeline Stage is a select type field.', 'fluentformpro'), 'component' => 'select' ]; $options = []; foreach ($pipelineStages as $option) { $options[$option['STAGE_ID']] = $option['STAGE_NAME']; } $data['options'] = $options; return $data; } protected function getProjectCategories() { $client = $this->getRemoteClient(); $projectCategories = $client->makeRequest($client->url . '/v3.1/projectcategories', null); if (is_wp_error($projectCategories)) { wp_send_json_error([ 'message' => __($projectCategories->get_error_message(), 'fluentformpro'), ], 423); } $data = [ 'key' => 'CATEGORY_ID', 'placeholder' => __('Select Project Category', 'fluentformpro'), 'label' => __('Project Category', 'fluentformpro'), 'required' => false, 'tips' => __('Project Category is a select type field.', 'fluentformpro'), 'component' => 'select' ]; $options = []; foreach ($projectCategories as $option) { $options[$option['CATEGORY_ID']] = $option['CATEGORY_NAME']; } $data['options'] = $options; return $data; } protected function getOrganisations() { $client = $this->getRemoteClient(); $organisations = $client->makeRequest($client->url . '/v3.1/organisations', null); if (is_wp_error($organisations)) { wp_send_json_error([ 'message' => __($organisations->get_error_message(), 'fluentformpro'), ], 423); } $data = [ 'key' => 'ORGANISATION_ID', 'placeholder' => __('Select Organisation', 'fluentformpro'), 'label' => __('Organisation', 'fluentformpro'), 'required' => false, 'tips' => __('Organisation is a select type field.', 'fluentformpro'), 'component' => 'select' ]; $options = []; foreach ($organisations as $option) { $options[$option['ORGANISATION_ID']] = $option['ORGANISATION_NAME']; } $data['options'] = $options; return $data; } protected function getTaskCategories() { $client = $this->getRemoteClient(); $taskCategories = $client->makeRequest($client->url . '/v3.1/taskcategories', null); if (is_wp_error($taskCategories)) { wp_send_json_error([ 'message' => __($taskCategories->get_error_message(), 'fluentformpro'), ], 423); } $data = [ 'key' => 'CATEGORY_ID', 'placeholder' => __('Select Task Category', 'fluentformpro'), 'label' => __('Task Category', 'fluentformpro'), 'required' => false, 'tips' => __('Task Category is a select type field.', 'fluentformpro'), 'component' => 'select' ]; $options = []; foreach ($taskCategories as $option) { $options[$option['CATEGORY_ID']] = $option['CATEGORY_NAME']; } $data['options'] = $options; return $data; } protected function getAllFields($listId) { $fields = $this->getFields($listId); $allFields = []; foreach ($fields as $field) { $keyData = []; $keyData['key'] = $field['key']; if ($field['required']) { $keyData['required'] = $field['required']; $allFields[] = $keyData; } else { $keyData['required'] = 0; $allFields[] = $keyData; } } return $allFields; } public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; $subscriber['attributes'] = []; $subscriber['list_id'] = $feedData['list_id']; $allFields = $this->getAllFields($feedData['list_id']); foreach ($allFields as $field) { $key = $field['key']; if (!empty($feedData[$key])) { if(strpos($key, '*') != false) { $fieldArray = explode('*', $key, 2); $fieldType = $fieldArray[0]; $fieldName = $fieldArray[1]; if($fieldType == 'date') { $timeStamp = strtotime($feedData[$key]); $date = date('Y-m-d H:i:s', $timeStamp); $subscriber['attributes'][$fieldName] = $date; } if($fieldType == 'custom') { $subscriber['attributes']['CUSTOMFIELDS'][] = [ 'FIELD_NAME' => $fieldName, 'FIELD_VALUE' => $feedData[$key] ]; } } else { $subscriber['attributes'][$key] = ArrayHelper::get($feedData, $key); } } } $client = $this->getRemoteClient(); $response = $client->subscribe($subscriber); if (!is_wp_error($response)) { do_action('fluentform/integration_action_result', $feed, 'success', __('Insightly feed has been successfully initiated and pushed', 'fluentformpro') . $feedData['list_id'] . ' data'); } else { $message = $response->get_error_message(); if (!$message) { $errorCode = $response->get_error_code(); if ($errorCode == 400) { $message = __("Data validation failed", 'fluentformpro'); } elseif ($errorCode == 401) { $message = __("Authentication failed", 'fluentformpro'); } elseif ($errorCode == 402) { $message = __("Record limit reached", 'fluentformpro'); } } do_action('fluentform/integration_action_result', $feed, 'failed', $message); } } } PK!Z  "src/Integrations/Insightly/API.phpnu[url = trim($settings['url']); $this->apiKey = 'Basic ' . base64_encode($settings['api_key'] . ':' . ' '); } public function checkAuth() { return $this->makeRequest($this->url . '/v3.1/instance'); } public function makeRequest($url, $bodyArgs = [], $type = 'GET') { $request = []; if ($type == 'GET') { $request = wp_remote_get($url, [ 'headers' => [ 'Content-Type' => 'application/json', 'Accept' => 'application/json', 'Authorization' => $this->apiKey, ] ]); } if ($type == 'POST') { $request = wp_remote_post($url, [ 'headers' => [ 'Content-Type' => 'application/json', 'Accept' => 'application/json', 'Authorization' => $this->apiKey, ], 'body' => $bodyArgs ]); } if (is_wp_error($request)) { $code = $request->get_error_code(); $message = $request->get_error_message(); return new \WP_Error($code, $message); } $body = wp_remote_retrieve_body($request); $body = \json_decode($body, true); $code = wp_remote_retrieve_response_code($request); if ($code == 200 || $code == 201) { return $body; } else { $message = ArrayHelper::get($body, 'Message'); if(empty($message)){ $message = ArrayHelper::get($body, '0.Message','Something went wrong please check again!'); } return new \WP_Error($code, $message); } } public function subscribe($subscriber) { $url = $this->url . '/v3.1/' . $subscriber['list_id']; $post = \json_encode($subscriber['attributes'], true); $response = $this->makeRequest($url, $post, 'POST'); return $response; } } PK!r--)src/Integrations/MailerLite/Bootstrap.phpnu[logo = fluentFormMix('img/integrations/mailerlite.png'); $this->description = 'Mailer Lite is an email marketing software for designers and their clients. Use Fluent Forms to add subscribers to MailerLite.'; $this->registerAdminHooks(); // add_filter('fluentform/notifying_async_mailerlite', '__return_false'); } public function getGlobalFields($fields) { return [ 'logo' => $this->logo, 'menu_title' => __('MailerLite Settings', 'fluentformpro'), 'menu_description' => $this->description, 'valid_message' => __('Your MailerLite API Key is valid', 'fluentformpro'), 'invalid_message' => __('Your MailerLite API Key is not valid', 'fluentformpro'), 'save_button_text' => __('Save Settings', 'fluentformpro'), 'fields' => [ 'apiKey' => [ 'type' => 'text', 'placeholder' => 'API Key', 'label_tips' => __("Enter your MailerLite API Key, if you do not have
    Please log in to your MailerLite account and go to
    Profile -> Account Settings -> Account Info", 'fluentformpro'), 'label' => __('MailerLite API Key', 'fluentformpro'), ] ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your MailerLite API integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect MailerLite', 'fluentformpro'), 'data' => [ 'apiKey' => '' ], 'show_verify' => true ] ]; } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'apiKey' => '', 'status' => '' ]; return wp_parse_args($globalSettings, $defaults); } public function saveGlobalSettings($settings) { if (!$settings['apiKey']) { $integrationSettings = [ 'apiKey' => '', 'status' => false ]; // Update the reCaptcha details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your settings has been updated', 'fluentformpro'), 'status' => false ], 200); } // Verify API key now try { $integrationSettings = [ 'apiKey' => sanitize_text_field($settings['apiKey']), 'status' => false ]; update_option($this->optionKey, $integrationSettings, 'no'); $api = new API($settings['apiKey']); $result = $api->auth_test(); if (!empty($result['error'])) { throw new \Exception($result['message']); } } catch (\Exception $exception) { wp_send_json_error([ 'message' => $exception->getMessage() ], 400); } // Integration key is verified now, Proceed now $integrationSettings = [ 'apiKey' => sanitize_text_field($settings['apiKey']), 'status' => true ]; // Update the reCaptcha details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your MailerLite api key has been verified and successfully set', 'fluentformpro'), 'status' => true ], 200); } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => $this->title . ' Integration', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-mailerlite-settings'), 'configure_message' => __('MailerLite is not configured yet! Please configure your MailerLite api first', 'fluentformpro'), 'configure_button_text' => __('Set MailerLite API', 'fluentformpro') ]; return $integrations; } public function getIntegrationDefaults($settings, $formId) { return [ 'name' => '', 'list_id' => '', 'fields' => (object)[], 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'resubscribe' => false, 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { return [ 'fields' => [ [ 'key' => 'name', 'label' => __('Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'list_id', 'label' => __('Group List', 'fluentformpro'), 'placeholder' => __('Select MailerLite List', 'fluentformpro'), 'tips' => __('Select the MailerLite Group you would like to add your contacts to.', 'fluentformpro'), 'component' => 'list_ajax_options', 'options' => $this->getLists(), ], [ 'key' => 'fields', 'require_list' => true, 'label' => __('Map Fields', 'fluentformpro'), 'tips' => __('Select which Fluent Forms fields pair with their
    respective MailerLite fields.', 'fluentformpro'), 'component' => 'map_fields', 'field_label_remote' => __('MailerLite Field', 'fluentformpro'), 'field_label_local' => __('Form Field', 'fluentformpro'), 'primary_fileds' => [] ], [ 'require_list' => true, 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow MailerLite integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => true, 'key' => 'resubscribe', 'label' => __('Resubscribe', 'fluentformpro'), 'checkbox_label' => __('Reactivate subscriber if value is checked', 'fluentformpro'), 'component' => 'checkbox-single' ], [ 'require_list' => true, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable This feed', 'fluentformpro') ] ], 'button_require_list' => true, 'integration_title' => $this->title ]; } protected function getLists() { $api = $this->getRemoteClient(); $lists = $api->getGroups(); $formateddLists = []; foreach ($lists as $list) { $formateddLists[$list['id']] = $list['name']; } return $formateddLists; } public function getMergeFields($list = false, $listId = false, $formId = false) { $api = $this->getRemoteClient(); if (!$api) { return []; } $fields = $api->getCustomFields(); $formattedFields = []; if ($fields) { foreach ($fields as $field) { $formattedFields[$field['key']] = $field['title']; } } return $formattedFields; } /* * Form Submission Hooks Here */ public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; $dataFields = $feedData['fields']; $fields = $this->getMergeFields(); $subscriber = [ 'email' => '', 'confirmation_ip' => $entry->ip, 'confirmation_timestamp' => date('Y-m-d H:i:s'), 'fields' => [], 'resubscribe' => !empty($feedData['resubscribe']) ? true : false ]; foreach ($fields as $fieldKey => $fieldName) { if (empty($dataFields[$fieldKey])) { continue; } if ($fieldKey == 'name' || $fieldKey == 'email') { $subscriber[$fieldKey] = $dataFields[$fieldKey]; } else { $subscriber['fields'][$fieldKey] = $dataFields[$fieldKey]; } } if (empty($subscriber['email']) || !is_email($subscriber['email'])) { do_action('fluentform/integration_action_result', $feed, 'failed', __('MailerLte API call has been skipped because no valid email available', 'fluentformpro')); return; } $subscriber = apply_filters_deprecated( 'fluentform_integration_data_' . $this->integrationKey, [ $subscriber, $feed, $entry ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/integration_data_' . $this->integrationKey, 'Use fluentform/integration_data_' . $this->integrationKey . ' instead of fluentform_integration_data_' . $this->integrationKey ); $subscriber = apply_filters('fluentform/integration_data_' . $this->integrationKey, $subscriber, $feed, $entry); $api = $this->getRemoteClient(); $response = $api->subscribe($feedData['list_id'], $subscriber); if (is_wp_error($response)) { do_action('fluentform/integration_action_result', $feed, 'failed', $response->get_error_message()); return; } do_action('fluentform/integration_action_result', $feed, 'success', __('MailerLite feed has been successfully initialed and pushed data', 'fluentformpro')); } public function getRemoteClient() { $settings = $this->getGlobalSettings([]); return new API($settings['apiKey']); } } PK!Mc  #src/Integrations/MailerLite/API.phpnu[apiKey = $apiKey; } public function default_options() { return [ 'User-Agent' => 'MailerLite PHP SDK/2.0', 'X-MailerLite-ApiKey' => $this->apiKey, 'Content-Type' => 'application/json' ]; } public function make_request($action, $options = array(), $method = 'GET') { $headers = $this->default_options(); $endpointUrl = $this->apiUrl . $action; $args = [ 'headers' => $headers ]; if ($options) { $args['body'] = \json_encode($options); } /* Execute request based on method. */ switch ($method) { case 'POST': $response = wp_remote_post($endpointUrl, $args); break; case 'GET': $response = wp_remote_get($endpointUrl, $args); break; } /* If WP_Error, die. Otherwise, return decoded JSON. */ if (is_wp_error($response)) { return [ 'error' => 'API_Error', 'message' => $response->get_error_message() ]; } else if ($response && $response['response']['code'] >= 300) { return [ 'error' => 'API_Error', 'message' => $response['response']['message'] ]; } return json_decode($response['body'], true); } /** * Test the provided API credentials. * * @access public * @return bool */ public function auth_test() { return $this->make_request('groups', [], 'GET'); } public function subscribe($formId, $data) { $response = $this->make_request('groups/' . $formId . '/subscribers', $data, 'POST'); if (!empty($response['error'])) { return new \WP_Error('api_error', $response['message']); } return $response; } /** * Get all Forms in the system. * * @access public * @return array */ public function getGroups() { $response = $this->make_request('groups', array(), 'GET'); if (empty($response['error'])) { return $response; } return []; } public function getCustomFields() { $response = $this->make_request('fields', array(), 'GET'); if (empty($response['error'])) { return $response; } return false; } } PK!Qbaa&src/Integrations/Mailjet/Bootstrap.phpnu[logo = fluentFormMix('img/integrations/mailjet.png'); $this->description = 'Mailjet is an easy-to-use all-in-one e-mail platform.'; $this->registerAdminHooks(); add_filter( 'fluentform/get_integration_values_' . $this->integrationKey, [$this, 'resolveIntegrationSettings'], 10, 3 ); add_filter( 'fluentform/save_integration_value_' . $this->integrationKey, [$this, 'validate'], 10, 3 ); } public function resolveIntegrationSettings($settings, $feed, $formId) { $serviceName = $this->app->request->get('serviceName', ''); $serviceId = $this->app->request->get('serviceId', ''); if ($serviceName) { $settings['name'] = $serviceName; } if ($serviceId) { $settings['list_id'] = $serviceId; } return $settings; } public function validate($settings, $integrationId, $formId) { $error = false; $errors = []; foreach ($this->getFields($settings['list_id']) as $field) { if ($field['required'] && empty($settings[$field['key']])) { $error = true; $errors[$field['key']] = [__($field['label'] . ' is required', 'fluentformpro')]; } } if ($error) { wp_send_json_error([ 'message' => __('Validation Failed', 'fluentformpro'), 'errors' => $errors ], 423); } return $settings; } public function getRemoteClient() { $settings = $this->getGlobalSettings([]); return new API($settings); } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'client_id' => '', 'client_secret' => '', 'access_token' => '', 'status' => false, ]; return wp_parse_args($globalSettings, $defaults); } public function getGlobalFields($fields) { return [ 'logo' => $this->logo, 'menu_title' => __('Mailjet Settings', 'fluentformpro'), 'menu_description' => __($this->description, 'fluentformpro'), 'valid_message' => __('Your Mailjet Integration Key is valid', 'fluentformpro'), 'invalid_message' => __('Your Mailjet Integration Key is not valid', 'fluentformpro'), 'save_button_text' => __('Save Settings', 'fluentformpro'), 'config_instruction' => __($this->getConfigInstructions(), 'fluentformpro'), 'fields' => [ 'api_key' => [ 'type' => 'text', 'placeholder' => __('Mailjet API Key', 'fluentformpro'), 'label_tips' => __('Enter your Mailjet API Key', 'fluentformpro'), 'label' => __('Mailjet API Key', 'fluentformpro'), ], 'secret_key' => [ 'type' => 'password', 'placeholder' => __('Mailjet Secret Key', 'fluentformpro'), 'label_tips' => __('Enter your Mailjet Secret Key', 'fluentformpro'), 'label' => __('Mailjet Secret Key', 'fluentformpro'), ], ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your Mailjet API integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect Mailjet', 'fluentformpro'), 'data' => [ 'api_key' => '', 'secret_key' => '', 'access_token' => '', ], 'show_verify' => true ] ]; } protected function getConfigInstructions() { ob_start(); ?>
    1. Go Here and copy your API Key and Secret Key.
    '', 'secret_key' => '', 'access_token' => '', 'status' => false ]; update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_error([ 'message' => __('Please provide all fields to integrate', 'fluentformpro'), 'status' => false ], 423); } try { $client = new API($settings); $result = $client->checkAuth(); if (is_wp_error($result)) { throw new \Exception($result->get_error_message(), $result->get_error_code()); } } catch (\Exception $exception) { wp_send_json_error([ 'message' => $exception->getMessage(), 'status' => false ], $exception->getCode()); } $integrationSettings = [ 'api_key' => $settings['api_key'], 'secret_key' => $settings['secret_key'], 'status' => true ]; update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your Mailjet API key has been verified and successfully set', 'fluentformpro'), 'status' => true ], 200); } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => $this->title . ' Integration', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-mailjet-settings'), 'configure_message' => __('Mailjet is not configured yet! Please configure your Mailjet API first', 'fluentformpro'), 'configure_button_text' => __('Set Mailjet API', 'fluentformpro') ]; return $integrations; } public function getIntegrationDefaults($settings, $formId) { $listId = $this->app->request->get('serviceId'); return [ 'name' => '', 'list_id' => $listId, 'fields' => [ [ 'item_value' => '', 'label' => '' ] ], 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { $fieldSettings = [ 'fields' => [ [ 'key' => 'name', 'label' => __('Feed Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'list_id', 'label' => __('Mailjet Services', 'fluentformpro'), 'placeholder' => __('Select Mailjet Service', 'fluentformpro'), 'required' => true, 'component' => 'refresh', 'options' => $this->getLists() ], ], 'button_require_list' => false, 'integration_title' => $this->title ]; $listId = $this->app->request->get('serviceId', ArrayHelper::get($settings, 'list_id')); if ($listId) { $fields = $this->getFields($listId); if (empty($fields)) { wp_send_json_error([ 'message' => __("The selected service doesn't have any field settings.", 'fluentformpro'), ], 423); } $fields = array_merge($fieldSettings['fields'], $fields); $fieldSettings['fields'] = $fields; } $fieldSettings['fields'] = array_merge($fieldSettings['fields'], [ [ 'require_list' => false, 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow this integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => false, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable this feed', 'fluentformpro') ] ]); return $fieldSettings; } protected function getLists() { return [ 'contact' => 'Contact', 'template' => 'Template', 'send' => 'Send Email' ]; } public function getMergeFields($list, $listId, $formId) { return false; } public function getFields($listId) { $settings = $this->getGlobalSettings([]); $mergedFields = []; switch ($listId) { case 'contact': $mergedFields = [ [ 'key' => 'contact_bool_IsExcludedFromCampaigns', 'label' => __('Exclude the contact', 'fluentformpro'), 'required' => false, 'tips' => __('Whether the contact is added to the exclusion list for campaigns or not', 'fluentformpro'), 'component' => 'radio_choice', 'options' => [ 'true' => __('Yes', 'fluentformpro'), 'false' => __('No', 'fluentformpro') ] ], [ 'key' => 'contact_string_Email', 'placeholder' => __('Enter Contact Email', 'fluentformpro'), 'label' => __('Contact Email', 'fluentformpro'), 'required' => true, 'tips' => __('Contact Email is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'contact_string_Name', 'placeholder' => __('Enter Contact Name', 'fluentformpro'), 'label' => __('Contact Name', 'fluentformpro'), 'required' => false, 'tips' => __('Contact Name is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], ]; break; case 'template': $mergedFields = [ [ 'key' => 'template_string_Name', 'placeholder' => __('Enter Template Name', 'fluentformpro'), 'label' => __('Template Name', 'fluentformpro'), 'required' => true, 'tips' => __('Template name is a required string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'template_string_Author', 'placeholder' => __('Enter Author Name', 'fluentformpro'), 'label' => __('Author Name', 'fluentformpro'), 'required' => true, 'tips' => __('Author Name is a required string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'template_multiselect_Categories', 'placeholder' => __('Select Categories', 'fluentformpro'), 'label' => __('Select Categories', 'fluentformpro'), 'required' => false, 'tips' => __('Select a Template Category', 'fluentformpro'), 'component' => 'select', 'is_multiple' => true, 'options' => [ 'full' => 'Full', 'basic' => 'Basic', 'newsletter' => 'Newsletter', 'e-commerce' => 'E-commerce', 'events' => 'Events', 'travel' => 'Travel', 'sports' => 'Sports', 'welcome' => 'Welcome', 'contact-property-update' => 'Contact Property Update', 'support' => 'Support', 'invoice' => 'Invoice', 'anniversary' => 'Anniversary', 'account' => 'Account', 'activation' => 'Activation' ] ], [ 'key' => 'template_string_Copyright', 'placeholder' => __('Enter Copyright Message', 'fluentformpro'), 'label' => __('Copyright Message', 'fluentformpro'), 'required' => false, 'tips' => __('Copyright Message is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'template_string_Description', 'placeholder' => __('Enter Template Description', 'fluentformpro'), 'label' => __('Company Message', 'fluentformpro'), 'required' => false, 'tips' => __('Company Message is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'template_bool_IsStarred', 'label' => __('Starred Campaign', 'fluentformpro'), 'required' => false, 'tips' => __('Whether the campaign is marked as Starred or not.', 'fluentformpro'), 'component' => 'radio_choice', 'options' => [ 'true' => __('Yes', 'fluentformpro'), 'false' => __('No', 'fluentformpro') ] ], [ 'key' => 'template_multiselect_Purposes', 'placeholder' => __('Select Purpose', 'fluentformpro'), 'label' => __('Select Purpose', 'fluentformpro'), 'required' => true, 'tips' => __('Select a Purpose', 'fluentformpro'), 'component' => 'select', 'is_multiple' => true, 'options' => [ 'marketing' => __('Marketing', 'fluentformpro'), 'transactional' => __('Transactional', 'fluentformpro'), 'automation' => __('Automation', 'fluentformpro') ], ] ]; break; case 'send': $mergedFields = [ [ 'key' => 'send_string_FromEmail', 'placeholder' => __('Enter Sender Email', 'fluentformpro'), 'label' => __('Sender Email', 'fluentformpro'), 'required' => true, 'tips' => __('Sender Email is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'send_string_FromName', 'placeholder' => __('Enter Sender Name', 'fluentformpro'), 'label' => __('Sender Name', 'fluentformpro'), 'required' => false, 'tips' => __('Sender Name is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'send_string_To', 'placeholder' => __('Enter Recipients Email', 'fluentformpro'), 'label' => __('Recipients Email', 'fluentformpro'), 'required' => true, 'tips' => __('Recipients Email is a required string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'send_string_Cc', 'placeholder' => __('Enter CC Email', 'fluentformpro'), 'label' => __('CC Email', 'fluentformpro'), 'required' => false, 'tips' => __('CC Email is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'send_string_Bcc', 'placeholder' => __('Enter BCC Email', 'fluentformpro'), 'label' => __('BCC Email', 'fluentformpro'), 'required' => false, 'tips' => __('BCC Email is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'send_string_Subject', 'placeholder' => __('Enter Email Subject', 'fluentformpro'), 'label' => __('Email Subject', 'fluentformpro'), 'required' => true, 'tips' => __('Email Subject is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'send_string_Text-part', 'placeholder' => __('Enter Email Text Part', 'fluentformpro'), 'label' => __('Email Text Part', 'fluentformpro'), 'required' => true, 'tips' => __('Email Text Part is a required string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'send_string_Html-part', 'placeholder' => __('Enter Email Html Part', 'fluentformpro'), 'label' => __('Email Html Part', 'fluentformpro'), 'required' => false, 'tips' => __('Email Html Part is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'send_string_Mj-campaign', 'placeholder' => __('Enter Campaign Name', 'fluentformpro'), 'label' => __('Campaign Name', 'fluentformpro'), 'required' => false, 'tips' => __('Campaign Name is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], ]; break; default: $mergedFields = [ [] ]; } return $mergedFields; } protected function getAllFields($listId) { $fields = $this->getFields($listId); $allFields = []; foreach ($fields as $field) { $keyData = []; $keyData['key'] = $field['key']; if ($field['required']) { $keyData['required'] = $field['required']; $allFields[] = $keyData; } else { $keyData['required'] = 0; $allFields[] = $keyData; } } return $allFields; } public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; $subscriber['attributes'] = []; $subscriber['list_id'] = $feedData['list_id']; $allFields = $this->getAllFields($feedData['list_id']); foreach ($allFields as $field) { $key = $field['key']; if (!empty($feedData[$key])) { $fieldArray = explode('_', $key, 3); $fieldService = $fieldArray[0]; $fieldType = $fieldArray[1]; $fieldName = $fieldArray[2]; if ($fieldType == 'bool') { if (ArrayHelper::get($feedData, $key) == 'true') { $subscriber['attributes'][$fieldName] = true; } else { $subscriber['attributes'][$fieldName] = false; } } else { $subscriber['attributes'][$fieldName] = ArrayHelper::get($feedData, $key); } if ($fieldService == 'send') { $subscriber['attributes']['Mj-deduplicatecampaign'] = false; } } } $client = $this->getRemoteClient(); $response = $client->subscribe($subscriber); if (!is_wp_error($response)) { do_action('fluentform/integration_action_result', $feed, 'success', 'Mailjet feed has been successfully initiated and pushed data'); } else { $error = $response->get_error_message(); do_action('fluentform/integration_action_result', $feed, 'failed', $error); } } } PK!$  src/Integrations/Mailjet/API.phpnu[clientId = $settings['api_key']; $this->clientSecret = $settings['secret_key']; $this->accessToken = 'Basic ' . base64_encode($settings['api_key'] . ':' . $settings['secret_key']); } public function checkAuth() { return $this->makeRequest($this->url . 'rest/contact'); } public function makeRequest($url, $bodyArgs = [], $type = 'GET') { $request = []; if ($type == 'GET') { $request = wp_remote_get($url, [ 'headers' => [ 'Content-Type' => 'application/json', 'Accept' => 'application/json', 'Authorization' => $this->accessToken, ] ]); } if ($type == 'POST') { $request = wp_remote_post($url, [ 'headers' => [ 'Content-Type' => 'application/json', 'Accept' => 'application/json', 'Authorization' => $this->accessToken, ], 'body' => $bodyArgs ]); } if (is_wp_error($request)) { $code = $request->get_error_code(); $message = $request->get_error_message(); return new \WP_Error($code, $message); } $body = wp_remote_retrieve_body($request); $body = \json_decode($body, true); $code = wp_remote_retrieve_response_code($request); if ($code == 200 || $code == 201) { return $body; } else { if (is_null($body)) { return new \WP_Error($code, __('Bad Request.', 'fluentformpro')); } return new \WP_Error($code, __('Error related to ' . $body['ErrorRelatedTo'][0] . ': ' . $body['ErrorMessage'], 'fluentformpro')); } } public function subscribe($subscriber) { if ($subscriber['list_id'] == 'send') { $url = $this->url . $subscriber['list_id']; } else { $url = $this->url . 'rest/' . $subscriber['list_id']; } $post = \json_encode($subscriber['attributes'], true); $response = $this->makeRequest($url, $post, 'POST'); return $response; } } PK!63+3+'src/Integrations/Mailster/Bootstrap.phpnu[logo = fluentFormMix('img/integrations/mailster.png'); $this->description = "Send Beautiful Email Newsletters in WordPress. Join more than 26,000 people worldwide and use Mailster to grow your business."; add_filter('fluentform/save_integration_value_' . $this->integrationKey, [$this, 'validate'], 10, 3); $this->registerAdminHooks(); } public function validate($settings, $integrationId, $formId) { $error = false; $errors = array(); foreach ($this->getFields() as $field){ if ($field['required'] && empty($settings[$field['key']])) { $error = true; $errors[$field['key']] = [__($field['label'].' is required', 'fluentformpro')]; } } if ($error){ wp_send_json_error([ 'message' => __('Validation Failed', 'fluentformpro'), 'errors' => $errors ], 423); } return $settings; } public function requiredPlugin() { $pluginInfo = $this->getMailsterInstallationDetails(); $class = 'notice notice-error'; $install_url_text = 'Click Here to Install the Plugin'; if ($pluginInfo->action == 'activate') { $install_url_text = 'Click Here to Activate the Plugin'; } $message = __('Fluent Forms Mailster Integration Requires Mailster Plugin', 'fluentformpro') . '' . $install_url_text . ''; printf('

    %2$s

    ', esc_attr($class), __($message, 'fluentformpro')); } protected function getMailsterInstallationDetails() { $activation = (object)[ 'action' => 'install', 'url' => '' ]; $allPlugins = get_plugins(); if (isset($allPlugins['mailster/mailster.php'])) { $url = wp_nonce_url( self_admin_url('plugins.php?action=activate&plugin=mailster/mailster.php'), 'activate-plugin_mailster/mailster.php' ); $activation->action = 'activate'; } else { $api = (object)[ 'slug' => 'mailster' ]; $url = wp_nonce_url( self_admin_url('update.php?action=install-plugin&plugin=' . $api->slug), 'install-plugin_' . $api->slug ); } $activation->url = $url; return $activation; } public function addGlobalMenu($setting) { return $setting; } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'category' => '', 'disable_global_settings' => 'yes', 'logo' => $this->logo, 'title' => $this->title . ' Integration', 'is_active' => $this->isConfigured() ]; return $integrations; } public function getIntegrationDefaults($settings, $formId) { return [ 'name' => '', 'list_id' => '', 'other_fields' => [ [ 'item_value' => '', 'label' => '' ] ], 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'enabled' => true ]; } public function getSettingsFields($settings, $formId = null) { if (!function_exists('mailster')) { return []; } $allFieldSettings = [ 'fields' => [ [ 'key' => 'name', 'label' => __('Feed Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'list_id', 'label' => __('Mailster Lists', 'fluentformpro'), 'placeholder' => __('Select Mailster List', 'fluentformpro'), 'required' => true, 'component' => 'select', 'tips' => __('Select Mailster List', 'fluentformpro'), 'options' => $this->getLists() ], ], 'integration_title' => $this->title ]; $getFields = $this->getFields(); $allFieldSettings['fields'] = array_merge($allFieldSettings['fields'], $getFields, [ [ 'require_list' => false, 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow this integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => false, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable this feed', 'fluentformpro') ] ]); return $allFieldSettings; } public function getMergeFields($list, $listId, $formId) { return false; } protected function getLists() { $modifiedList = []; $lists = mailster('lists')->get(); foreach ($lists as $field) { $modifiedList[$field->ID] = $field->name; } return $modifiedList; } protected function getFields() { return [ [ 'key' => 'firstname', 'label' => __('Enter First Name', 'fluentformpro'), 'required' => true, 'tips' => __('Enter First Name', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'lastname', 'label' => __('Enter Last Name', 'fluentformpro'), 'required' => true, 'tips' => __('Enter Last Name', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'email', 'label' => __('Enter Email', 'fluentformpro'), 'required' => true, 'tips' => __('Enter Email', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'mailster_status', 'label' => __('Select Status', 'fluentformpro'), 'required' => false, 'tips' => __('Select Status', 'fluentformpro'), 'component' => 'select', 'options' => [ "value_0" => __('Pending', 'fluentformpro'), "value_1" => __('Subscribed', 'fluentformpro'), "value_2" => __('Unsubscribed', 'fluentformpro'), "value_3" => __('Hardbounced', 'fluentformpro') ] ], [ 'key' => 'referer', 'label' => __('Enter Referer Name', 'fluentformpro'), 'required' => false, 'tips' => __('Enter Referer name', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'other_fields', 'require_list' => false, 'required' => false, 'label' => __('Custom Fields', 'fluentformpro'), 'tips' => __('Map Custom fields according with Fluent Forms fields.', 'fluentformpro'), 'component' => 'dropdown_label_repeater', 'field_label' => __('Custom Field Key', 'fluentformpro'), 'value_label' => __('Custom Field Value', 'fluentformpro') ] ]; } public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; $subscriber = [ 'list_id' => $feedData['list_id'] ]; $getFields = $this->getFields(); foreach ($getFields as $fieldValue) { if (!empty($feedData[$fieldValue['key']])) { if ($fieldValue['key'] == 'other_fields') { $otherFields = ArrayHelper::get($feedData, 'other_fields'); foreach ($otherFields as $other) { if (!empty($other['item_value'])) { $subscriber[$other['label']] = $other['item_value']; } } } else { if (strpos($fieldValue['key'], 'mailster') !== false) { $arr = explode('_', $fieldValue['key']); $key = $arr[1]; $subscriber[$key] = ArrayHelper::get($feedData, $fieldValue['key']); if (strpos($subscriber[$key], 'value_') !== false) { $subscriber[$key] = explode('_', $subscriber[$key])[1]; } } else { $subscriber[$fieldValue['key']] = ArrayHelper::get($feedData, $fieldValue['key']); } } } } if (function_exists('mailster')) { $subscriber_id = mailster('subscribers')->add($subscriber); if (!is_wp_error($subscriber_id)) { mailster('subscribers')->assign_lists($subscriber_id, $subscriber['list_id'], false); do_action('fluentform/integration_action_result', $feed, 'success', __('Mailster feed has been successfully initialed and pushed data', 'fluentformpro')); } else { $error = $subscriber_id->get_error_message(); do_action('fluentform/integration_action_result', $feed, 'failed', $error); } } else { do_action('fluentform/integration_action_result', $feed, 'failed', __('Please install or active Mailster plugin.', 'fluentformpro')); } } public function isConfigured() { return true; } } PK!C8//&src/Integrations/MooSend/Bootstrap.phpnu[description = 'Connect MooSend with Fluent Forms and subscribe a contact when a form is submitted.'; $this->logo = fluentFormMix('img/integrations/moosend_logo.png'); $this->registerAdminHooks(); // add_filter('fluentform/notifying_async_moosend', '__return_false'); } public function getGlobalFields($fields) { return [ 'logo' => $this->logo, 'menu_title' => __('MooSend API Settings', 'fluentformpro'), 'menu_description' => __('MooSend is email marketing software. Use Fluent Forms to collect customer information and automatically add it as MooSend subscriber list.', 'fluentformpro'), 'valid_message' => __('Your MooSend API Key is valid', 'fluentformpro'), 'invalid_message' => __('Your MooSend API Key is not valid', 'fluentformpro'), 'save_button_text' => __('Save Settings', 'fluentformpro'), 'fields' => [ 'apiKey' => [ 'type' => 'password', 'placeholder' => 'API Key', 'label_tips' => __("Enter your MooSend API Key, if you do not have
    Please log in to your MooSend account and go to
    Account -> Api Key", 'fluentformpro'), 'label' => __('MooSend API Key', 'fluentformpro'), ] ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your MooSend API integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect MooSend', 'fluentformpro'), 'data' => [ 'apiKey' => '' ], 'show_verify' => true ] ]; } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'apiKey' => '', 'status' => '' ]; return wp_parse_args($globalSettings, $defaults); } public function saveGlobalSettings($settings) { if (!$settings['apiKey']) { $integrationSettings = [ 'apiKey' => '', 'status' => false ]; // Update the reCaptcha details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your settings has been updated', 'fluentformpro'), 'status' => false ], 200); } // Verify API key now try { $api = new API($settings['apiKey']); $result = $api->auth_test(); if (!empty($result['Error'])) { throw new \Exception($result['Error']); } } catch (\Exception $exception) { wp_send_json_error([ 'message' => $exception->getMessage(), 'status' => false ], 400); } // Integration key is verified now, Proceed now $integrationSettings = [ 'apiKey' => sanitize_text_field($settings['apiKey']), 'status' => true ]; // Update the reCaptcha details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your MooSend api key has been verified and successfully set', 'fluentformpro'), 'status' => true ], 200); } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => $this->title . ' Integration', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-moosend-settings'), 'configure_message' => __('MooSend is not configured yet! Please configure your MooSend api first', 'fluentformpro'), 'configure_button_text' => __('Set MooSend API', 'fluentformpro') ]; return $integrations; } public function getIntegrationDefaults($settings, $formId) { return [ 'name' => '', 'SubscriberName' => '', // Name in MooSend 'Email' => '', 'HasExternalDoubleOptIn' => false, 'CustomFields' => (object)[], 'list_id' => '', // MailingListID 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { return [ 'fields' => [ [ 'key' => 'name', 'label' => __('Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'list_id', 'label' => __('MooSend Mailing Lists', 'fluentformpro'), 'placeholder' => __('Select MooSend Mailing List', 'fluentformpro'), 'tips' => __('Select the MooSend Mailing List you would like to add your contacts to.', 'fluentformpro'), 'component' => 'list_ajax_options', 'options' => $this->getLists(), ], [ 'key' => 'CustomFields', 'require_list' => true, 'label' => __('Map Fields', 'fluentformpro'), 'tips' => __('Associate your MooSend merge tags to the appropriate Fluent Forms fields by selecting the appropriate form field from the list.', 'fluentformpro'), 'component' => 'map_fields', 'field_label_remote' => __('MooSend Field', 'fluentformpro'), 'field_label_local' => __('Form Field', 'fluentformpro'), 'primary_fileds' => [ [ 'key' => 'Email', 'label' => __('Email Address', 'fluentformpro'), 'required' => true, 'input_options' => 'emails' ], [ 'key' => 'SubscriberName', 'label' => __('Name', 'fluentformpro') ] ] ], [ 'key' => 'HasExternalDoubleOptIn', 'require_list' => true, 'label' => __('Double Opt-in', 'fluentformpro'), 'tips' => __('When the double opt-in option is enabled,
    MooSend will send a confirmation email
    to the user and will only add them to your
    'checkbox-single', 'checkbox_label' => __('Enable Double Opt-in', 'fluentformpro') ], [ 'require_list' => true, 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow MooSend integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => true, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable This feed', 'fluentformpro') ] ], 'button_require_list' => true, 'integration_title' => $this->title ]; } public function getMergeFields($list, $listId, $formId) { $api = $this->getApiInstance(); $remoteList = $api->getList($listId); $mergetags = []; if (!$remoteList) { return $mergetags; } foreach ($remoteList['CustomFieldsDefinition'] as $tag) { $mergetags[$tag['Name']] = $tag['Name']; } return $mergetags; } protected function getLists() { $api = $this->getApiInstance(); $lists = $api->getLists(); $formattedLists = []; foreach ($lists as $list) { $formattedLists[$list['ID']] = $list['Name']; } return $formattedLists; } /* * Form Submission Hooks Here */ public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; if (!is_email($feedData['Email'])) { $feedData['Email'] = ArrayHelper::get($formData, $feedData['Email']); } if (!is_email($feedData['Email'])) { do_action('fluentform/integration_action_result', $feed, 'failed', __('Moosend API call has been skipped because no valid email available', 'fluentformpro')); // No Valid email found return; } $subscriber = [ 'Name' => $feedData['SubscriberName'], 'Email' => $feedData['Email'], ]; $customFields = ArrayHelper::get($feedData, 'CustomFields', []); $subscriber['CustomFields'] = $customFields; $subscriber = array_filter($subscriber); $subscriber = apply_filters_deprecated( 'fluentform_integration_data_' . $this->integrationKey, [ $subscriber, $feed, $entry ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/integration_data_' . $this->integrationKey, 'Use fluentform/integration_data_' . $this->integrationKey . ' instead of fluentform_integration_data_' . $this->integrationKey ); $subscriber = apply_filters('fluentform/integration_data_' . $this->integrationKey, $subscriber, $feed, $entry); $api = $this->getApiInstance(); // ! is required for Moosend. Their API is bit confusing $isDoubleOptIn = !ArrayHelper::isTrue($feedData, 'HasExternalDoubleOptIn'); $result = $api->subscribe($feedData['list_id'], $subscriber, $isDoubleOptIn); if (is_wp_error($result)) { do_action('fluentform/integration_action_result', $feed, 'failed', $result->get_error_message()); return; } do_action('fluentform/integration_action_result', $feed, 'success', __('Moosend feed has been successfully initialed and pushed data', 'fluentformpro')); } protected function getApiInstance() { $settings = $this->getApiSettings(); return new API($settings['apiKey']); } } PK!ц src/Integrations/MooSend/API.phpnu[apiKey = $apiKey; } public function default_options() { return array( 'apikey' => $this->apiKey ); } public function make_request($action, $options = array(), $method = 'GET') { /* Build request options string. */ $request_options = $this->default_options(); $request_options = wp_parse_args($options, $request_options); $options_string = http_build_query($request_options); /* Build request URL. */ $request_url = $this->apiUrl . $action . '?' . $options_string; /* Execute request based on method. */ switch ($method) { case 'POST': $request_url = $this->apiUrl . $action . '?apikey=' . $this->apiKey; $args = []; $args['body'] = $options; $args['method'] = 'POST'; $args['headers'] = [ 'Content-Type' => 'application/json', 'Accept' => 'application/json' ]; $response = wp_remote_post($request_url, $args); break; case 'GET': $response = wp_remote_get($request_url); break; } /* If WP_Error, die. Otherwise, return decoded JSON. */ if (is_wp_error($response)) { return [ 'error' => 'API_Error', 'message' => $response->get_error_message() ]; } else { return json_decode($response['body'], true); } } /** * Test the provided API credentials. * * @access public * @return bool */ public function auth_test() { return $this->make_request('lists.json', [ 'WithStatistics' => false, 'ShortBy' => 'CreatedOn', 'SortMethod' => 'ASC', 'PageSize' => 1 ], 'GET'); } public function subscribe($formId, $data, $doubleOptIn = false) { $data['HasExternalDoubleOptIn'] = $doubleOptIn; $url = $this->apiUrl."subscribers/" . $formId . "/subscribe.json?apikey=" . $this->apiKey; if(!empty($data['CustomFields'])) { $customFields = $data['CustomFields']; $fieldPairs = []; foreach ($customFields as $key => $value){ if(!$value) { continue; } $fieldPairs[] = $key.'='.$value; } if($fieldPairs) { $data['CustomFields'] = $fieldPairs; } } $response = wp_remote_post($url, [ 'method' => 'POST', 'timeout' => 45, 'blocking' => true, 'header' => [ 'Content-Type' => 'application/json', 'Accept' => 'application/json' ], 'body' => $data ]); if($response && is_wp_error($response)) { return new \WP_Error('request_error', $response->get_error_messages()); } $responseBody = json_decode($response['body'], true); if(!empty($responseBody['Error'])) { return new \WP_Error('api_error', $response['message']); } return $responseBody['Context']; } /** * Get all Forms in the system. * * @access public * @return array */ public function getLists() { $response = $this->make_request('lists.json', [ 'WithStatistics' => false, 'ShortBy' => 'CreatedOn', 'SortMethod' => 'DESC', 'PageSize' => 999 ], 'GET'); if (empty($response['Error']) && !empty($response['Context']['MailingLists'])) { return $response['Context']['MailingLists']; } return false; } /** * Get single Form in the system. * * @access public * @return array */ public function getList($listId) { $response = $this->make_request('lists/' . $listId . '/details.json', [ 'WithStatistics' => false ], 'GET'); if (empty($response['Error'])) { return $response['Context']; } return false; } } PK!QKK*src/Integrations/NewAirtable/Bootstrap.phpnu[logo = fluentformmix('img/integrations/airtable.png'); $this->description = "Airtable is a low-code platform for building collaborative apps. Customize your workflow, collaborate, and achieve ambitious outcomes."; $this->registerAdminHooks(); add_filter( 'fluentform/get_integration_values_' . $this->integrationKey, [$this, 'resolveIntegrationSettings'], 10, 3 ); add_filter( 'fluentform/save_integration_value_' . $this->integrationKey, [$this, 'validate'], 10, 3 ); } public function resolveIntegrationSettings($settings, $feed, $formId) { $configs = $this->app->request->get('configs', ''); $baseId = ArrayHelper::get($configs, 'base_id'); $tableId = ArrayHelper::get($configs, 'table_id'); if ($baseId) { $settings['chained_config']['base_id'] = $configs['base_id']; } if ($tableId) { $settings['chained_config']['table_id'] = $configs['table_id']; } return $settings; } public function validate($settings, $integrationId, $formId) { $error = false; $errors = []; $baseId = ArrayHelper::get($settings, 'chained_config' . '.' . 'base_id'); $tableId = ArrayHelper::get($settings, 'chained_config' . '.' . 'table_id'); $fields = $this->getFields($baseId, $tableId); if (isset($fields['status']) && $fields['status'] === false) { wp_send_json_error([ 'message' => __($fields['message'], 'fluentformpro'), 'errors' => [] ], 423); } foreach ($fields as $field) { if ($field['required'] && empty($settings[$field['key']])) { $error = true; $errors[$field['key']] = [__($field['label'] . ' is required', 'fluentformpro')]; } } if ($error) { wp_send_json_error([ 'message' => __('Validation Failed', 'fluentformpro'), 'errors' => $errors ], 423); } return $settings; } public function getRemoteClient() { $settings = $this->getGlobalSettings([]); return new API( $settings ); } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'status' => false, 'access_token' => '' ]; return wp_parse_args($globalSettings, $defaults); } public function getGlobalFields($fields) { return [ 'logo' => $this->logo, 'menu_title' => __('Airtable Settings', 'fluentformpro'), 'menu_description' => __($this->description, 'fluentformpro'), 'valid_message' => __('Your Airtable API Key is valid', 'fluentformpro'), 'invalid_message' => __('Your Airtable API Key is not valid', 'fluentformpro'), 'save_button_text' => __('Save Settings', 'fluentformpro'), 'config_instruction' => __($this->getConfigInstructions(), 'fluentformpro'), 'fields' => [ 'access_token' => [ 'type' => 'password', 'placeholder' => __('Airtable Access Token', 'fluentformpro'), 'label_tips' => __('Enter your Airtable Access Token', 'fluentformpro'), 'label' => __('Airtable Access Token', 'fluentformpro'), ], ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your Airtable API integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect Airtable', 'fluentformpro'), 'data' => [ 'access_token' => '', ], 'show_verify' => true ] ]; } protected function getConfigInstructions() { ob_start(); ?>
    1. Go Here and create your Access Token by clicking Create new token button.
    2. Give a name for your token then select these scope data.records:read, data.records:write and schema.bases:read by clicking Add a scope.
    3. Select your access level by clicking Add a base then hit the Create token button below.
    4. After token creation, copy the token and paste it here.
    '', 'status' => false ]; update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_error([ 'message' => __('Please provide all fields to integrate', 'fluentformpro'), 'status' => false ], 423); } try { $client = new API($settings); $result = $client->checkAuth(); if (is_wp_error($result)) { throw new \Exception($result->get_error_message(), $result->get_error_code()); } } catch (\Exception $exception) { wp_send_json_error([ 'message' => $exception->getMessage(), 'status' => false ], $exception->getCode()); } $integrationSettings = [ 'access_token' => $settings['access_token'], 'status' => true ]; update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your Airtable Access Token has been verified and successfully set', 'fluentformpro'), 'status' => true ], 200); } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => $this->title . ' Integration', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-airtable_v2-settings'), 'configure_message' => __('Airtable is not configured yet! Please configure your Airtable api first', 'fluentformpro'), 'configure_button_text' => __('Set Airtable API', 'fluentformpro') ]; return $integrations; } public function getIntegrationDefaults($settings, $formId) { $config = $this->app->request->get('configs'); $baseId = ArrayHelper::get($config, 'base_id'); $tableId = ArrayHelper::get($config, 'table_id'); return [ 'name' => '', 'chained_config' => [ 'base_id' => $baseId, 'table_id' => $tableId, ], 'typecast' => false, 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { $config = $this->app->request->get('configs', ArrayHelper::get($settings, 'chained_config')); $baseId = ArrayHelper::get($config, 'base_id'); $tableId = ArrayHelper::get($config, 'table_id'); $fieldSettings = [ 'fields' => [ [ 'key' => 'name', 'label' => __('Feed Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'chained_config', 'label' => __('Airtable Configuration', 'fluentformpro'), 'required' => true, 'component' => 'chained-ajax-fields', 'options_labels' => [ 'base_id' => [ 'placeholder' => __('Select Base', 'fluentformpro'), 'options' => $this->getBases() ], 'table_id' => [ 'placeholder' => __('Select Table', 'fluentformpro'), 'options' => $this->getTables($baseId) ], ] ], ], 'button_require_list' => false, 'integration_title' => $this->title ]; $error = false; $message = ''; if ($baseId && $tableId) { $fields = $this->getFields($baseId, $tableId); if (isset($fields['status']) && $fields['status'] === false) { $error = true; $message = $fields['message']; } if (!$error) { $fields = array_merge($fieldSettings['fields'], $fields); $fieldSettings['fields'] = $fields; } } $fieldSettings['fields'] = array_merge($fieldSettings['fields'], [ [ 'key' => 'typecast', 'label' => __('Enable Typecast', 'fluentformpro'), 'required' => false, 'tips' => __('Whether auto typecasting is enabled or not.', 'fluentformpro'), 'component' => 'radio_choice', 'options' => [ true => 'Yes', false => 'No' ] ], [ 'require_list' => false, 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow this integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => false, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable this feed', 'fluentformpro') ] ]); if ($error) { wp_send_json_error([ 'settings_fields' => $fieldSettings, 'message' => __($message, 'fluentform'), 'status' => false ], 423); } return $fieldSettings; } public function getMergeFields($list, $listId, $formId) { return false; } protected function getBases() { $api = $this->getRemoteClient(); if (!$api) { return []; } $bases = $api->getBases(); if (is_wp_error($bases)) { wp_send_json_error([ 'message' => $bases->get_error_message() ], 423); } $formattedBases = []; foreach ($bases['bases'] as $base) { $formattedBases[$base['id']] = $base['name']; } return $formattedBases; } protected function getTables($baseId) { if (!$baseId) { return []; } $api = $this->getRemoteClient(); if (!$api) { return []; } $tables = $api->getTables($baseId); if (is_wp_error($tables)) { wp_send_json_error([ 'message' => $tables->get_error_message() ], 423); } $formattedTables = []; foreach ($tables['tables'] as $table) { $formattedTables[$table['id']] = $table['name']; } return $formattedTables; } protected function getFields($baseId, $tableId) { if (!$baseId && $tableId) { return []; } $formattedFields = []; $api = $this->getRemoteClient(); $tables = $api->getTables($baseId); if (is_wp_error($tables)) { wp_send_json_error([ 'message' => $tables->get_error_message() ], 423); } $fields = []; foreach ($tables['tables'] as $table) { if ($table['id'] == $tableId) { $fields = $table['fields']; break; } } $supportedFormatsArray = $this->getSupportedFormats(); foreach ($fields as $fieldValue) { if (array_key_exists($fieldValue['type'], $supportedFormatsArray)) { $data = [ 'key' => $fieldValue['id'], 'placeholder' => __($fieldValue['name'], 'fluentformpro'), 'tips' => __(ArrayHelper::get($supportedFormatsArray, $fieldValue['type']), 'fluentformpro'), 'label' => __($fieldValue['name'], 'fluentformpro'), 'required' => false, 'component' => 'value_text', 'type' => $fieldValue['type'], ]; $formattedFields[] = $data; } } return $formattedFields; } protected function getSupportedFormats() { return [ 'singleLineText' => 'Single Line Text field', 'multilineText' => 'Multi Line Text field', 'checkbox' => 'Boolean field', 'singleSelect' => 'Single Select field', 'multipleSelects' => 'Multi Select field', 'date' => 'Date field supports M/D/YYYY | D/M/YYYY | YYYY-MM-DD format', 'phoneNumber' => 'Phone Field', 'email' => 'Email Field', 'url' => 'URL field', 'number' => 'Number Field', 'currency' => 'Currency Field', 'percent' => 'Percentage Value', 'duration' => 'An integer value representing number in seconds', 'rating' => 'Rating Field supports value ranged from 1 to 10', 'singleCollaborator' => 'Use Airtable registered User email', 'multipleAttachments' => 'Allow you to add images, documents through Upload' ]; } public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; $subscriber = []; $records['records'] = []; $baseId = ArrayHelper::get($feedData, 'chained_config' . '.' . 'base_id'); $tableId = ArrayHelper::get($feedData, 'chained_config' . '.' . 'table_id'); $formFields = ArrayHelper::get(json_decode($form->form_fields, true), 'fields'); $fields = $this->getFields($baseId, $tableId); foreach ($fields as $field) { $fieldType = $field['type']; $fieldName = $field['label']; $fieldKey = $field['key']; $value = ArrayHelper::get($feedData, $fieldKey); if (!empty($value)) { if ($fieldType == 'checkbox') { if ($value == 'true' || $value == 'yes') { $value = true; } elseif ($value == 'false' || $value == 'no') { $value = false; } $subscriber[$fieldName] = $value; } elseif ($fieldType == 'multipleSelects') { $arrayValues = array_map('trim', explode(',', $value)); $subscriber[$fieldName] = []; foreach ($arrayValues as $multiValue) { $subscriber[$fieldName][] = $multiValue; } } elseif ($fieldType == 'singleCollaborator') { if (is_email($value)) { $subscriber[$fieldName] = ['email' => $value]; } } elseif ($fieldType == 'multipleAttachments') { $arrayValues = array_map('trim', explode(',', $value)); $subscriber[$fieldName] = []; foreach ($arrayValues as $urlValue) { $subscriber[$fieldName][] = ['url' => $urlValue]; } } elseif ($fieldType == 'phoneNumber') { // handling phone validation issue foreach ($formFields as $formField) { if (ArrayHelper::get($formField, 'element') == 'phone') { if (isset($feedData[$fieldKey])) { $value .= ' '; } } } $subscriber[$fieldName] = $value; } else { $subscriber[$fieldName] = $value; } } } $subscriber = Helper::replaceBrTag($subscriber); $isTypecast = ArrayHelper::get($feed, 'settings.typecast'); if ($isTypecast) { $records = ['typecast' => true]; } $records['records'][] = ['fields' => $subscriber]; $client = $this->getRemoteClient(); $response = $client->subscribe($records, $baseId, $tableId); if (!is_wp_error($response)) { do_action('fluentform/integration_action_result', $feed, 'success', __('Airtable feed has been successfully initialed and pushed data', 'fluentformpro')); } else { $error = $response->get_error_message(); do_action('fluentform/integration_action_result', $feed, 'failed', $error); } } } PK!⒗$src/Integrations/NewAirtable/API.phpnu[accessToken = 'Bearer ' . $settings['access_token']; } public function checkAuth() { return $this->makeRequest($this->url . 'meta/whoami'); } public function getBases() { return $this->makeRequest($this->url . 'meta/bases'); } public function getTables($baseId) { return $this->makeRequest($this->url . 'meta/bases/' . $baseId . '/tables'); } public function makeRequest($url, $bodyArgs = [], $type = 'GET') { $request = []; $headers = [ 'Content-Type' => 'application/json', 'Accept' => 'application/json', 'Authorization' => $this->accessToken ]; if ($type == 'GET') { $request = wp_remote_get($url, [ 'headers' => $headers ]); } if ($type == 'POST') { $request = wp_remote_post($url, [ 'headers' => $headers, 'body' => $bodyArgs ]); } if (is_wp_error($request)) { $code = $request->get_error_code(); $message = $request->get_error_message(); return new \WP_Error($code, $message); } $body = wp_remote_retrieve_body($request); $body = \json_decode($body, true); $code = wp_remote_retrieve_response_code($request); if ($code == 200 || $code == 201) { return $body; } else { return new \WP_Error($code, isset($body['error']['type']) ? $body['error']['type'] . ': ' . $body['error']['message'] : $body['error']); } } public function subscribe($subscriber, $baseId, $tableId) { $url = 'https://api.airtable.com/v0/' . $baseId . '/' . $tableId; $post = \json_encode($subscriber, JSON_NUMERIC_CHECK); return $this->makeRequest($url, $post, 'POST'); } }PK!di4<<%src/Integrations/Notion/Bootstrap.phpnu[logo = fluentFormMix('img/integrations/notion.png'); $this->description = 'Send form submissions directly to your Notion database.'; $this->registerAdminHooks(); // add_filter('fluentform/notifying_async_notion', '__return_false'); add_filter( 'fluentform/get_integration_values_' . $this->integrationKey, [$this, 'resolveIntegrationSettings'], 10, 3 ); add_filter( 'fluentform/save_integration_value_' . $this->integrationKey, [$this, 'validate'], 10, 3 ); } public function resolveIntegrationSettings($settings, $feed, $formId) { $serviceName = $this->app->request->get('serviceName', ''); $serviceId = $this->app->request->get('serviceId', ''); if ($serviceName) { $settings['name'] = $serviceName; } if ($serviceId) { $settings['list_id'] = $serviceId; } return $settings; } public function getGlobalFields($fields) { $api = new API(); return [ 'logo' => $this->logo, 'menu_title' => __('Notion Integration', 'fluentformpro'), 'menu_description' => __($this->description, 'fluentformpro'), 'valid_message' => __('Your Notion connection is valid', 'fluentformpro'), 'invalid_message' => __('Your Notion connection is not valid', 'fluentformpro'), 'save_button_text' => __('Verify Notion', 'fluentformpro'), 'fields' => [ 'button_link' => [ 'type' => 'link', 'link_text' => __('Get Notion Code', 'fluentformpro'), 'link' => $api->getAuthUrl(), 'target' => '_blank', 'tips' => __('Please click on this link get Access Code from Notion and Select your Notion database to connect with Fluent Forms', 'fluentformpro'), ], 'access_token' => [ 'type' => 'password', 'placeholder' => __('Access Code', 'fluentformpro'), 'label_tips' => __("Please find access code by clicking 'Get Notion Access Code' Button then paste it here", 'fluentformpro'), 'label' => __('Access Code', 'fluentformpro'), ] ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your Notion integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect Notion', 'fluentformpro'), 'data' => [ 'access_code' => '' ], 'show_verify' => false ] ]; } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'access_token' => '' ]; return wp_parse_args($globalSettings, $defaults); } public function saveGlobalSettings($settings) { if (empty($settings['access_token'])) { $integrationSettings = [ 'access_token' => '', 'status' => false ]; // Update the reCaptcha details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your settings has been updated', 'fluentformpro'), 'status' => false ], 200); } // Verify API key now try { $token = sanitize_textarea_field($settings['access_token']); $api = new API(); $result = $api->generateAccessToken($token); if (is_wp_error($result)) { throw new \Exception($result->get_error_message()); } $token = [ 'status' => true, 'access_token' => $result ]; update_option($this->optionKey, $token, 'no'); } catch (\Exception $exception) { wp_send_json_error([ 'message' => $exception->getMessage() ], 400); } wp_send_json_success([ 'message' => __('Your Notion api key has been verified and successfully set', 'fluentformpro'), 'status' => true ], 200); } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => 'Notion Integration', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-notion-settings'), 'configure_message' => __('Notion is not configured yet! Please configure your Notion api first', 'fluentformpro'), 'configure_button_text' => __('Set Notion API', 'fluentformpro') ]; return $integrations; } public function getIntegrationDefaults($settings, $formId) { $listId = $this->app->request->get('serviceId'); return [ 'name' => '', 'list_id' => $listId, 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { $fieldSettings = [ 'fields' => [ [ 'key' => 'name', 'label' => __('Feed Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'list_id', 'label' => __('Notion Databases', 'fluentformpro'), 'placeholder' => __('Select Notion Database', 'fluentformpro'), 'required' => true, 'component' => 'refresh', 'options' => $this->getLists() ], ], 'button_require_list' => false, 'integration_title' => $this->title ]; $listId = $this->app->request->get('serviceId', ArrayHelper::get($settings, 'list_id')); if ($listId) { $fields = $this->getFields($listId); if (empty($fields)) { wp_send_json_error([ 'message' => __("The selected service doesn't have any field settings.", 'fluentformpro'), ], 423); } $fields = array_merge($fieldSettings['fields'], $fields); $fieldSettings['fields'] = $fields; } $fieldSettings['fields'] = array_merge($fieldSettings['fields'], [ [ 'require_list' => false, 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow this integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => false, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable this feed', 'fluentformpro') ] ]); return $fieldSettings; } public function getMergeFields($list, $listId, $formId) { return false; } protected function getLists() { $api = new API(); if (!$this->isConfigured()) { return false; } $bodyArgs = [ "filter" => [ "value" => "database", "property" => "object" ] ]; $lists = $api->makeRequest('https://api.notion.com/v1/search', $bodyArgs, 'POST'); if (is_wp_error($lists)) { wp_send_json_error([ 'message' => __($lists->get_error_message(), 'fluentformpro'), ], 423); } $databases = []; foreach ($lists['results'] as $db) { $databases[$db['id']] = $db['title'][0]['plain_text']; } return $databases; } public function validate($settings, $integrationId, $formId) { $error = false; $errors = []; foreach ($this->getFields($settings['list_id']) as $field) { if ($field['required'] && empty($settings[$field['key']])) { $error = true; $errors[$field['key']] = [__($field['label'] . ' is required', 'fluentformpro')]; } } if ($error) { wp_send_json_error([ 'message' => __('Validation Failed', 'fluentformpro'), 'errors' => $errors ], 423); } return $settings; } public function getFields($listId, $isNameValuePair = false) { $api = new API(); if (!$this->isConfigured()) { return false; } $lists = $api->makeRequest('https://api.notion.com/v1/databases/' . $listId); if (is_wp_error($lists)) { wp_send_json_error([ 'message' => __($lists->get_error_message(), 'fluentformpro'), ], 423); } $fields = []; $lists = $lists['properties']; if ($lists) { $supportedFormats = $this->getSupportedFormats(); foreach ($lists as $input) { if (!$isNameValuePair) { if (Arr::exists($supportedFormats, $input['type'])) { $fields[] = [ 'key' => $input['name'], 'placeholder' => __($input['name'], 'fluentformpro'), 'label' => __($input['name'], 'fluentformpro'), 'required' => false, 'tips' => __($supportedFormats[$input['type']], 'fluentformpro'), 'component' => 'value_text' ]; } } else { if (Arr::exists($supportedFormats, $input['type'])) { $fields[] = [ 'name' => $input['name'], 'type' => $input['type'] ]; } } } } return $fields; } protected function getSupportedFormats() { return [ 'checkbox' => 'Boolean field', 'date' => 'Date field support all types of dates without d/m/Y, M/d/Y and y/m/d formats', 'email' => 'Email Field', 'multi_select' => 'Multiple Select field', 'number' => 'Number Field', 'phone_number' => 'Phone Field', 'select' => 'Single Select field', 'status' => 'Array of options and groups object', 'title' => 'Title Field', 'url' => 'URL value', 'rich_text' => 'Text/Textarea Field', ]; } public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; if (empty($feedData['list_id'])) { do_action('fluentform/integration_action_result', $feed, 'failed', 'No Valid Database Found'); return; } $subscriber = []; $allFields = $this->getFields($feedData['list_id'], true); $cls = new \stdClass(); foreach ($allFields as $field) { $name = $field['name']; $type = $field['type']; $value = ArrayHelper::get($feedData, $name); if (!empty($value)) { $subscriber['parent']['database_id'] = $feedData['list_id']; $cls->$name = new \stdClass(); if ($type == 'title' || $type == 'rich_text') { $cls->$name->$type[] = [ 'text' => [ 'content' => $value ] ]; } elseif ($type == 'select' || $type == 'status') { $cls->$name->$type = new \stdClass(); $cls->$name->$type->name = $value; } elseif ($type == 'date') { $cls->$name->$type = new \stdClass(); $cls->$name->$type->start = date_format(new \DateTime($value), 'c'); } elseif ($type == 'multi_select') { $values = []; $values[] = $value; if (strpos($value, ',') !== false) { $values = Str::separateString($value, ','); } $options = []; foreach ($values as $option) { $options[]['name'] = $option; } $cls->$name->$type = $options; } elseif ($type == 'checkbox') { if ($value == 'yes' || $value == 'true' || $value == 1) { $cls->$name->$type = true; } elseif ($value == 'no' || $value == 'false' || $value == 0) { $cls->$name->$type = false; } } elseif ($type == 'number') { $cls->$name->$type = floatval($value); } else { $cls->$name->$type = $value; } $subscriber['properties'] = $cls; } } $api = new API(); $response = $api->subscribe($subscriber); if (!is_wp_error($response)) { do_action('fluentform/integration_action_result', $feed, 'success', __('Notion feed has been successfully initialed and pushed data', 'fluentformpro')); } else { $error = $response->get_error_message(); do_action('fluentform/integration_action_result', $feed, 'failed', $error); } } } PK!/`src/Integrations/Notion/API.phpnu[clientId = FF_NOTION_CLIENT_ID; } if (defined('FF_NOTION_CLIENT_SECRET')) { $this->clientSecret = FF_NOTION_CLIENT_SECRET; } } public function makeRequest($url, $bodyArgs = null, $type = 'GET', $headers = []) { $request = []; if (empty($headers)) { $settings = get_option($this->optionKey); $accessToken = $settings['access_token']; $headers = [ 'Authorization' => 'Bearer ' . $accessToken, 'Content-Type' => 'application/json', 'Notion-Version' => '2022-06-28' ]; } if ($type == 'GET') { $request = wp_remote_get($url, [ 'headers' => $headers ]); } $bodyArgs = json_encode($bodyArgs, true); if ($type == 'POST') { $request = wp_remote_post($url, [ 'headers' => $headers, 'body' => $bodyArgs ]); } if (is_wp_error($request)) { $message = $request->get_error_message(); return new \WP_Error(423, $message); } $body = json_decode(wp_remote_retrieve_body($request), true); $code = wp_remote_retrieve_response_code($request); if ($code >= 400 && $code <= 504) { $error = 'Something went wrong'; if (isset($body['message'])) { $error = $body['message']; } return new \WP_Error(423, $error); } return $body; } public function generateAccessToken($token) { $headers = [ 'Authorization' => 'Basic ' . base64_encode($this->clientId . ':' . $this->clientSecret), 'Content-Type' => 'application/json', 'Notion-Version' => '2022-06-28' ]; $body = [ 'code' => $token, 'grant_type' => 'authorization_code', 'redirect_uri' => $this->redirect ]; $request = $this->makeRequest('https://api.notion.com/v1/oauth/token', $body, 'POST', $headers); $token = $request['access_token']; $this->authCode = $token; return $token; } public function getAccessToken() { $tokens = get_option($this->optionKey); if (!$tokens) { return false; } if (($tokens['created_at'] + $tokens['expires_in'] - 30) < time()) { // It's expired so we have to re-issue again $refreshTokens = $this->refreshToken($tokens); if (!is_wp_error($refreshTokens)) { $tokens['access_token'] = $refreshTokens['access_token']; $tokens['expires_in'] = $refreshTokens['expires_in']; $tokens['created_at'] = time(); update_option($this->optionKey, $tokens, 'no'); } else { return false; } } return $tokens['access_token']; } public function getAuthUrl() { return 'https://api.notion.com/v1/oauth/authorize?client_id=' . $this->clientId . '&response_type=code&owner=user&redirect_uri=' . $this->redirect; } public function subscribe($subscriber) { $url = 'https://api.notion.com/v1/pages/'; $response = $this->makeRequest($url, $subscriber, 'POST'); return $response; } }PK!]S)src/Integrations/OnePageCrm/Bootstrap.phpnu[logo = fluentFormMix('img/integrations/onepagecrm.png'); $this->description = "Complete your actions with the combination of Fluent Forms and OnePageCRM to collect leads and more."; $this->registerAdminHooks(); // add_filter('fluentform/notifying_async_onepagecrm', '__return_false'); add_filter( 'fluentform/get_integration_values_' . $this->integrationKey, [$this, 'resolveIntegrationSettings'], 10, 3 ); add_filter( 'fluentform/save_integration_value_' . $this->integrationKey, [$this, 'validate'], 10, 3 ); } public function resolveIntegrationSettings($settings, $feed, $formId) { $serviceName = $this->app->request->get('serviceName', ''); $serviceId = $this->app->request->get('serviceId', ''); if ($serviceName) { $settings['name'] = $serviceName; } if ($serviceId) { $settings['list_id'] = $serviceId; } return $settings; } public function validate($settings, $integrationId, $formId) { $error = false; $errors = []; foreach ($this->getFields($settings['list_id']) as $field) { if ($field['required'] && empty($settings[$field['key']])) { $error = true; $errors[$field['key']] = [__($field['label'] . ' is required', 'fluentformpro')]; } } if ($error) { wp_send_json_error([ 'message' => __('Validation Failed', 'fluentformpro'), 'errors' => $errors ], 423); } return $settings; } public function getGlobalFields($fields) { return [ 'logo' => $this->logo, 'menu_title' => __('OnePageCrm Settings', 'fluentformpro'), 'menu_description' => $this->description, 'valid_message' => __('Your OnePageCrm API Key is valid', 'fluentformpro'), 'invalid_message' => __('Your OnePageCrm API Key is not valid', 'fluentformpro'), 'save_button_text' => __('Save Settings', 'fluentformpro'), 'config_instruction' => $this->getConfigInstructions(), 'fields' => [ 'client_id' => [ 'type' => 'text', 'placeholder' => __('OnePageCrm User ID', 'fluentformpro'), 'label_tips' => __('Enter your OnePageCrm User ID', 'fluentformpro'), 'label' => __('OnePageCrm User ID', 'fluentformpro'), ], 'client_secret' => [ 'type' => 'password', 'placeholder' => __('OnePageCrm Api Key', 'fluentformpro'), 'label_tips' => __('Enter your OnePageCrm Api Key', 'fluentformpro'), 'label' => __('OnePageCrm Api Key', 'fluentformpro'), ], ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your OnePageCrm API integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect OnePageCrm', 'fluentformpro'), 'data' => [ 'client_id' => '', 'client_secret' => '', 'access_token' => '', ], 'show_verify' => true ] ]; } public function getRemoteClient() { $settings = $this->getGlobalSettings([]); return new API( $settings ); } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'client_id' => '', 'client_secret' => '', 'access_token' => '', 'status' => false, ]; return wp_parse_args($globalSettings, $defaults); } protected function getConfigInstructions() { ob_start(); ?>
    1. After logging into your OnePageCRM account and navigating to this Link and select the configuration tab.
    2. Copy the User ID and API Key to use for authentication.
    '', 'client_secret' => '', 'access_token' => '', 'status' => false ]; // Update the reCaptcha details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your settings has been updated', 'fluentformpro'), 'status' => false ], 200); } // Verify API key now try { $client = new API($settings); $result = $client->checkAuth(); if (is_wp_error($result)) { throw new \Exception($result->get_error_message(), $result->get_error_code()); } $accessToken = $client->getAccessToken(); } catch (\Exception $exception) { wp_send_json_error([ 'message' => $exception->getMessage(), 'status' => false ], $exception->getCode()); } $integrationSettings = [ 'client_id' => sanitize_text_field($settings['client_id']), 'client_secret' => sanitize_text_field($settings['client_secret']), 'access_token' => $accessToken['access_token'], 'status' => true ]; update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your OnePageCRM api key has been verified and successfully set', 'fluentformpro'), 'status' => true ], 200); } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => $this->title . ' Integration', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-onepagecrm-settings'), 'configure_message' => __('OnePageCRM is not configured yet! Please configure your OnePageCRM api first', 'fluentformpro'), 'configure_button_text' => __('Set OnePageCRM API', 'fluentformpro') ]; return $integrations; } public function getIntegrationDefaults($settings, $formId) { $listId = $this->app->request->get('serviceId'); return [ 'name' => '', 'list_id' => $listId, 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { $fieldSettings = [ 'fields' => [ [ 'key' => 'name', 'label' => __('Feed Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'list_id', 'label' => __('OnePageCRM Services', 'fluentformpro'), 'placeholder' => __('Select OnePageCRM Service', 'fluentformpro'), 'required' => true, 'component' => 'refresh', 'options' => $this->getLists() ], ], 'button_require_list' => false, 'integration_title' => $this->title ]; $listId = $this->app->request->get('serviceId', ArrayHelper::get($settings, 'list_id')); if ($listId) { $fields = $this->getFields($listId); if (empty($fields)) { wp_send_json_error([ 'message' => __("The selected service doesn't have any field settings.", 'fluentformpro'), ], 423); } $fields = array_merge($fieldSettings['fields'], $fields); $fieldSettings['fields'] = $fields; } $fieldSettings['fields'] = array_merge($fieldSettings['fields'], [ [ 'require_list' => false, 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow this integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => false, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable this feed', 'fluentformpro') ] ]); return $fieldSettings; } protected function getLists() { return [ 'contacts' => 'Contact', 'deals' => 'Deal', 'predefined_items' => 'Predefined Item', 'notes' => 'Note', 'actions' => 'Action' ]; } public function getMergeFields($list, $listId, $formId) { return false; } public function getFields($listId) { if (!$this->isConfigured()) { return false; } $url = 'https://app.onepagecrm.com/api/v3/'; $mergedFields = []; switch ($listId) { case 'contacts': $mergedFields = [ [ 'key' => 'title', 'placeholder' => __('Enter Title', 'fluentformpro'), 'label' => __('Title', 'fluentformpro'), 'required' => false, 'tips' => __('Title is a select type field.', 'fluentformpro'), 'component' => 'select', 'options' => [ 'Mr' => __('Mr', 'fluentformpro'), 'Mrs' => __('Mrs', 'fluentformpro'), 'Ms' => __('Ms', 'fluentformpro') ] ], [ 'key' => 'first_name', 'placeholder' => __('Enter First Name', 'fluentformpro'), 'label' => __('First Name', 'fluentformpro'), 'required' => false, 'tips' => __('First Name is a required string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'last_name', 'placeholder' => __('Enter Last Name', 'fluentformpro'), 'label' => __('Last Name', 'fluentformpro'), 'required' => true, 'tips' => __('Last Name is a required string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'job_title', 'placeholder' => __('Enter Job Title', 'fluentformpro'), 'label' => __('Job Title', 'fluentformpro'), 'required' => false, 'tips' => __('Job Title is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'starred', 'label' => __('Starred', 'fluentformpro'), 'required' => false, 'tips' => __('Starred is a bool type field.', 'fluentformpro'), 'component' => 'radio_choice', 'options' => [ 'true' => __('yes', 'fluentformpro'), 'false' => __('no', 'fluentformpro') ] ], [ 'key' => 'company_name', 'placeholder' => __('Enter Company Name', 'fluentformpro'), 'label' => __('Company Name', 'fluentformpro'), 'required' => true, 'tips' => __('Company Name is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'urls_type', 'placeholder' => __('Select URL Type', 'fluentformpro'), 'label' => __('Select URL Type', 'fluentformpro'), 'required' => false, 'tips' => __('URL is a select type field.', 'fluentformpro'), 'component' => 'select', 'options' => [ 'website' => __('Website', 'fluentformpro'), 'blog' => __('Blog', 'fluentformpro'), 'twitter' => __('Twitter', 'fluentformpro'), 'linkedin' => __('Linkedin', 'fluentformpro'), 'xing' => __('Xing', 'fluentformpro'), 'facebook' => __('Facebook', 'fluentformpro'), 'google_plus' => __('Google Plus', 'fluentformpro'), 'other' => __('Other', 'fluentformpro') ] ], [ 'key' => 'urls_value', 'placeholder' => __('Enter URL', 'fluentformpro'), 'label' => __('Enter URL', 'fluentformpro'), 'required' => false, 'tips' => __('URL is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'phones_type', 'placeholder' => __('Select Phone Type', 'fluentformpro'), 'label' => __('Select Phone Type', 'fluentformpro'), 'required' => false, 'tips' => __('Phone is a select type field.', 'fluentformpro'), 'component' => 'select', 'options' => [ 'work' => __('Work', 'fluentformpro'), 'mobile' => __('Mobile', 'fluentformpro'), 'home' => __('Home', 'fluentformpro'), 'direct' => __('Direct', 'fluentformpro'), 'fax' => __('Fax', 'fluentformpro'), 'skype' => __('Skype', 'fluentformpro'), 'company' => __('Company', 'fluentformpro'), 'other' => __('Other', 'fluentformpro') ] ], [ 'key' => 'phones_value', 'placeholder' => __('Enter Phone', 'fluentformpro'), 'label' => __('Enter Phone', 'fluentformpro'), 'required' => false, 'tips' => __('Phone is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'emails_type', 'placeholder' => __('Select Email', 'fluentformpro'), 'label' => __('Select Email', 'fluentformpro'), 'required' => false, 'tips' => __('Email is a select type field.', 'fluentformpro'), 'component' => 'select', 'options' => [ 'work' => __('Work', 'fluentformpro'), 'home' => __('Home', 'fluentformpro'), 'other' => __('Other', 'fluentformpro') ] ], [ 'key' => 'emails_value', 'placeholder' => __('Enter Email', 'fluentformpro'), 'label' => __('Enter Email', 'fluentformpro'), 'required' => false, 'tips' => __('Email is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'address_address', 'placeholder' => __('Enter Address', 'fluentformpro'), 'label' => __('Enter Address', 'fluentformpro'), 'required' => false, 'tips' => __('Address is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'address_city', 'placeholder' => __('Enter City', 'fluentformpro'), 'label' => __('Enter City', 'fluentformpro'), 'required' => false, 'tips' => __('City is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'address_state', 'placeholder' => __('Enter State', 'fluentformpro'), 'label' => __('Enter State', 'fluentformpro'), 'required' => false, 'tips' => __('State is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'address_zip_code', 'placeholder' => __('Enter Zip Code', 'fluentformpro'), 'label' => __('Enter Zip Code', 'fluentformpro'), 'required' => false, 'tips' => __('Zip Code is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'address_country_code', 'placeholder' => __('Enter Country Code', 'fluentformpro'), 'label' => __('Enter Country Code', 'fluentformpro'), 'required' => false, 'tips' => __('Country Code is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'address_type', 'placeholder' => __('Enter Address Type', 'fluentformpro'), 'label' => __('Enter Address Type', 'fluentformpro'), 'required' => false, 'tips' => __('Address Type is a string type field.', 'fluentformpro'), 'component' => 'select', 'options' => [ 'work' => __('Work', 'fluentformpro'), 'home' => __('Home', 'fluentformpro'), 'billing' => __('Billing', 'fluentformpro'), 'delivery' => __('Delivery', 'fluentformpro'), 'other' => __('Other', 'fluentformpro') ] ], [ 'key' => 'contactKey_status', 'placeholder' => __('Select Status', 'fluentformpro'), 'label' => __('Select Status', 'fluentformpro'), 'required' => false, 'tips' => __('Status is a select type field.', 'fluentformpro'), 'component' => 'select', 'options' => [ 'lead' => __('Lead', 'fluentformpro'), 'prospect' => __('Prospect', 'fluentformpro'), 'trial' => __('Trial', 'fluentformpro'), 'customer' => __('Customer', 'fluentformpro'), 'inactive' => __('Inactive', 'fluentformpro'), 'general' => __('General', 'fluentformpro'), 'partner' => __('Partner', 'fluentformpro') ] ], [ 'key' => 'lead_source_id', 'placeholder' => __('Select Lead Source', 'fluentformpro'), 'label' => __('Select Lead Source', 'fluentformpro'), 'required' => false, 'tips' => __('Lead Source is a select type field.', 'fluentformpro'), 'component' => 'select', 'options' => [ 'advertisement' => __('Advertisement', 'fluentformpro'), 'email_web' => __('Email or Web', 'fluentformpro'), 'list_generation' => __('List Generation', 'fluentformpro'), 'partner' => __('Partner', 'fluentformpro'), 'affiliate' => __('Affiliate', 'fluentformpro'), 'seminar' => __('Seminar', 'fluentformpro'), 'social' => __('Social', 'fluentformpro'), 'tradeshow' => __('Tradeshow', 'fluentformpro'), 'word_of_mouth' => __('Word of mouth', 'fluentformpro'), 'other' => __('Other', 'fluentformpro') ] ], [ 'key' => 'background', 'placeholder' => __('Write Background', 'fluentformpro'), 'label' => __('Write Background', 'fluentformpro'), 'required' => false, 'tips' => __('Background is a string type field.', 'fluentformpro'), 'component' => 'value_text' ] ]; $url = $url . '/custom_fields?per_page=100'; $customFields = $this->getCustomFields($url); $mergedFields = array_merge($mergedFields, $customFields); break; case 'deals': $mergedFields = [ [ 'key' => 'dealKey_name', 'placeholder' => __('Enter Deal Name', 'fluentformpro'), 'label' => __('Deal Name', 'fluentformpro'), 'required' => true, 'tips' => __('Deal Name is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'text', 'placeholder' => __('Enter Deal Details', 'fluentformpro'), 'label' => __('Deal Details', 'fluentformpro'), 'required' => false, 'tips' => __('Deal details is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'stage', 'placeholder' => __('Enter Stage', 'fluentformpro'), 'label' => __('Stage Number', 'fluentformpro'), 'required' => false, 'tips' => __('Stage Number is a int type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'expected_close_date', 'placeholder' => __('Enter Expected Close Date', 'fluentformpro'), 'label' => __('Expected Close Date', 'fluentformpro'), 'required' => false, 'tips' => __('Expected Close Date is a date type field.', 'fluentformpro'), 'component' => 'datetime' ], [ 'key' => 'close_date', 'placeholder' => __('Enter Close Date', 'fluentformpro'), 'label' => __('Close Date', 'fluentformpro'), 'required' => false, 'tips' => __('Close Date is a date type field.', 'fluentformpro'), 'component' => 'datetime' ], [ 'key' => 'date', 'placeholder' => __('Enter Creation Date', 'fluentformpro'), 'label' => __('Creation Date', 'fluentformpro'), 'required' => false, 'tips' => __('creation Date is a date type field.', 'fluentformpro'), 'component' => 'datetime' ], [ 'key' => 'dealKey_status', 'placeholder' => __('Select status of the deal', 'fluentformpro'), 'label' => __('Status', 'fluentformpro'), 'required' => false, 'tips' => __('Status is a select type field.', 'fluentformpro'), 'component' => 'select', 'options' => [ 'pending' => __('Pending', 'fluentformpro'), 'won' => __('Won', 'fluentformpro'), 'lost' => __('Lost', 'fluentformpro') ] ], ]; $userFields = $this->getUsers(); $mergedFields[] = $userFields; break; case 'predefined_items': $mergedFields = [ [ 'key' => 'itemKey_name', 'placeholder' => __('Enter Item Name', 'fluentformpro'), 'label' => __('Item Name', 'fluentformpro'), 'required' => true, 'tips' => __('Item Name is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'description', 'placeholder' => __('Enter Item Description', 'fluentformpro'), 'label' => __('Item Description', 'fluentformpro'), 'required' => false, 'tips' => __('Item Description is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'price', 'placeholder' => __('Enter Item Price', 'fluentformpro'), 'label' => __('Item Price', 'fluentformpro'), 'required' => true, 'tips' => __('Item Price is a int type field.', 'fluentformpro'), 'component' => 'value_text' ] ]; break; case 'notes': $mergedFields = [ [ 'key' => 'text', 'placeholder' => __('Enter Note Details', 'fluentformpro'), 'label' => __('Note Details', 'fluentformpro'), 'required' => true, 'tips' => __('Item Name is a string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'Date', 'placeholder' => __('Enter Notes Date', 'fluentformpro'), 'label' => __('Date', 'fluentformpro'), 'required' => false, 'tips' => __('Date is a date type field.', 'fluentformpro'), 'component' => 'datetime' ] ]; $userFields = $this->getUsers(); $mergedFields[] = $userFields; break; case 'actions': $mergedFields = [ [ 'key' => 'actionKey_status', 'placeholder' => __('Select Action Status', 'fluentformpro'), 'label' => __('Action Status', 'fluentformpro'), 'required' => true, 'tips' => __('Action Status is a select type field.', 'fluentformpro'), 'component' => 'select', 'options' => [ 'asap' => 'ASAP', 'date' => 'Date', 'date_time' => 'Date Time', 'waiting' => 'Waiting', 'queued' => 'Queued', 'queued_with_date' => 'Queued With Date', 'done' => 'Done' ] ], [ 'key' => 'text', 'placeholder' => __('Enter Action Details', 'fluentformpro'), 'label' => __('Action Details', 'fluentformpro'), 'required' => false, 'tips' => __('Action Details is string type field.', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'date', 'placeholder' => __('Enter Action Date', 'fluentformpro'), 'label' => __('Action Date', 'fluentformpro'), 'required' => false, 'tips' => __('Action Date is date type field. Due date for the action (status must be one of Date, Date Time or Queued with date)', 'fluentformpro'), 'component' => 'datetime' ] ]; $userFields = $this->getUsers(); $mergedFields[] = $userFields; break; } return $mergedFields; } protected function getUsers() { $client = $this->getRemoteClient(); try { $lists = $client->makeRequest('https://app.onepagecrm.com/api/v3/contacts', null); if (!$lists) { return []; } } catch (\Exception $exception) { return false; } if (is_wp_error($lists)) { $error = $lists->get_error_message(); $code = $lists->get_error_code(); wp_send_json_error([ 'message' => __($error, 'fluentformpro') ], $code); } $data = [ 'key' => 'contact_id', 'placeholder' => __('Select the User', 'fluentformpro'), 'label' => __('Contact Name', 'fluentformpro'), 'required' => true, 'tips' => __('Select the User', 'fluentformpro'), 'component' => 'select', ]; $data['options'] = []; foreach ($lists['data']['contacts'] as $contact) { $data['options'] += [$contact['contact']['id'] => $contact['contact']['first_name'] . ' ' . $contact['contact']['last_name']]; } return $data; } protected function getCustomFields($url) { $client = $this->getRemoteClient(); try { $lists = $client->makeRequest($url, null); if (!$lists) { return []; } } catch (\Exception $exception) { return false; } if (is_wp_error($lists)) { $error = $lists->get_error_message(); $code = $lists->get_error_code(); wp_send_json_error([ 'message' => __($error, 'fluentformpro') ], $code); } $customFields = []; foreach ($lists['data']['custom_fields'] as $customField) { $field = $customField['custom_field']; if ($field['type'] == 'multiple_choice' || $field['type'] == 'select_box') { $data = [ 'key' => 'custom_' . $field['id'] . '_multiple_choice_' . $field['name'], 'placeholder' => __($field['name'], 'fluentformpro'), 'label' => __($field['name'], 'fluentformpro'), 'required' => false, 'tips' => __($field['name'] . ' is a ' . $field['type'] . ' type of field.', 'fluentformpro'), 'component' => 'select' ]; $choices = ArrayHelper::get($field, 'choices'); $options = []; foreach ($choices as $choice) { $options[$choice] = $choice; } $data['options'] = $options; } elseif ($field['type'] == 'anniversary' || $field['type'] == 'date') { $data = [ 'key' => 'custom_' . $field['id'] . '_date_' . $field['name'], 'label' => __($field['name'], 'fluentformpro'), 'required' => false, 'tips' => __($field['name'] . ' is a ' . $field['type'] . ' type of field.', 'fluentformpro'), 'component' => 'datetime', ]; } else { $data = [ 'key' => 'custom_' . $field['id'] . '_normal_' . $field['name'], 'placeholder' => __($field['name'], 'fluentformpro'), 'label' => __($field['name'], 'fluentformpro'), 'required' => false, 'tips' => __($field['name'] . ' is a ' . $field['type'] . ' type of field.', 'fluentformpro'), 'component' => 'value_text' ]; } $customFields[] = $data; } return $customFields; } protected function getAllFields($listId) { $fields = $this->getFields($listId); $allFields = []; foreach ($fields as $field) { $keyData = []; $keyData['key'] = $field['key']; if ($field['required']) { $keyData['required'] = $field['required']; $allFields[] = $keyData; } else { $keyData['required'] = 0; $allFields[] = $keyData; } } return $allFields; } public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; $subscriber = []; $subscriber['list_id'] = $feedData['list_id']; $subscriber['attributes'] = []; $fieldContainer = []; $fieldFormatted['address_list'] = []; $fieldFormatted['custom_fields'] = []; $customFieldContainer = []; $normalTemp = []; $customTemp = []; $addressTemp = []; $allFields = $this->getAllFields($feedData['list_id']); foreach ($allFields as $field) { if (!empty($feedData[$field['key']])) { $fieldContainer[$field['key']] = ArrayHelper::get($feedData, $field['key']); } } foreach ($fieldContainer as $key => $value) { if (strpos($key, 'urls') !== false || strpos($key, 'phones') !== false || strpos($key, 'emails') !== false || strpos($key, 'address') !== false) { $arr = explode('_', $key, 2); $keyName = $arr[0]; $fieldName = $arr[1]; if ($keyName == 'address') { $addressTemp[$fieldName] = $value; } else { if ($arr[1] == 'type') { $normalTemp[$keyName]['type'] = $value; } if ($arr[1] == 'value') { $normalTemp[$keyName]['value'] = $value; } } unset($fieldContainer[$key]); } if (strpos($key, 'date') !== false && strpos($key, 'custom') == false) { $value = date('Y-m-d', strtotime($value)); $fieldFormatted[$key] = $value; unset($fieldContainer[$key]); } if (strpos($key, 'custom') !== false) { $arr = explode('_', $key); $fieldId = $arr[1]; $fieldType = $arr[2]; if ($fieldType == 'date') { $value = date('Y-m-d', strtotime($value)); } $customTemp['custom_field']['id'] = $fieldId; $customTemp['value'] = $value; $customFieldContainer[] = $customTemp; unset($fieldContainer[$key]); } if (strpos($key, 'status') !== false) { $fieldFormatted['status'] = $value; unset($fieldContainer[$key]); } if (strpos($key, 'contactKey') !== false || strpos($key, 'dealKey') !== false || strpos($key, 'itemKey') !== false) { $arr = explode('_', $key, 2); $keyName = $arr[1]; $fieldFormatted[$keyName] = $value; unset($fieldContainer[$key]); } } $fieldFormatted += $normalTemp; if (empty($fieldFormatted['address_list'])) { unset($fieldFormatted['address_list']); } else { $fieldFormatted['address_list'][] = $addressTemp; } if (!empty($customFieldContainer)) { $fieldFormatted['custom_fields'] += $customFieldContainer; } $fieldContainer += $fieldFormatted; $subscriber['attributes'] = $fieldContainer; $client = $this->getRemoteClient(); $response = $client->subscribe($subscriber); if (!is_wp_error($response)) { do_action('fluentform/integration_action_result', $feed, 'success', __('OnePageCRM feed has been successfully initiated and pushed data', 'fluentformpro')); } else { $errorMessage = $response->get_error_message(); $errors = $response->get_error_data(); if ($errors) { if (is_array($errors)) { $stringifyErrorMessages = implode('', $errors); $errors = $stringifyErrorMessages; } $errorMessage = $errorMessage . '. ' . $errors; } do_action('fluentform/integration_action_result', $feed, 'failed', $errorMessage); } } } PK!1]8#src/Integrations/OnePageCrm/API.phpnu[clientId = $settings['client_id']; $this->clientSecret = $settings['client_secret']; $this->accessToken = 'Basic ' . base64_encode($settings['client_id'] . ':' . $settings['client_secret']); } public function checkAuth() { return $this->makeRequest($this->url . 'bootstrap'); } public function getAccessToken() { return [ 'access_token' => $this->accessToken, ]; } public function makeRequest($url, $bodyArgs = [], $type = 'GET') { $accessToken = $this->getAccessToken(); $request = []; if ($type == 'GET') { $request = wp_remote_get($url, [ 'headers' => [ 'Content-Type' => 'application/json', 'Accept' => 'application/json', 'Authorization' => $accessToken['access_token'], ] ]); } if ($type == 'POST') { $request = wp_remote_post($url, [ 'headers' => [ 'Content-Type' => 'application/json', 'Accept' => 'application/json', 'Authorization' => $accessToken['access_token'], ], 'body' => $bodyArgs ]); } $body = wp_remote_retrieve_body($request); $body = \json_decode($body, true); $code = wp_remote_retrieve_response_code($request); if ($code == 200 || $code == 201) { return $body; } else { return new \WP_Error($code, $body['error_message'], $body['errors']); } } public function subscribe($subscriber) { $url = 'https://app.onepagecrm.com/api/v3/' . $subscriber['list_id']; $post = \json_encode($subscriber['attributes'], true); return $this->makeRequest($url, $post, 'POST'); } } PK!h4jj(src/Integrations/Pipedrive/Bootstrap.phpnu[logo = fluentFormMix('img/integrations/pipedrive.png'); $this->description = 'By connecting Pipedrive with Fluent Forms, you can connect and organize leads and more.'; $this->registerAdminHooks(); // add_filter('fluentform/notifying_async_pipedrive', '__return_false'); add_filter( 'fluentform/get_integration_values_pipedrive', [$this, 'resolveIntegrationSettings'], 100, 3 ); add_filter('fluentform/save_integration_value_' . $this->integrationKey, [$this, 'validate'], 10, 3); } public function getGlobalFields($fields) { return [ 'logo' => $this->logo, 'menu_title' => __('Pipedrive API Settings', 'fluentformpro'), 'menu_description' => __('Pipedrive is a deal-driven customer relationship management CRM solution that also works as an account-management tool with the ability to assist with marketing and the entire sales process. If you don\'t have an Pipedrive account, you can sign up for one here.', 'fluentformpro'), 'valid_message' => __('Your Pipedrive API token is valid', 'fluentformpro'), 'invalid_message' => __('Your Pipedrive API token is invalid', 'fluentformpro'), 'save_button_text' => __('Verify Pipedrive API Token', 'fluentformpro'), 'config_instruction' => $this->getConfigInstructions(), 'fields' => [ 'apiToken' => [ 'type' => 'text', 'placeholder' => __('Enter Your API token', 'fluentformpro'), 'label_tips' => __("Enter your Pipedrive API token, if you do not have follow-up upper instructions.", 'fluentformpro'), 'label' => __('Pipedrive API Token', 'fluentformpro'), ], ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your Pipedrive API integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect Pipedrive', 'fluentformpro'), 'data' => [ 'apiToken' => '' ], 'show_verify' => true ] ]; } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'apiToken' => '', 'status' => '' ]; return wp_parse_args($globalSettings, $defaults); } public function getIntegrationDefaults($settings, $formId) { $name = $this->app->request->get('serviceName', ''); $serviceId = $this->app->request->get('serviceId', ''); return [ 'name' => $name, 'list_id' => $serviceId, 'other_fields' => [ [ 'item_value' => '', 'label' => '' ] ], 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'enabled' => true ]; } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => $this->title . ' Integration', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-pipedrive-settings'), 'configure_message' => __('Pipedrive is not configured yet! Please configure your Pipedrive api token first', 'fluentformpro'), 'configure_button_text' => __('Set Pipedrive API Token', 'fluentformpro') ]; return $integrations; } public function getSettingsFields($settings, $formId) { $fieldSettings = [ 'fields' => [ [ 'key' => 'name', 'label' => __('Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'list_id', 'label' => __('Services', 'fluentformpro'), 'placeholder' => __('Choose Service', 'fluentformpro'), 'required' => true, 'component' => 'refresh', 'options' => $this->getServices() ], ], 'button_require_list' => false, 'integration_title' => $this->title ]; $serviceId = $this->app->request->get( 'serviceId', ArrayHelper::get($settings, 'list_id') ); if ($serviceId) { $fields = $this->getFields($serviceId); $fields = array_merge($fieldSettings['fields'], $fields); $fieldSettings['fields'] = $fields; } $fieldSettings['fields'] = array_merge($fieldSettings['fields'], [ [ 'require_list' => false, 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow this integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => false, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable This feed', 'fluentformpro') ] ]); return $fieldSettings; } public function saveGlobalSettings($settings){ if (!$settings['apiToken']) { $integrationSettings = [ 'apiToken' => '', 'status' => false ]; // Update the details with access token update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_error([ 'message' => __('API token in required.', 'fluentformpro'), 'status' => false, 'require_load' => true ], 404); } try { $settings['status'] = false; update_option($this->optionKey, $settings, 'no'); $api = $this->getApi($settings['apiToken']); $auth = $api->auth_test(); if ($auth['success']) { $settings['status'] = true; update_option($this->optionKey, $settings, 'no'); wp_send_json_success([ 'status' => true, 'message' => __('Your settings has been updated!', 'fluentformpro') ], 200); } throw new \Exception(__('Invalid Api Token','fluentformpro'), 401); } catch (\Exception $e) { wp_send_json_error([ 'status' => false, 'message' => $e->getMessage() ], $e->getCode()); } } public function getMergeFields($list, $listId, $formId) { return []; } public function resolveIntegrationSettings($settings, $feed, $formId) { $serviceName = $this->app->request->get('serviceName', ''); $serviceId = $this->app->request->get('serviceId', ''); if ($serviceName) { $settings['name'] = $serviceName; } if ($serviceId) { $settings['list_id'] = $serviceId; } return $settings; } protected function getServices() { return [ 'persons' => 'Person', 'leads' => 'Leads', 'organizations' => 'Organization', 'deals' => 'Deal', 'activities' => 'Activity', ]; } public function getFields($serviceId) { if ($serviceId === 'leads') { $fieldId = $this->makeFieldEndpoint('deals'); } else { $fieldId = $this->makeFieldEndpoint($serviceId); } $api = $this->getApi(); $response = $api->getFields($fieldId); // if got error or integration status is false exit with false if (is_wp_error($response) || !$response['success']) { return false; } $fields = array(); if ($response['data']) { $others_fields = array(); foreach ($response['data'] as $field) { // if field is not valid skip this field if (!$this->isFieldValid($field, $serviceId)) { continue; } if ($this->filterField($field) && !ArrayHelper::get($field, 'edit_flag')) { if (in_array($field['key'], ['name', 'status'])) { $field['key'] = 'field_' . $field['key']; } $data = array( 'key' => $field['key'], 'placeholder' => __($field['name'], 'fluentformpro'), 'label' => __($field['name'], 'fluentformpro'), 'data_type' => $field['field_type'], 'required' => false, 'tips' => __('Enter ' . $field['name'] . ' value or choose form input provided by shortcode.', 'fluentformpro'), 'component' => 'value_text' ); if ($this->isRequiredField($serviceId, $field)) { $data['required'] = true; $data['tips'] = __($field['name'] . ' is a required field. Enter value or choose form input provided by shortcode.', 'fluentformpro'); } if ($field['key'] === 'value') { $data['tips'] = __('Amount value. Currency is pipedrive default currency.', 'fluentformpro'); } if ($this->isSelectField($field)) { $data['component'] = 'select'; $data['tips'] = __("Choose " . $field['name'] . " type in select list.", 'fluentformpro'); $data_options = array(); if ($field['field_type'] === 'user') { $users = $api->getUsers(); if (is_wp_error($users) || !$users['success']) { continue; } if ($users['data']) { $data_options = $this->formatArray($users['data']); } } elseif (in_array($field['field_type'], ['org', 'people'])) { $people_options = $orgs_options = []; $data['tips'] .= __("
    If list empty first create " . $field['name'] ." in you pipedrive dashboard.", 'fluentformpro'); $orgs = $api->getOrganizations(); if (is_wp_error($orgs) || !$orgs['success']) { continue; } if ($orgs['data']) { $orgs_options = $this->formatArray($orgs['data']); } $people = $api->getPerson(); if (is_wp_error($people) || !$people['success']) { continue; } if ($people['data']) { $people_options = $this->formatArray($people['data']); } if ($field['field_type'] === 'people') { if ($orgs_options && empty($people_options)) { $data['required'] = false; } $data_options = $people_options; } if ($field['field_type'] === 'org') { if ($people_options && empty($orgs_options)) { $data['required'] = false; } if ($people_options && !empty($orgs_options)) { $data['required'] = false; } $data_options = $orgs_options; } } else { $data_options = $this->formatArray($field['options'], 'options'); } $data['options'] = $data_options; } if ($field['field_type'] == 'text') { $data['component'] = 'value_textarea'; } if ($serviceId === 'leads' && $field['key'] === 'value') { $data['required'] = false; $fields[] = $data; $fields = $this->getLeadExtraFields($fields); } elseif ($serviceId === 'activities' && $field['key'] === 'type') { $fields[] = $data; $fields[] = [ 'key' => 'due_date', 'placeholder' => __('Enter Lead Title or choose shortcode', 'fluentformpro'), 'label' => __('Activity Due Date', 'fluentformpro'), 'required' => false, 'tips' => __('The due date of the activity. In ISO 8601 format: YYYY-MM-DD.', 'fluentformpro'), 'component' => 'datetime' ]; } else { $fields[] = $data; } } else { if ($this->isOthersfield($field)) { $others_fields[$field['key']] = $field['name']; } } } if (!empty($others_fields)) { $fields[] = [ 'key' => 'other_fields', 'require_list' => false, 'required' => false, 'label' => __('Other Fields', 'fluentformpro'), 'tips' => __('Select which Fluent Forms fields pair with their respective pipedrive modules fields.
    Field value must be string type.', 'fluentformpro'), 'component' => 'dropdown_many_fields', 'options' => $others_fields ]; } } return $fields; } protected function getLeadExtraFields($fields) { $api = $this->getApi(); $currencies = []; $response = $api->getCurrencies(); if (!is_wp_error($response) && $response['success'] && $response['data']) { $currencies = $this->formatArray($response['data'], 'currencies'); } $fields[] = [ 'key' => 'currency', 'placeholder' => __('Currency', 'fluentformpro'), 'label' => __('Currency Code', 'fluentformpro'), 'required' => false, 'tips' => __('Choose witch country currency amount value is.', 'fluentformpro'), 'component' => 'select', 'options' => $currencies ]; $fields[] = [ 'key' => 'expected_close_date', 'placeholder' => __('Enter Lead Title or choose shortcode', 'fluentformpro'), 'label' => __('Expected Close Date', 'fluentformpro'), 'required' => false, 'tips' => __('The date of when the deal which will be created from the lead is expected to be closed. In ISO 8601 format: YYYY-MM-DD.', 'fluentformpro'), 'component' => 'datetime' ]; return $fields; } protected function formatArray($items = [], $from = '') { $newArray = []; foreach ($items as $item) { if ($from === 'currencies') { // make country currencies options for dropdown $newArray[$item['code']] = $item['name']; } elseif ($from === 'lead_keys') { // make leads service keys for validation and get data from feed settings $data = [ 'key' => $item['key'], 'feed_key' => $item['key'], 'label' => $item['label'], 'data_type' => '', 'required' => $item['required'] ]; if (isset($item['data_type'])) { $data['data_type'] = $item['data_type']; } array_push($newArray, $data); } elseif ($from === 'options') { // format other field options $newArray[$item['id']] = $item['label']; } else { // make other select field options $newArray[$item['id']] = $item['name']; } } return $newArray; } public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; $list_id = $feedData['list_id']; if (!$list_id) { return false; } $keys = $this->getAllKeys($list_id); $postData = array(); foreach ($keys as $key){ if (ArrayHelper::get($key, 'other_fields') && !empty($feedData['other_fields'])) { foreach ($feedData['other_fields'] as $other_field) { if ( !empty($other_field['item_value']) && !empty($other_field['label']) && $other_field['label'] === $key['feed_key'] ) { $postData[$other_field['label']] = $other_field['item_value']; } } continue; } if ($key['required'] && empty($feedData[$key['feed_key']])) { do_action('fluentform/integration_action_result', $feed, 'failed', __('Failed to insert Pipedrive feed. Details : ' . $key['label'] . ' empty', 'fluentformpro')); return false; } if (!empty($feedData[$key['feed_key']])) { $postData[$key['key']] = $feedData[$key['feed_key']]; } } if ($list_id === 'leads') { $postData['value'] = [ 'amount' => intval(ArrayHelper::get($postData, 'value')), 'currency' => ArrayHelper::get($postData,'currency') ]; ArrayHelper::forget($postData, ['currency']); if ($orgId = ArrayHelper::get($postData, 'org_id')) { $postData['organization_id'] = intval($orgId); ArrayHelper::forget($postData, ['org_id']); } if ($person = ArrayHelper::get($postData, 'person_id')) { $postData['person_id'] = intval($person); } if ($owner = ArrayHelper::get($postData, 'user_id')) { $postData['owner_id'] = intval($owner); ArrayHelper::forget($postData, ['user_id']); } if ($date = ArrayHelper::get($postData, 'expected_close_date')) { $postData['expected_close_date'] = date('Y-m-d', strtotime($date)); } } $postData = apply_filters('fluentform/integration_data_' . $this->integrationKey, $postData, $feed, $entry); if ($list_id === 'activities') { if ($date = ArrayHelper::get($postData,'due_date')) { $postData['due_date'] = date('Y-m-d', strtotime($date)); } } $api = $this->getApi(); $response = $api->insertServiceData($feedData['list_id'], $postData); if (is_wp_error($response)) { // it's failed do_action('fluentform/integration_action_result', $feed, 'failed', __('Failed to insert Pipedrive feed. Details : ', 'fluentformpro') . $response->get_error_message()); } else { // It's success do_action('fluentform/integration_action_result', $feed, 'success', __('Pipedrive feed has been successfully inserted ', 'fluentformpro') . $list_id . __(' data.', 'fluentformpro')); } } public function validate($settings, $integrationId, $formId) { $error = false; $errors = array(); $fields = $this->getAllKeys($settings['list_id']); if ($fields) { foreach ($fields as $field){ if ($field['required'] && empty($settings[$field['feed_key']])) { $error = true; $msg = __($field['label'].' is required.', 'fluentformpro'); if ($field['data_type'] === 'org') { $msg .= __(' First Create Organization In your Integration.', 'fluentformpro'); } $errors[$field['feed_key']] = [$msg]; } } } if ($error){ wp_send_json_error([ 'message' => __('Validation Failed', 'fluentformpro'), 'errors' => $errors ], 423); } return $settings; } protected function getAllKeys($serviceId) { $fields = $this->getFields($serviceId); $keys = []; foreach ($fields as $field) { $data = [ 'key' => $field['key'], 'feed_key' => $field['key'], 'label' => $field['label'], 'data_type' => ArrayHelper::get($field, 'data_type'), 'required' => $field['required'] ]; if (in_array($field['key'], ['field_name', 'field_status'])) { $data['key'] = (explode("_",$field['key']))[1]; } if ($field['key'] == 'other_fields' && $options = ArrayHelper::get($field, 'options')) { $data['other_fields'] = true; foreach ($options as $key => $value) { $data = [ 'key' => $key, 'feed_key' => $key, 'label' => $value, 'other_fields' => true, 'data_type' => '', 'required' => false ]; $keys[] = $data; } } else { $keys[] = $data; } } return $keys; } protected function isFieldValid($field, $serviceId) { // if bulk edit not set skip this field if (!isset($field['bulk_edit_allowed']) || !ArrayHelper::get($field, 'bulk_edit_allowed')) { return false; } //skip leads status field if ($serviceId === 'leads' && $field['key'] === 'status') { return false; } // if field data type is data/stage/varchar_options/lead/deal skip this field if ( in_array($field['field_type'], ['date', 'stage', 'varchar_options', 'lead', 'deal', 'set']) || $field['key'] === 'done' ) { return false; } // if field type is select but not property options skit this field if (in_array($field['field_type'], ['enum', 'visible_to']) && !isset($field['options'])) { return false; } return true; } protected function filterField($field) { if ( ($field['mandatory_flag'] && $field['bulk_edit_allowed']) || ($field['bulk_edit_allowed'] && ( in_array($field['field_type'], ['enum', 'visible_to', 'text', 'org']) || $field['key'] === 'value' ) ) || ArrayHelper::get($field, 'important_flag') ) { return true; } return false; } protected function isSelectField($field) { if ( ( in_array($field['field_type'], ['enum', 'visible_to', 'status']) && ArrayHelper::get($field, 'options') ) || in_array($field['field_type'], ['user', 'people', 'org']) ) { return true; } return false; } protected function isRequiredField($serviceId, $field) { switch ($serviceId) { case 'organizations': case 'persons': return ArrayHelper::get($field, 'key') == 'field_name'; case 'deals': case 'leads': return ArrayHelper::get($field, 'key') == 'title'; case 'activities': return ArrayHelper::get($field, 'key') == 'subject'; default: return false; } } protected function isOthersfield($field) { if ( ArrayHelper::get($field, 'edit_flag') && in_array($field['field_type'],['varchar', 'phone', 'text']) ) { return true; } return false; } protected function makeFieldEndpoint($serviceId) { if ($serviceId === 'activities') { $fieldId = 'activityFields'; } else { $fieldId = substr($serviceId,0,strlen($serviceId) -1) . 'Fields'; } return $fieldId; } protected function getApi($apiToken = null) { if (!$apiToken) { $apiToken = $this->getGlobalSettings([])['apiToken']; } return new PipedriveApi($apiToken); } protected function getConfigInstructions() { ob_start(); ?>

    You can get the API token manually from the Pipedrive web app by going to account name (on the top right) > Company settings > Personal preferences > API or by clicking here.

    apiToken = $api_Token; } private function getApiUrl($resource) { $parameters = []; $parameters['api_token'] = $this->apiToken; $paramString = http_build_query($parameters); return $this->apiUrl . $resource . '?' . $paramString; } public function auth_test() { return $this->make_request('leads', [], 'GET'); } public function make_request($resource, $data, $method = 'GET') { $requestApi = $this->getApiUrl($resource); $args = array( 'headers' => array( 'Content-Type' => 'application/json' ) ); if ($method == 'GET') { $response = wp_remote_get($requestApi, $args); } else if ($method == 'POST') { $args['body'] = json_encode($data); $response = wp_remote_post($requestApi, $args); } else { return (new \WP_Error(423, 'Request method could not be found')); } /* If WP_Error, die. Otherwise, return decoded JSON. */ if (is_wp_error($response)) { return (new \WP_Error(423, $response->get_error_message())); } return json_decode($response['body'], true); } public function getFields($serviceId){ return $this->make_request($serviceId, [], 'GET'); } public function getUsers(){ return $this->make_request('users', [], 'GET'); } public function getPerson() { return $this->make_request('persons', [], 'GET'); } public function getOrganizations(){ return $this->make_request('organizations', [], 'GET'); } public function getCurrencies(){ return $this->make_request('currencies', [], 'GET'); } public function insertServiceData($service_name, $data) { $response = $this->make_request($service_name, $data, 'POST'); if ($response['success']) { return $response; } $err_msg = 'Something goes wrong!'; if (is_wp_error($response)) { $err_msg = $response->get_error_message(); } if (!$response['success']) { $err_msg = $response['error'] . ' - '. $response['error_info']; } return new \WP_Error('error', $err_msg); } }PK!jG~ E E)src/Integrations/Platformly/Bootstrap.phpnu[logo = fluentFormMix('img/integrations/platformly.png'); $this->description = 'Build and grow your email subscriber list with the integration of Platformly.'; $this->registerAdminHooks(); // add_filter('fluentform/notifying_async_platformly', '__return_false'); } public function getGlobalFields($fields) { return [ 'logo' => $this->logo, 'menu_title' => __('Platformly API Settings', 'fluentformpro'), 'menu_description' => __('Platformly is an integrated email marketing, marketing automation, and small business CRM. Save time while growing your business with sales automation. Use Fluent Forms to collect customer information and automatically add it to your Platformly list. If you don\'t have a Platformly account, you can sign up for one here.', 'fluentformpro'), 'valid_message' => __('Your Platformly configuration is valid', 'fluentformpro'), 'invalid_message' => __('Your Platformly configuration is invalid', 'fluentformpro'), 'save_button_text' => __('Save Settings', 'fluentformpro'), 'fields' => [ 'apiKey' => [ 'type' => 'password', 'placeholder' => __('API Key', 'fluentformpro'), 'required' => true, 'label_tips' => __("Enter your Platformly API Key, If you do not have Please login to your Platformly account and find the API key", 'fluentformpro'), 'label' => __('Platformly API Key', 'fluentformpro'), ], 'projectId' => [ 'type' => 'number', 'placeholder' => __('Project ID', 'fluentformpro'), 'required' => true, 'label_tips' => __("Please Provide your Platformly Project ID", 'fluentformpro'), 'label' => __('Platformly Project ID', 'fluentformpro'), ], ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your Platformly API integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect Platformly', 'fluentformpro'), 'data' => [ 'apiKey' => '' ], 'show_verify' => true ] ]; } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'apiKey' => '', 'projectId' => '', 'status' => '' ]; return wp_parse_args($globalSettings, $defaults); } public function saveGlobalSettings($settings) { if (!ArrayHelper::get($settings, 'apiKey') || !ArrayHelper::get($settings, 'projectId')) { $integrationSettings = [ 'apiKey' => '', 'projectId' => '', 'status' => false ]; update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your settings has been updated', 'fluentformpro'), 'status' => false ], 200); } try { $settings['status'] = false; update_option($this->optionKey, $settings, 'no'); $api = new PlatformlyApi($settings['apiKey'], $settings['projectId']); $auth = $api->auth_test(); if (isset($auth['account_id'])) { $settings['status'] = true; update_option($this->optionKey, $settings, 'no'); wp_send_json_success([ 'status' => true, 'message' => __('Your settings has been updated!', 'fluentformpro') ], 200); } throw new \Exception('Invalid Credentials', 400); } catch (\Exception $e) { wp_send_json_error([ 'status' => false, 'message' => $e->getMessage() ], $e->getCode()); } } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => $this->title . ' Integration', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-platformly-settings'), 'configure_message' => __('Platformly is not configured yet! Please configure your Platformly API first', 'fluentformpro'), 'configure_button_text' => __('Set Platformly API', 'fluentformpro') ]; return $integrations; } public function getIntegrationDefaults($settings, $formId) { return [ 'name' => '', 'list_id' => '', 'fieldEmailAddress' => '', 'custom_field_mappings' => (object) [], 'default_fields' => (object) [], 'other_fields_mapping' => [ [ 'item_value' => '', 'label' => '' ] ], 'ip_address' => '{ip}', 'tags' => [], 'tag_ids_selection_type' => 'simple', 'tag_routers' => [], 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { return [ 'fields' => [ [ 'key' => 'name', 'label' => __('Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'list_id', 'label' => __('Platformly Segment', 'fluentformpro'), 'placeholder' => __('Select Platformly Segment', 'fluentformpro'), 'tips' => __('Select the Platformly segment you would like to add your contacts to.', 'fluentformpro'), 'component' => 'list_ajax_options', 'options' => $this->getLists() ], [ 'key' => 'custom_field_mappings', 'require_list' => true, 'label' => __('Map Fields', 'fluentformpro'), 'tips' => __('Select which Fluent Forms fields pair with their
    respective Platformly fields.', 'fluentformpro'), 'component' => 'map_fields', 'field_label_remote' => __('Platformly Field', 'fluentformpro'), 'field_label_local' => __('Form Field', 'fluentformpro'), 'primary_fileds' => [ [ 'key' => 'fieldEmailAddress', 'label' => __('Email Address', 'fluentformpro'), 'required' => true, 'input_options' => 'emails' ] ], 'default_fields' => [ array( 'name' => 'first_name', 'label' => esc_html__('First Name', 'fluentformpro'), 'required' => false ), array( 'name' => 'last_name', 'label' => esc_html__('Last Name', 'fluentformpro'), 'required' => false ), array( 'name' => 'phone', 'label' => esc_html__('Phone Number', 'fluentformpro'), 'required' => false ) ] ], [ 'key' => 'other_fields_mapping', 'require_list' => true, 'label' => __('Other Fields', 'fluentformpro'), 'tips' => __('Select which Fluent Forms fields pair, with their
    respective Platformly fields.', 'fluentformpro'), 'component' => 'dropdown_many_fields', 'field_label_remote' => __('Platformly Field', 'fluentformpro'), 'field_label_local' => __('Form Field', 'fluentformpro'), 'options' => [ 'company' => __('Company Name', 'fluentformpro'), 'address' => __('Address Line 1', 'fluentformpro'), 'address2' => __('Address Line 2', 'fluentformpro'), 'city' => __('City', 'fluentformpro'), 'state' => __('State', 'fluentformpro'), 'zip' => __('ZIP code', 'fluentformpro'), 'country' => __('Country', 'fluentformpro'), 'fax' => __('Fax', 'fluentformpro'), 'sms_number' => __('SMS Number', 'fluentformpro'), 'phone' => __('Phone', 'fluentformpro'), 'birthday' => __('Birthday', 'fluentformpro'), 'website' => __('Website', 'fluentformpro') ] ], [ 'key' => 'tags', 'require_list' => true, 'label' => __('Contact Tags', 'fluentformpro'), 'placeholder' => __('Select Tags', 'fluentformpro'), 'component' => 'selection_routing', 'simple_component' => 'select', 'routing_input_type' => 'select', 'routing_key' => 'tag_ids_selection_type', 'settings_key' => 'tag_routers', 'is_multiple' => true, 'labels' => [ 'choice_label' => __('Enable Dynamic Tag Selection', 'fluentformpro'), 'input_label' => '', 'input_placeholder' => __('Set Tag', 'fluentformpro'), ], 'options' => $this->getTags() ], [ 'key' => 'note', 'require_list' => true, 'label' => __('Note', 'fluentformpro'), 'placeholder' => __('write a note for this contact', 'fluentformpro'), 'tips' => __('You can write a note for this contact', 'fluentformpro'), 'component' => 'value_textarea' ], [ 'require_list' => true, 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow Platformly integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => true, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable This feed', 'fluentformpro') ] ], 'button_require_list' => true, 'integration_title' => $this->title ]; } protected function getLists() { $api = $this->getApiClient(); if (!$api) { return []; } $lists = $api->getLists(); $formattedLists = []; foreach ($lists as $list) { if (is_array($list)) { $formattedLists[$list['id']] = $list['name']; } } return $formattedLists; } // getting available tags protected function getTags() { $api = $this->getApiClient(); if (!$api) { return []; } $tags = $api->getTags(); $formattedLists = []; foreach ($tags as $tag) { if (is_array($tag)) { $formattedLists[strval($tag['id'])] = $tag['name']; } } return $formattedLists; } public function getMergeFields($list, $listId, $formId) { $api = $this->getApiClient(); $fields = $api->getCustomFields(); $formattedFields = []; foreach ($fields as $field) { $formattedFields['cf_' . $field['alias'] . '_' . $field['id']] = $field['name']; } return $formattedFields; } /** * Prepare Platformly forms for feed field. * * @return array */ /* * Submission Broadcast Handler */ public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; if (!is_email($feedData['fieldEmailAddress'])) { $feedData['fieldEmailAddress'] = ArrayHelper::get($formData, $feedData['fieldEmailAddress']); } if (!is_email($feedData['fieldEmailAddress'])) { do_action('fluentform/integration_action_result', $feed, 'error', __('Email is not valid for integration', 'fluentformpro')); return; } $addData = []; $addData = array_merge($addData, ArrayHelper::get($feedData, 'default_fields')); if (ArrayHelper::get($feedData, 'custom_field_mappings')) { $addData = array_merge($addData, ArrayHelper::get($feedData, 'custom_field_mappings')); } foreach (ArrayHelper::get($feedData, 'other_fields_mapping') as $item) { $addData[$item['label']] = $item['item_value']; } $tags = $this->getSelectedTagIds($feedData, $formData, 'tags'); if ($tags) { $addData['tag'] = implode(",", $tags); } $addData['segment'] = $feedData['list_id']; $addData['ip'] = $feedData['ip_address']; $addData = array_filter($addData); $addData['email'] = $feedData['fieldEmailAddress']; $addData['time'] = time(); $addData = apply_filters_deprecated( 'fluentform_integration_data_' . $this->integrationKey, [ $addData, $feed, $entry ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/integration_data_' . $this->integrationKey, 'Use fluentform/integration_data_' . $this->integrationKey . ' instead of fluentform_integration_data_' . $this->integrationKey ); $addData = apply_filters('fluentform/integration_data_' . $this->integrationKey, $addData, $feed, $entry); // Now let's prepare the data and push to Platformly $api = $this->getApiClient(); $response = $api->addContact($addData); if (!is_wp_error($response) && $response['status'] === 'success') { do_action('fluentform/integration_action_result', $feed, 'success', 'Platformly feed has been successfully initialed and pushed data'); if (ArrayHelper::get($feedData, 'note')) { $api->add_note($response["data"]["cc_id"], ArrayHelper::get($feedData, 'fieldEmailAddress'), ArrayHelper::get($feedData, 'note')); } } else { $error = is_wp_error($response) ? $response->get_error_messages() : __('API Error when submitting Data', 'fluentformpro'); do_action('fluentform/integration_action_result', $feed, 'failed', $error); } } protected function getApiClient() { $settings = get_option($this->optionKey); return new PlatformlyApi( $settings['apiKey'], $settings['projectId'] ); } } PK!  -src/Integrations/Platformly/PlatformlyApi.phpnu[apiKey = $apiKey; $this->projectId = $projectId; } public function make_request($data = array(), $method = 'POST') { $data['api_key'] = $this->apiKey; $args = array( 'method' => $method, 'headers' => array( 'content-type: application/x-www-form-urlencoded' ), 'body' => json_encode($data) ); if ($method == 'POST') { $response = wp_remote_post($this->apiUrl, $args); } else { $response = wp_remote_get($this->apiUrl, $args); } /* If WP_Error, die. Otherwise, return decoded JSON. */ if (is_wp_error($response)) { return [ 'error' => 'failed', 'message' => $response->get_error_message() ]; } return json_decode($response['body'], true); } /** * Test the provided API credentials. * * @access public * @return array */ public function auth_test() { return $this->make_request([ 'action' => 'profile', 'value' => new \stdClass() ], 'POST'); } public function getLists() { $lists = $this->make_request([ 'action' => 'list_segments', 'value' => (object) [ 'project_id' => $this->projectId ], ], 'POST'); if (!empty($lists['error'])) { return []; } return $lists; } public function getTags() { $tags = $this->make_request([ 'action' => 'list_tags', 'value' => (object) [ 'project_id' => $this->projectId ], ], 'POST'); if (!empty($tags['error'])) { return []; } return $tags; } public function getCustomFields() { $customFields = $this->make_request([ 'action' => 'list_custom_fields', 'value' => (object) [ 'project_id' => $this->projectId ], ], 'POST'); if (!empty($tags['error'])) { return []; } return $customFields; } public function addContact($contact) { $contact['project_id'] = $this->projectId; $response = $this->make_request([ 'action' => 'add_contact', 'value' => (object) $contact ]); if (!empty($response['status']) && $response['status'] == 'success') { return $response; } return new \WP_Error('error', $response['message']); } public function add_note($contact_id, $email, $note) { return $this->make_request([ 'action' => 'contact_add_note', 'value' => (object) [ 'contact_id' => $contact_id, 'email' => $email, 'note' => $note ], ], 'POST'); } }PK!f],],.src/Integrations/SMSNotification/Bootstrap.phpnu[logo = fluentFormMix('img/integrations/twilio.png'); $this->description = 'Send SMS in real time when a form is submitted with Twilio.'; $this->registerAdminHooks(); // add_filter('fluentform/notifying_async_sms_notification', '__return_false'); } public function getGlobalFields($fields) { return [ 'logo' => $this->logo, 'menu_title' => __('SMS Provider Settings (Twilio)', 'fluentformpro'), 'menu_description' => __('Please Provide your Twilio Settings here', 'fluentformpro'), 'valid_message' => __('Your Twilio API Key is valid', 'fluentformpro'), 'invalid_message' => __('Your Twilio API Key is not valid', 'fluentformpro'), 'save_button_text' => __('Save Settings', 'fluentformpro'), 'fields' => [ 'senderNumber' => [ 'type' => 'text', 'placeholder' => __('Twilio Number', 'fluentformpro'), 'label_tips' => __("Enter your twillo sender number", 'fluentformpro'), 'label' => __('Number From', 'fluentformpro'), ], 'accountSID' => [ 'type' => 'text', 'placeholder' => __('Account SID', 'fluentformpro'), 'label_tips' => __("Enter Twilio Account SID. This can be found from twillio", 'fluentformpro'), 'label' => __('Account SID', 'fluentformpro'), ], 'authToken' => [ 'type' => 'password', 'placeholder' => __('Auth Token', 'fluentformpro'), 'label_tips' => __("Enter Twilio API Auth Token. This can be found from twillio", 'fluentformpro'), 'label' => __('Auth Token', 'fluentformpro'), ] ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your Twilio API integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect Twilio', 'fluentformpro'), 'data' => [ 'authToken' => '' ], 'show_verify' => true ] ]; } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'senderNumber' => '', 'accountSID' => '', 'authToken' => '', 'provider' => 'twillio' ]; return wp_parse_args($globalSettings, $defaults); } public function saveGlobalSettings($settings) { if (!$settings['authToken']) { $integrationSettings = [ 'senderNumber' => '', 'accountSID' => '', 'authToken' => '', 'provider' => 'twillio', 'status' => false ]; // Update the reCaptcha details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your settings has been updated', 'fluentformpro'), 'status' => false ], 200); } // Verify API key now try { if (empty($settings['senderNumber'])) { //prevent saving integration without the sender number throw new \Exception('Sender number is required'); } $integrationSettings = [ 'senderNumber' => sanitize_textarea_field($settings['senderNumber']), 'accountSID' => sanitize_text_field($settings['accountSID']), 'authToken' => sanitize_text_field($settings['authToken']), 'provider' => 'twillio', 'status' => false ]; update_option($this->optionKey, $integrationSettings, 'no'); $api = new TwilioApi($settings['authToken'], $settings['accountSID']); $result = $api->auth_test(); if (!empty($result['error'])) { throw new \Exception($result['message']); } } catch (\Exception $exception) { wp_send_json_error([ 'message' => $exception->getMessage() ], 400); } // Integration key is verified now, Proceed now $integrationSettings = [ 'senderNumber' => sanitize_textarea_field($settings['senderNumber']), 'accountSID' => sanitize_text_field($settings['accountSID']), 'authToken' => sanitize_text_field($settings['authToken']), 'provider' => 'twillio', 'status' => true ]; // Update the reCaptcha details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your Twilio api key has been verified and successfully set', 'fluentformpro'), 'status' => true ], 200); } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => 'SMS Notification by Twilio', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-sms_notification-settings'), 'configure_message' => __('SMS Notification is not configured yet! Please configure your SMS api first', 'fluentformpro'), 'configure_button_text' => __('Set SMS Notification API', 'fluentformpro') ]; return $integrations; } public function getIntegrationDefaults($settings, $formId) { return [ 'name' => '', 'receiver_number' => '', 'message' => '', 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { return [ 'fields' => [ [ 'key' => 'name', 'label' => __('Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'receiver_number', 'label' => __('To', 'fluentformpro'), 'required' => true, 'placeholder' => __('Type the receiver number', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'message', 'label' => __('SMS text', 'fluentformpro'), 'required' => true, 'placeholder' => __('SMS Text', 'fluentformpro'), 'component' => 'value_textarea' ], [ 'require_list' => false, 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Send SMS Notification conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => false, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable This feed', 'fluentformpro') ] ], 'button_require_list' => false, 'integration_title' => $this->title ]; } public function getMergeFields($list, $listId, $formId) { return []; } /* * Form Submission Hooks Here */ public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; if (empty($feedData['receiver_number']) || empty($feedData['message'])) { do_action('fluentform/integration_action_result', $feed, 'failed', __('No valid receiver_number found', 'fluentformpro')); return; } $apiSettings = $this->getGlobalSettings([]); $feedData['message'] = str_replace('
    ', "\n", $feedData['message']); $feedData['message'] = preg_replace('/\h+/', ' ', sanitize_textarea_field($feedData['message'])); $smsData = [ 'Body' => trim($feedData['message']), 'From' => $apiSettings['senderNumber'], 'To' => $feedData['receiver_number'] ]; $smsData = apply_filters_deprecated( 'fluentform_integration_data_' . $this->integrationKey, [ $smsData, $feed, $entry ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/integration_data_' . $this->integrationKey, 'Use fluentform/integration_data_' . $this->integrationKey . ' instead of fluentform_integration_data_' . $this->integrationKey ); $smsData = apply_filters('fluentform/integration_data_' . $this->integrationKey, $smsData, $feed, $entry); $api = $this->getRemoteClient(); $response = $api->sendSMS($apiSettings['accountSID'], $smsData); if (is_wp_error($response)) { do_action('fluentform/integration_action_result', $feed, 'failed', $response->get_error_message()); } else { do_action('fluentform/integration_action_result', $feed, 'success', __('Twilio SMS feed has been successfully initialed and pushed data', 'fluentformpro')); } } public function getRemoteClient() { $settings = $this->getGlobalSettings([]); return new TwilioApi($settings['authToken'], $settings['accountSID']); } } PK! ְc c .src/Integrations/SMSNotification/TwilioApi.phpnu[authToken = $authToken; $this->accountSID = $accountSID; } public function default_options() { return array( 'api_key' => $this->apiKey ); } public function make_request($action, $options = array(), $method = 'GET') { $args = array( 'headers' => array( 'Authorization' => 'Basic ' . base64_encode($this->accountSID . ':' . $this->authToken), 'Content-Type' => 'application/json', ) ); /* Build request URL. */ $request_url = $this->apiUrl . $action; /* Execute request based on method. */ $response = ''; switch ($method) { case 'POST': $args['headers']['Content-Type'] = 'application/x-www-form-urlencoded'; //$request_url .= '?'.http_build_query($options); $args['body'] = $options; $response = wp_remote_post($request_url, $args); break; case 'GET': $response = wp_remote_get($request_url, $args); break; } /* If WP_Error, die. Otherwise, return decoded JSON. */ if (is_wp_error($response)) { return new \WP_Error($response->get_error_code(), $response->get_error_message()); } $code = wp_remote_retrieve_response_code($response); $body = json_decode(wp_remote_retrieve_body($response), true); if ($code >= 300) { $message = ArrayHelper::get($body, 'message'); return new \WP_Error($code, $message); } else { return $body; } } /** * Test the provided API credentials. * * @access public * @return bool */ public function auth_test() { return $this->make_request('Accounts.json', [], 'GET'); } public function sendSMS($accountId, $data) { $response = $this->make_request('Accounts/' . \rawurlencode($accountId) . '/Messages.json', $data, 'POST'); if (is_wp_error($response)) { return new \WP_Error($response->get_error_code(), $response->get_error_message()); } return $response; } } PK!H@;@;)src/Integrations/Salesflare/Bootstrap.phpnu[key), $this->key, '_fluentform_' . $this->key . '_settings', $this->key . '_feeds', 98 ); $this->logo = fluentFormMix('img/integrations/salesflare.png'); $this->description = 'Create Salesflare contact from WordPress, so you can grow your contact list.'; $this->registerAdminHooks(); // add_filter('fluentform/notifying_async_'.$this->key, '__return_false'); } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => sprintf(__('%s Integration', 'fluentformpro'), $this->name), 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url( 'admin.php?page=fluent_forms_settings#general-' . $this->key . '-settings' ), 'configure_message' => sprintf( __('%s is not configured yet! Please configure the addon first.', 'fluentformpro'), $this->name ), 'configure_button_text' => __('Set API', 'fluentformpro') ]; return $integrations; } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'apiKey' => '', 'status' => '' ]; return wp_parse_args($globalSettings, $defaults); } public function getGlobalFields($fields) { return [ 'logo' => $this->logo, 'menu_title' => sprintf(__('%s Integration Settings', 'fluentformpro'), $this->name), 'menu_description' => __( 'Copy the API Key from Salesflare settings API keys and paste it here, then click on Save.', 'fluentformpro' ), 'valid_message' => sprintf(__('Your %s API Key is valid', 'fluentformpro'), $this->name), 'invalid_message' => sprintf(__('Your %s API Key is not valid', 'fluentformpro'), $this->name), 'save_button_text' => __('Save Settings', 'fluentformpro'), 'fields' => [ 'apiKey' => [ 'type' => 'text', 'placeholder' => __('API Key', 'fluenformpro'), 'label_tips' => sprintf( __( 'Enter your %s Api Key, Copy the API Code and paste it here, then click on Save button', 'fluentformpro' ), $this->name ), 'label' => sprintf(__('%s API Key', 'fluentformpro'), $this->name), ], ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => sprintf( __('Your %s API integration is up and running', 'fluentformpro'), $this->name ), 'button_text' => sprintf(__('Disconnect %s', 'fluentformpro'), $this->name), 'data' => [ 'apiKey' => '' ], 'show_verify' => true ] ]; } public function saveGlobalSettings($settings) { if (!$settings['apiKey']) { $integrationSettings = [ 'apiKey' => '', 'status' => false ]; update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your settings has been updated and discarded', 'fluentformpro'), 'status' => false ], 200); } try { $apiKey = $settings['apiKey']; update_option($this->optionKey, [ 'status' => false, 'apiKey' => $apiKey ], 'no'); $response = (new API($apiKey))->ping(); if (!is_wp_error($response)) { update_option($this->optionKey, [ 'status' => true, 'apiKey' => $apiKey ], 'no'); wp_send_json_success([ 'status' => true, 'message' => __('Your settings has been updated!', 'fluentformpro') ], 200); } throw new \Exception($response->get_error_message(), 400); } catch (\Exception $e) { wp_send_json_error([ 'status' => false, 'message' => 'Invalid API key' ], $e->getCode()); } } public function getIntegrationDefaults($settings, $formId) { return [ 'name' => '', 'list_id' => '', 'email' => '', 'firstname' => '', 'lastname' => '', 'website' => '', 'company' => '', 'phone' => '', 'address' => '', 'city' => '', 'state' => '', 'zip' => '', 'tags' => '', 'fields' => (object)[], 'custom_fields_mapping' => [ [ 'item_value' => '', 'label' => '' ] ], 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'contact_update' => false, 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { return [ 'fields' => [ [ 'key' => 'name', 'label' => __('Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'fields', 'require_list' => false, 'label' => __('Map Fields', 'fluentformpro'), 'tips' => __('Select which Fluent Forms fields pair with their
    respective ' . $this->name . ' fields.', 'fluentformpro'), 'component' => 'map_fields', 'field_label_remote' => $this->name . ' Field', 'field_label_local' => __('Form Field', 'fluentformpro'), 'primary_fileds' => [ [ 'key' => 'email', 'label' => __('Email Address', 'fluentformpro'), 'required' => true, 'input_options' => 'emails' ], [ 'key' => 'firstname', 'label' => __('First Name', 'fluentformpro') ], [ 'key' => 'lastname', 'label' => __('Last Name', 'fluentformpro') ], [ 'key' => 'phone_number', 'label' => __('Phone Number', 'fluentformpro') ], [ 'key' => 'country', 'label' => __('Country', 'fluentformpro') ], [ 'key' => 'city', 'label' => __('City', 'fluentformpro') ], [ 'key' => 'state_region', 'label' => __('State', 'fluentformpro') ], [ 'key' => 'street', 'label' => __('Street', 'fluentformpro') ], [ 'key' => 'zip', 'label' => __('Zip', 'fluentformpro') ], ] ], [ 'key' => 'custom_fields_mapping', 'require_list' => false, 'label' => __('Custom Fields', 'fluentformpro'), 'tips' => __('Select which Fluent Forms fields pair with their
    respective ' . $this->name . ' fields.', 'fluentformpro'), 'component' => 'dropdown_many_fields', 'field_label_remote' => __($this->name . ' Field', 'fluentformpro'), 'field_label_local' => __('Form Field', 'fluentformpro'), 'options' => $this->customFields() ], [ 'require_list' => false, 'key' => 'tags', 'label' => __('Tags', 'fluentformpro'), 'tips' => __('Associate tags to your ' . $this->name . ' contacts with a comma separated list (e.g. new lead, FluentForms, web source). Commas within a merge tag value will be created as a single tag.', 'fluentformpro'), 'component' => 'value_text', 'inline_tip' => __('Please provide each tag by comma separated value, You can use dynamic smart codes', 'fluentformpro') ], [ 'require_list' => false, 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow ' . $this->name . ' integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => false, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable This feed', 'fluentformpro') ] ], 'button_require_list' => false, 'integration_title' => $this->title ]; } public function getMergeFields($list, $listId, $formId) { return []; } public function customFields() { $api = $this->getApiClient(); $fields = $api->customFields(); $formattedFields = []; foreach ($fields as $field) { if (isset($field['api_field'])) { $formattedFields[$field['api_field']] = $field['name']; } } return $formattedFields; } protected function getApiClient() { $settings = $this->getGlobalSettings([]); return new API( $settings['apiKey'] ); } public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; if (!is_email($feedData['email'])) { $feedData['email'] = ArrayHelper::get($formData, $feedData['email']); } if (!is_email($feedData['email'])) { do_action( 'fluentform/integration_action_result', $feed, 'failed', $this->name . __(' API called skipped because no valid email available', 'fluentformpro') ); return; } $addData = [ 'email' => $feedData['email'], 'firstname' => ArrayHelper::get($feedData, 'firstname'), 'lastname' => ArrayHelper::get($feedData, 'lastname'), 'phone_number' => ArrayHelper::get($feedData, 'phone_number'), ]; if ($this->addressData($feedData)) { $addData['address'] = $this->addressData($feedData); } if ($customFields = ArrayHelper::get($feedData, 'custom_fields_mapping')) { $customData = []; foreach ($customFields as $customField) { $customData[$customField['label']] = $customField['item_value']; } $customData = array_filter($customData); if ($customData) { $addData['custom'] = $customData; } } $tags = ArrayHelper::get($feedData, 'tags'); if (!is_array($tags)) { $tags = explode(',', $tags); } $tags = array_map('trim', $tags); $tags = array_filter($tags); if ($tags) { $addData['tags'] = $tags; } $addData = apply_filters_deprecated( 'fluentform_integration_data_' . $this->integrationKey, [ $addData, $feed, $entry ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/integration_data_' . $this->integrationKey, 'Use fluentform/integration_data_' . $this->integrationKey . ' instead of fluentform_integration_data_' . $this->integrationKey ); $addData = apply_filters('fluentform/integration_data_' . $this->integrationKey, $addData, $feed, $entry); $response = $this->getApiClient()->createContact($addData); if (!is_wp_error($response) && isset($response['id'])) { do_action( 'fluentform/integration_action_result', $feed, 'success', $this->name . __(' feed has been successfully initialed and pushed data', 'fluentformpro') ); } else { $error = is_wp_error($response) ? $response->get_error_messages() : 'API Error when submitting Data'; do_action('fluentform/integration_action_result', $feed, 'failed', $error); } } private function addressData($feedData) { $addressList = ArrayHelper::only($feedData, [ 'city', 'country', 'state_region', 'street', 'zip' ]); $address = []; foreach ($addressList as $addressKey => $value) { $address[$addressKey] = $value; } if (count(array_filter($address)) > 0) { return array_filter($address); } return false; } } PK!ʹ #src/Integrations/Salesflare/API.phpnu[apiKey = $apiKey; } public function make_request($action, $options, $method = 'GET', $headers = "") { $endpointUrl = $this->apiUrl . $action; if ($headers) { $args = [ 'headers' => $headers ]; } if ($options) { $args['body'] = $options; } /* Execute request based on method. */ switch ($method) { case 'POST': $response = wp_remote_post($endpointUrl, $args); break; case 'GET': $response = wp_remote_get($endpointUrl, $args); break; } if (is_wp_error($response)) { return [ 'error' => 'API_Error', 'message' => $response->get_error_message() ]; } elseif ($response['response']['code'] == 200) { return json_decode($response['body'], true); } $body = json_decode(wp_remote_retrieve_body($response), true); if (!empty($body['error'])) { $error = 'Unknown Error'; if (isset($body['message'])) { $error = $body['message']; } elseif (!empty($body['error']['message'])) { $error = $body['error']['message']; } return new \WP_Error(423, $error); } return $body; } public function ping() { $headers = [ 'Authorization' => 'Bearer ' . $this->apiKey ]; return $this->make_request('accounts', '', 'GET', $headers); } public function customFields() { $headers = [ 'Authorization' => 'Bearer ' . $this->apiKey ]; return $this->make_request('customfields/contacts', '', 'GET', $headers); } public function createContact($addData) { $headers = [ 'Authorization' => 'Bearer ' . $this->apiKey, 'Content-Type' => 'application/json' ]; return $this->make_request('contacts', json_encode($addData), 'POST', $headers); } } PK!&T&T)src/Integrations/Salesforce/Bootstrap.phpnu[logo = fluentFormMix('img/integrations/salesforce.png'); $this->description = "Connect Salesforce with Fluent Forms and get contacts and others more organized."; $this->registerAdminHooks(); add_action('admin_init', function () { $isSaleforceAuthCode = isset($_REQUEST['ff_salesforce_auth']) && isset($_REQUEST['code']); if ($isSaleforceAuthCode) { // Get the access token now $code = sanitize_text_field($_REQUEST['code']); $settings = $this->getGlobalSettings([]); $client = $this->getRemoteClient(); $settings = $client->generateAccessToken($code, $settings); if (!is_wp_error($settings)) { $settings['status'] = true; update_option($this->optionKey, $settings, 'no'); } wp_redirect(admin_url('admin.php?page=fluent_forms_settings#general-salesforce-settings')); exit(); } }); add_filter( 'fluentform/get_integration_values_salesforce', [$this, 'resolveIntegrationSettings'], 10, 3 ); add_filter( 'fluentform/save_integration_value_' . $this->integrationKey, [$this, 'validate'], 10, 3 ); } public function resolveIntegrationSettings($settings, $feed, $formId) { $serviceName = $this->app->request->get('serviceName', ''); $serviceId = $this->app->request->get('serviceId', ''); if ($serviceName) { $settings['name'] = $serviceName; } if ($serviceId) { $settings['list_id'] = $serviceId; } return $settings; } public function getRemoteClient() { $settings = $this->getGlobalSettings([]); return new API( $settings ); } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'client_id' => '', 'client_secret' => '', 'status' => false, 'is_sandbox' => false, 'access_token' => '', 'refresh_token' => '' ]; return wp_parse_args($globalSettings, $defaults); } public function getGlobalFields($fields) { return [ 'logo' => $this->logo, 'menu_title' => __('Salesforce Settings', 'fluentformpro'), 'menu_description' => __($this->description, 'fluentformpro'), 'valid_message' => __('Your Salesforce API Key is valid', 'fluentformpro'), 'invalid_message' => __('Your Salesforce API Key is not valid', 'fluentformpro'), 'save_button_text' => __('Save Settings', 'fluentformpro'), 'config_instruction' => $this->getConfigInstructions(), 'fields' => [ 'is_sandbox' => [ 'type' => 'checkbox-single', 'checkbox_label' => __('Salesforce Sandbox Account', 'fluentformpro'), 'label_tips' => __('Check if your Salesforce is a sandbox account', 'fluentformpro'), 'label' => __('Sandbox Account', 'fluentformpro'), ], 'instance_url' => [ 'type' => 'text', 'placeholder' => __('Salesforce Domain URL', 'fluentformpro'), 'label_tips' => __('Enter your Salesforce domain URL including https:// in front', 'fluentformpro'), 'label' => __('Salesforce Domain URL', 'fluentformpro'), ], 'client_id' => [ 'type' => 'text', 'placeholder' => __('Salesforce Consumer Key', 'fluentformpro'), 'label_tips' => __('Enter your Salesforce Consumer Key', 'fluentformpro'), 'label' => __('Salesforce Consumer Key', 'fluentformpro'), ], 'client_secret' => [ 'type' => 'password', 'placeholder' => __('Salesforce App Consumer Secret', 'fluentformpro'), 'label_tips' => __('Enter your Salesforce Consumer secret', 'fluentformpro'), 'label' => __('Salesforce Consumer Secret', 'fluentformpro'), ], ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your Salesforce API integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect Salesforce', 'fluentformpro'), 'data' => [ 'client_id' => '', 'client_secret' => '', 'access_token' => '', 'instance_url' => '', ], 'show_verify' => true ] ]; } protected function getConfigInstructions() { $authLink = admin_url('?ff_salesforce_auth=true'); ob_start(); ?>
    1. Open Setup Home -> Apps -> App Manager -> New Connected App and set the App Name, API Name and Contact Email. Check the Enable OAuth Settings and set the callback URL as
    2. Select the scopes : "Manage user data via APIs (api) and Perform requests at any time (refresh_token, offline_access)". Save the connected app and wait a few minutes for it to be activated. Copy the Consumer Key and Consumer Secret to use them in the next step.
    3. Paste your Salesforce Domain URL, Consumer key and Consumer Secret and save the settings. This Domain URL uses a standard format as, https://{MyDomainName}.my.salesforce.com. For more details click here
    '', 'client_secret' => '', 'instance_url' => '', 'access_token' => '', 'is_sandbox' => false, 'status' => false ]; // Update the details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your settings has been updated', 'fluentformpro'), 'status' => false ], 200); } try { if (empty($settings['instance_url'])) { throw new \Exception('Instance URL is required'); } $oldSettings = $this->getGlobalSettings([]); $oldSettings['client_id'] = sanitize_text_field($settings['client_id']); $oldSettings['client_secret'] = sanitize_text_field($settings['client_secret']); $oldSettings['instance_url'] = sanitize_text_field($settings['instance_url']); $oldSettings['is_sandbox'] = isset($settings['is_sandbox']) ? $settings['is_sandbox'] : false; $oldSettings['status'] = false; update_option($this->optionKey, $oldSettings, 'no'); wp_send_json_success([ 'message' => __('You are redirecting Salesforce to authenticate', 'fluentformpro'), 'redirect_url' => $this->getRemoteClient()->getRedirectServerURL() ], 200); } catch (\Exception $exception) { wp_send_json_error([ 'message' => $exception->getMessage() ], 400); } } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => $this->title . ' Integration', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-salesforce-settings'), 'configure_message' => __('Salesforce is not configured yet! Please configure your Salesforce api first', 'fluentformpro'), 'configure_button_text' => __('Set Salesforce API', 'fluentformpro') ]; return $integrations; } public function getIntegrationDefaults($settings, $formId) { $listId = $this->app->request->get('serviceId'); return [ 'name' => '', 'list_id' => $listId, 'other_fields' => [ [ 'item_value' => '', 'label' => '' ] ], 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { $fieldSettings = [ 'fields' => [ [ 'key' => 'name', 'label' => __('Feed Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'list_id', 'label' => __('Salesforce Services', 'fluentformpro'), 'placeholder' => __('Select Salesforce Service', 'fluentformpro'), 'required' => true, 'component' => 'refresh', 'options' => $this->getLists() ], ], 'button_require_list' => false, 'integration_title' => $this->title ]; $listId = $this->app->request->get('serviceId', ArrayHelper::get($settings, 'list_id')); if ($listId) { $fields = $this->getFields($listId); if (empty($fields)) { wp_send_json_error([ 'message' => __("The selected service doesn't have any field settings.", 'fluentformpro'), ], 423); } $fields = array_merge($fieldSettings['fields'], $fields); $fieldSettings['fields'] = $fields; } $fieldSettings['fields'] = array_merge($fieldSettings['fields'], [ [ 'require_list' => false, 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow this integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => false, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable this feed', 'fluentformpro') ] ]); return $fieldSettings; } protected function getLists() { return [ 'account' => 'Account', 'campaign' => 'Campaign', 'case' => 'Case', 'contact' => 'Contact', 'lead' => 'Lead', 'opportunity' => 'Opportunity', 'product2' => 'Product', ]; } public function getMergeFields($list, $listId, $formId) { return false; } public function validate($settings, $integrationId, $formId) { $error = false; $errors = []; foreach ($this->getFields($settings['list_id']) as $field) { if ($field['required'] && empty($settings[$field['key']])) { $error = true; $errors[$field['key']] = [__($field['label'] . ' is required', 'fluentformpro')]; } } if ($error) { wp_send_json_error([ 'message' => __('Validation Failed', 'fluentformpro'), 'errors' => $errors ], 423); } return $settings; } public function getFields($listId) { $client = $this->getRemoteClient(); if (!$this->isConfigured()) { return false; } $settings = get_option($this->optionKey); $lists = $client->makeRequest( rtrim($settings['instance_url'], '/') . '/services/data/v53.0/sobjects/' . $listId . '/describe', null ); if (is_wp_error($lists)) { wp_send_json_error([ 'message' => __($lists->get_error_message(), 'fluentformpro'), ], 423); } $fields = []; if ($lists['fields']) { $otherFields = []; foreach ($lists['fields'] as $input) { if ($input['createable']) { if (!$input['nillable'] && $input['type'] != 'picklist' && $input['type'] != 'reference' && $input['type'] != 'boolean' && $input['type'] != 'date') { $data = [ 'key' => $input['name'], 'placeholder' => __($input['label'], 'fluentformpro'), 'label' => __($input['label'], 'fluentformpro'), 'required' => true, 'tips' => __($input['label'] . ' is a required field.', 'fluentformpro'), 'component' => 'value_text' ]; array_push($fields, $data); } if ($input['type'] == 'email') { $data = [ 'key' => $input['name'], 'placeholder' => __($input['label'], 'fluentformpro'), 'label' => __($input['label'], 'fluentformpro'), 'required' => false, 'tips' => __($input['label'] . ' is a required field.', 'fluentformpro'), 'component' => 'value_text' ]; array_push($fields, $data); } if (!$input['nillable'] && $input['type'] == 'picklist' && !empty($input['picklistValues'])) { $data = [ 'key' => $input['name'], 'placeholder' => __($input['label'], 'fluentformpro'), 'label' => __($input['label'], 'fluentformpro'), 'required' => true, 'tips' => __($input['label'] . ' is a required list field.', 'fluentformpro'), 'component' => 'select' ]; $options = []; foreach ($input['picklistValues'] as $option) { $options[$option['value']] = $option['label']; } $data['options'] = $options; array_push($fields, $data); } if ($input['nillable'] && $input['type'] == 'picklist' && !empty($input['picklistValues'])) { $data = [ 'key' => $input['name'], 'placeholder' => __($input['label'], 'fluentformpro'), 'label' => __($input['label'], 'fluentformpro'), 'required' => false, 'tips' => __($input['label'] . ' is a list field.', 'fluentformpro'), 'component' => 'select' ]; $options = []; foreach ($input['picklistValues'] as $option) { $options[$option['value']] = $option['label']; } $data['options'] = $options; array_push($fields, $data); } if (!$input['nillable'] && $input['type'] == 'date') { $data = [ 'key' => $input['name'], 'placeholder' => __($input['label'], 'fluentformpro'), 'label' => __($input['label'], 'fluentformpro'), 'required' => true, 'tips' => __($input['label'] . ' is a required field. Date format must be YYYY/MM/DD 00:00:00 format.', 'fluentformpro'), 'component' => 'datetime' ]; array_push($fields, $data); } if ($input['nillable'] && ($input['type'] != 'picklist' && $input['type'] != 'reference' && $input['type'] != 'boolean' && $input['type'] != 'email')) { $otherFields[$input['name']] = $input['label']; } } } if (!empty($otherFields)) { $fields[] = [ 'key' => 'other_fields', 'require_list' => false, 'required' => false, 'label' => __('Other Fields', 'fluentformpro'), 'tips' => __('Map fields according with Fluent Forms fields.', 'fluentformpro'), 'component' => 'dropdown_many_fields', 'field_label_remote' => 'Others Field', 'field_label_local' => 'Others Field', 'options' => $otherFields ]; } } return $fields; } protected function getAllFields($listId) { $fields = $this->getFields($listId); $allFields = []; foreach ($fields as $field) { $keyData = []; $keyData['key'] = $field['key']; if ($field['required']) { $keyData['required'] = $field['required']; array_push($allFields, $keyData); } else { $keyData['required'] = 0; array_push($allFields, $keyData); } } return $allFields; } public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; if (empty($feedData['list_id'])) { do_action('fluentform/integration_action_result', $feed, 'failed', 'No Valid Service Found'); return; } $subscriber = [ 'list_id' => $feedData['list_id'] ]; $allFields = $this->getAllFields($feedData['list_id']); foreach ($allFields as $field) { if (!empty($feedData[$field['key']])) { if ($field['key'] == 'other_fields') { $otherFields = ArrayHelper::get($feedData, 'other_fields'); foreach ($otherFields as $other) { if (!empty($other['item_value'])) { $subscriber['attributes'][$other['label']] = $other['item_value']; } } } else { $subscriber['attributes'][$field['key']] = ArrayHelper::get($feedData, $field['key']); } } } $client = $this->getRemoteClient(); $response = $client->subscribe($subscriber); if (!is_wp_error($response)) { do_action('fluentform/integration_action_result', $feed, 'success', 'Salesforce feed has been successfully initialed and pushed data'); } else { $error = $response->get_error_message(); do_action('fluentform/integration_action_result', $feed, 'failed', $error); } } } PK![=mm#src/Integrations/Salesforce/API.phpnu[clientId = $settings['client_id']; $this->clientSecret = $settings['client_secret']; $this->instance_url = rtrim($settings['instance_url'], '/'); $this->accessToken = $settings['access_token']; $this->callBackUrl = admin_url('?ff_salesforce_auth=true'); $this->settings = $settings; } public function getRedirectServerURL() { return $this->instance_url . '/services/oauth2/authorize?response_type=code&client_id=' . $this->clientId . '&redirect_uri=' . $this->callBackUrl; } public function generateAccessToken($code, $settings) { $url = $settings['is_sandbox'] == 'true' ? 'https://test.salesforce.com/services/oauth2/token' : 'https://login.salesforce.com/services/oauth2/token'; $response = wp_remote_post($url, [ 'body' => [ 'client_id' => $this->clientId, 'client_secret' => $this->clientSecret, 'grant_type' => 'authorization_code', 'redirect_uri' => $this->callBackUrl, 'code' => $code ] ]); if (is_wp_error($response)) { return $response; } $body = wp_remote_retrieve_body($response); $body = \json_decode($body, true); if (isset($body['error_description'])) { return new \WP_Error('invalid_client', $body['error_description']); } $settings['access_token'] = $body['access_token']; $settings['refresh_token'] = $body['refresh_token']; return $settings; } protected function getApiSettings() { $this->maybeRefreshToken(); if(!$this->settings['status']) { return new \WP_Error('invalid', __('API key is invalid', 'fluentformpro')); } return [ 'client_id' => $this->clientId, 'client_secret' => $this->clientSecret, 'callback' => $this->callBackUrl, 'access_token' => $this->settings['access_token'], 'refresh_token' => $this->settings['refresh_token'] ]; } protected function maybeRefreshToken() { $response = wp_remote_post('https://login.salesforce.com/services/oauth2/token', [ 'body' => [ 'client_id' => $this->clientId, 'client_secret' => $this->clientSecret, 'grant_type' => 'refresh_token', 'refresh_token' => $this->settings['refresh_token'] ] ]); if (is_wp_error($response)) { return new \WP_Error('error', $response[0]['errorCode'] . ': ' .$response[0]['message']); } $body = wp_remote_retrieve_body($response); $body = \json_decode($body, true); if (isset($body['error_description'])) { return new \WP_Error('invalid_client', $body['error_description']); } $this->settings['access_token'] = $body['access_token']; } public function makeRequest($url, $bodyArgs, $type = 'GET') { $apiSettings = $this->getApiSettings(); $this->accessToken = $apiSettings['access_token']; $request = []; if ($type == 'GET') { $request = wp_remote_get($url, [ 'headers' => [ 'Authorization' => " Bearer ". $this->accessToken, ] ]); } if ($type == 'POST') { $request = wp_remote_post($url, [ 'headers' => [ 'Authorization' => " Bearer ". $this->accessToken, 'Content-Type' => 'application/json' ], 'body' => $bodyArgs ]); } if (is_wp_error($request)) { $message = $request->get_error_message(); return new \WP_Error($request->get_error_code(), $message); } elseif ($request['response']['code'] >= 200 && $request['response']['code'] <= 299) { return json_decode($request['body'], true); } $body = wp_remote_retrieve_body($request); $body = \json_decode($body, true)[0]; $error = 'Unknown Error'; if (!empty($body['errorCode'])) { if (isset($body['message'])) { $error = $body['message']; } } return new \WP_Error($request['response']['code'], $error); } public function subscribe($subscriber) { $url = $this->instance_url . '/services/data/v53.0/sobjects/' . $subscriber['list_id']; $post = \json_encode($subscriber['attributes'], JSON_NUMERIC_CHECK); $response = $this->makeRequest($url, $post, 'POST'); return $response; } } PK!n;[,[,&src/Integrations/SendFox/Bootstrap.phpnu[logo = fluentFormMix('img/integrations/sendfox.png'); $this->description = 'Connect SendFox with Fluent Forms and subscribe a contact when a form is submitted.'; $this->registerAdminHooks(); // add_filter('fluentform/notifying_async_sendfox', '__return_false'); } public function getGlobalFields($fields) { return [ 'logo' => $this->logo, 'menu_title' => __('SendFox API Settings', 'fluentformpro'), 'menu_description' => __('SendFox is email marketing software. Use Fluent Forms to collect customer information and automatically add it as SendFox subscriber list.', 'fluentformpro'), 'valid_message' => __('Your SendFox API Key is valid', 'fluentformpro'), 'invalid_message' => __('Your SendFox API Key is not valid', 'fluentformpro'), 'save_button_text' => __('Save Settings', 'fluentformpro'), 'fields' => [ 'apiKey' => [ 'type' => 'textarea', 'placeholder' => 'API Key', 'label_tips' => __("Enter your SendFox API Key, if you do not have
    Please log in to your Sendfox account and go to
    Account -> API Key", 'fluentformpro'), 'label' => __('SendFox API Key', 'fluentformpro'), ] ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your SendFox API integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect SendFox', 'fluentformpro'), 'data' => [ 'apiKey' => '' ], 'show_verify' => true ] ]; } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'apiKey' => '', 'status' => '' ]; return wp_parse_args($globalSettings, $defaults); } public function saveGlobalSettings($settings) { if (!$settings['apiKey']) { $integrationSettings = [ 'apiKey' => '', 'status' => false ]; // Update the reCaptcha details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your settings has been updated', 'fluentformpro'), 'status' => false ], 200); } // Verify API key now try { $api = new API($settings['apiKey']); $result = $api->auth_test(); if (!empty($result['error'])) { throw new \Exception($result['message']); } } catch (\Exception $exception) { wp_send_json_error([ 'message' => $exception->getMessage(), 'status' => false ], 400); } // Integration key is verified now, Proceed now $integrationSettings = [ 'apiKey' => sanitize_text_field($settings['apiKey']), 'status' => true ]; // Update the reCaptcha details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your SendFox API key has been verified and successfully set', 'fluentformpro'), 'status' => true ], 200); } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => $this->title . ' Integration', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-sendfox-settings'), 'configure_message' => __('SendFox is not configured yet! Please configure your SendFox api first', 'fluentformpro'), 'configure_button_text' => __('Set SendFox API', 'fluentformpro') ]; return $integrations; } public function getIntegrationDefaults($settings, $formId) { return [ 'name' => '', 'SubscriberFirstName' => '', // Name in SendFox 'SubscriberLastName' => '', // Name in SendFox 'Email' => '', 'CustomFields' => (object)[], 'list_id' => '', // SendFox 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { return [ 'fields' => [ [ 'key' => 'name', 'label' => __('Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'list_id', 'label' => __('SendFox Mailing Lists', 'fluentformpro'), 'placeholder' => __('Select SendFox Mailing List', 'fluentformpro'), 'tips' => __('Select the SendFox Mailing List you would like to add your contacts to.', 'fluentformpro'), 'component' => 'list_ajax_options', 'options' => $this->getLists(), ], [ 'key' => 'CustomFields', 'require_list' => true, 'label' => __('Map Fields', 'fluentformpro'), 'tips' => __('Associate your SendFox merge tags to the appropriate Fluent Forms fields by selecting the appropriate form field from the list.', 'fluentformpro'), 'component' => 'map_fields', 'field_label_remote' => __('SendFox Field', 'fluentformpro'), 'field_label_local' => 'Form Field', 'primary_fileds' => [ [ 'key' => 'Email', 'label' => __('Email Address', 'fluentformpro'), 'required' => true, 'input_options' => 'emails' ], [ 'key' => 'SubscriberFirstName', 'label' => __('First Name', 'fluentformpro') ], [ 'key' => 'SubscriberLastName', 'label' => __('Last Name', 'fluentformpro') ] ] ], [ 'require_list' => true, 'key' => 'conditionals', 'label' => __('Conditional Logic', 'fluentformpro'), 'tips' => __('Allow SendFox integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => true, 'key' => 'enabled', 'label' => __('Status','fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable This feed', 'fluentformpro') ] ], 'button_require_list' => true, 'integration_title' => $this->title ]; } public function getMergeFields($list, $listId, $formId) { return []; } protected function getLists() { $api = $this->getApiInstance(); $lists = $api->getLists(); $formattedLists = []; foreach ($lists as $list) { $formattedLists[$list['id']] = $list['name']; } return $formattedLists; } /* * Form Submission Hooks Here */ public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; if (!is_email($feedData['Email'])) { $feedData['Email'] = ArrayHelper::get($formData, $feedData['Email']); } if (!is_email($feedData['Email'])) { do_action('fluentform/integration_action_result', $feed, 'failed', __('SendFox API call has been skipped because no valid email available', 'fluentformpro')); return; } $subscriber = [ 'first_name' => $feedData['SubscriberFirstName'], 'last_name' => $feedData['SubscriberLastName'], 'email' => $feedData['Email'], 'tags' => [ $feedData['list_id'] ] ]; $subscriber = array_filter($subscriber); $subscriber = apply_filters_deprecated( 'fluentform_integration_data_' . $this->integrationKey, [ $subscriber, $feed, $entry ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/integration_data_' . $this->integrationKey, 'Use fluentform/integration_data_' . $this->integrationKey . ' instead of fluentform_integration_data_' . $this->integrationKey ); $subscriber = apply_filters('fluentform/integration_data_' . $this->integrationKey, $subscriber, $feed, $entry); $api = $this->getApiInstance(); $result = $api->subscribe($subscriber); if (!$result) { do_action('fluentform/integration_action_result', $feed, 'failed', __('SendFox API call has been failed', 'fluentformpro')); } else { do_action('fluentform/integration_action_result', $feed, 'success', __('SendFox feed has been successfully initialed and pushed data', 'fluentformpro')); } } protected function getApiInstance() { $settings = $this->getApiSettings(); return new API($settings['apiKey']); } } PK!}78dd src/Integrations/SendFox/API.phpnu[apiKey = $apiKey; } public function default_options() { return array( 'apikey' => $this->apiKey ); } public function make_request($action, $options = array(), $method = 'GET') { /* Build request options string. */ $request_options = $this->default_options(); $request_options = wp_parse_args($options, $request_options); $options_string = http_build_query($request_options); /* Build request URL. */ $request_url = $this->apiUrl . $action; /* Execute request based on method. */ switch ($method) { case 'POST': $request_url = $this->apiUrl.$action; $args = []; $args['body'] = json_encode($options); $args['method'] = 'POST'; $args['headers'] = [ 'Content-Type' => 'application/json', 'Accept' => 'application/json', 'Authorization' => 'Bearer '.$this->apiKey ]; $response = wp_remote_post($request_url, $args); break; case 'GET': $args['headers'] = [ 'Content-Type' => 'application/json', 'Accept' => 'application/json', 'Authorization' => 'Bearer '.$this->apiKey ]; $response = wp_remote_get($request_url, $args); break; } /* If WP_Error, die. Otherwise, return decoded JSON. */ if (is_wp_error($response)) { return [ 'error' => 'API_Error', 'message' => $response->get_error_message() ]; } else if($response['response']['code'] == 200) { return json_decode($response['body'], true); } else { return [ 'error' => 'API_Error', 'message' => $response['response']['message'] ]; } } /** * Test the provided API credentials. * * @access public * @return bool */ public function auth_test() { return $this->make_request('me',[], 'GET'); } public function subscribe($data) { $request = $this->make_request('contacts', $data, 'POST'); if(!empty($request['id'])) { return true; } return false; } /** * Get all Forms in the system. * * @access public * @return array */ public function getLists() { $response = $this->make_request('lists', [], 'GET'); if (!empty($response['error'])) { return []; } $list = $response['data']; //update to fetch all paginated list while($response['next_page_url'] != null){ $nextPage = $response['current_page'] + 1; $response = $this->make_request('lists?page='.$nextPage, [], 'GET'); if (!empty($response['error'])) { return $list; } if(!empty($response['data'])) { $list = array_merge ($list,$response['data']); } } return $list; } /** * Get single Form in the system. * * @access public * @return array */ public function getList($listId) { $response = $this->make_request('lists/' . $listId . '/details.json', [ 'WithStatistics' => false ], 'GET'); if (empty($response['Error'])) { return $response['Context']; } return false; } } PK!{e6e6)src/Integrations/Sendinblue/Bootstrap.phpnu[logo = fluentFormMix('img/integrations/sendinblue.png'); $this->description = 'Create contacts easily on your Sendinblue email list with Fluent Forms Sendinblue integration.'; $this->registerAdminHooks(); // add_filter('fluentform/notifying_async_sendinblue', '__return_false'); } public function getGlobalFields($fields) { return [ 'logo' => $this->logo, 'menu_title' => __('Sendinblue API Settings', 'fluentformpro'), 'menu_description' => __('Sendinblue is an integrated email marketing, marketing automation, and small business CRM. Save time while growing your business with sales automation. Use Fluent Forms to collect customer information and automatically add it to your Sendinblue list. If you don\'t have an Sendinblue account, you can sign up for one here.', 'fluentformpro'), 'valid_message' => __('Your Sendinblue configuration is valid', 'fluentformpro'), 'invalid_message' => __('Your Sendinblue configuration is invalid', 'fluentformpro'), 'save_button_text' => __('Save Settings', 'fluentformpro'), 'fields' => [ 'apiKey' => [ 'type' => 'password', 'placeholder' => __('V3 API Key', 'fluentformpro'), 'label_tips' => __("Enter your Sendinblue API Key, if you do not have
    Please login to your Sendinblue account and find the api key", 'fluentformpro'), 'label' => __('Sendinblue V3 API Key', 'fluentformpro'), ] ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your Sendinblue API integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect Sendinblue', 'fluentformpro'), 'data' => [ 'apiKey' => '' ], 'show_verify' => true ] ]; } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'apiKey' => '', 'status' => '' ]; return wp_parse_args($globalSettings, $defaults); } public function saveGlobalSettings($settings) { if (!$settings['apiKey']) { $integrationSettings = [ 'apiKey' => '', 'status' => false ]; // Update the details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your settings has been updated and discarded', 'fluentformpro'), 'status' => false ], 200); } try { $settings['status'] = false; update_option($this->optionKey, $settings, 'no'); $api = new SendinblueApi($settings['apiKey']); $auth = $api->auth_test(); if (isset($auth['email'])) { $settings['status'] = true; update_option($this->optionKey, $settings, 'no'); wp_send_json_success([ 'status' => true, 'message' => __('Your settings has been updated!', 'fluentformpro') ], 200); } throw new \Exception(__('Invalid Credentials', 'fluentformpro'), 400); } catch (\Exception $e) { wp_send_json_error([ 'status' => false, 'message' => $e->getMessage() ], $e->getCode()); } } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => $this->title . ' Integration', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-sendinblue-settings'), 'configure_message' => __('Sendinblue is not configured yet! Please configure your Sendinblue API first', 'fluentformpro'), 'configure_button_text' => __('Set Sendinblue API', 'fluentformpro') ]; return $integrations; } public function getIntegrationDefaults($settings, $formId) { return [ 'name' => '', 'list_id' => '', 'fieldEmailAddress' => '', 'custom_field_mappings' => (object)[], 'default_fields' => (object)[], 'other_fields_mapping' => [ [ 'item_value' => '', 'label' => '' ] ], 'ip_address' => '{ip}', 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { return [ 'fields' => [ [ 'key' => 'name', 'label' => __('Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'list_id', 'label' => __('Sendinblue Segment', 'fluentformpro'), 'placeholder' => __('Select Sendinblue Segment', 'fluentformpro'), 'tips' => __('Select the Sendinblue segment you would like to add your contacts to.', 'fluentformpro'), 'component' => 'list_ajax_options', 'options' => $this->getLists() ], [ 'key' => 'custom_field_mappings', 'require_list' => true, 'label' => __('Map Fields', 'fluentformpro'), 'tips' => __('Select which Fluent Forms fields pair with their
    respective Sendinblue fields.', 'fluentformpro'), 'component' => 'map_fields', 'field_label_remote' => __('Sendinblue Field', 'fluentformpro'), 'field_label_local' => __('Form Field', 'fluentformpro'), 'primary_fileds' => [ [ 'key' => 'fieldEmailAddress', 'label' => __('Email Address', 'fluentformpro'), 'required' => true, 'input_options' => 'emails' ] ], 'default_fields' => [ array( 'name' => 'first_name', 'label' => esc_html__('First Name', 'fluentformpro'), 'required' => false ), array( 'name' => 'last_name', 'label' => esc_html__('Last Name', 'fluentformpro'), 'required' => false ) ] ], [ 'key' => 'other_fields_mapping', 'require_list' => true, 'label' => __('Other Fields', 'fluentformpro'), 'tips' => __('Select which Fluent Forms fields pair with their
    respective Sendinblue fields.', 'fluentformpro'), 'component' => 'dropdown_many_fields', 'field_label_remote' => __('SendInBlue Field', 'fluentformpro'), 'field_label_local' => __('Form Field', 'fluentformpro'), 'options' => $this->attributes() ], [ 'require_list' => true, 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow Sendinblue integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => true, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable This feed', 'fluentformpro') ] ], 'button_require_list' => true, 'integration_title' => $this->title ]; } protected function getLists() { $api = $this->getApiClient(); if (!$api) { return []; } $lists = $api->getLists(); if(!$lists) { return []; } $formattedLists = []; foreach ($lists as $list) { if (is_array($list)) { $formattedLists[strval($list['id'])] = $list['name']; } } return $formattedLists; } public function getMergeFields($list, $listId, $formId) { return []; } public function attributes() { $api = $this->getApiClient(); if (!$api) { return []; } $attributes = $api->attributes(); $formattedAttributes = []; foreach ($attributes["attributes"] as $attribute) { if (is_array($attribute)) { $formattedAttributes[$attribute['name']] = $attribute['name']; } } return $formattedAttributes; } /* * Submission Broadcast Handler */ public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; if (!is_email($feedData['fieldEmailAddress'])) { $feedData['fieldEmailAddress'] = ArrayHelper::get($formData, $feedData['fieldEmailAddress']); } if (!is_email($feedData['fieldEmailAddress'])) { do_action('fluentform/integration_action_result', $feed, 'failed', __('SendInBlue API call has been skipped because no valid email available', 'fluentformpro')); return; } $addData = []; $attributes = new \stdClass; $addData['listIds'] = [absint($feedData['list_id'])] ; $addData['email'] = $feedData['fieldEmailAddress']; $defaultFields = ArrayHelper::get($feedData, 'default_fields'); $attributes->FIRSTNAME = $defaultFields['first_name']; $attributes->LASTNAME = $defaultFields['last_name']; foreach (ArrayHelper::get($feedData, 'other_fields_mapping') as $item) { $label = $item['label']; if($item['item_value']){ $attributes->$label = $item['item_value']; } } $addData['attributes'] = $attributes; $addData = apply_filters_deprecated( 'fluentform_integration_data_' . $this->integrationKey, [ $addData, $feed, $entry ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/integration_data_' . $this->integrationKey, 'Use fluentform/integration_data_' . $this->integrationKey . ' instead of fluentform_integration_data_' . $this->integrationKey ); $addData = apply_filters('fluentform/integration_data_' . $this->integrationKey, $addData, $feed, $entry); $api = $this->getApiClient(); $response = $api->addContact($addData); if (!is_wp_error($response) && !empty($response['id'])) { do_action('fluentform/integration_action_result', $feed, 'success', __('SendinBlue feed has been successfully initialed and pushed data', 'fluentformpro')); } else { $error = __('API Error when submitting Data', 'fluentformpro'); if(is_wp_error($response)) { $error = $response->get_error_message(); } if(is_array($error)) { $error = $response->get_error_messages()[0]; } do_action('fluentform/integration_action_result', $feed, 'failed', $error); } } protected function getApiClient() { $settings = get_option($this->optionKey); return new SendinblueApi( $settings['apiKey'] ); } } PK!M-src/Integrations/Sendinblue/SendinblueApi.phpnu[apiKey = $apiKey; } public function make_request($path, $data = array(), $method = 'POST') { $args = array( 'method' => $method, 'headers' => array( 'accept'=> 'application/json', 'content-type' => 'application/json', 'api-key'=> $this->apiKey ) ); if(!empty($data)){ $data["updateEnabled"] = false; $args['body'] = json_encode($data); } $apiUrl = $this->apiUrl . $path; if($method == 'POST') { $response = wp_remote_post($apiUrl, $args); } else if($method == 'GET') { $response = wp_remote_get($apiUrl, $args); } else if($method == 'PUT') { $response = wp_remote_request($apiUrl, $args); } else { return (new \WP_Error(423, 'Request method could not be found')); } /* If WP_Error, die. Otherwise, return decoded JSON. */ if (is_wp_error($response)) { return (new \WP_Error(423, $response->get_error_message())); } return json_decode($response['body'], true); } /** * Test the provided API credentials. * * @access public * @return Array */ public function auth_test() { return $auth = $this->make_request('account/', [], 'GET'); } public function getLists($page = 1) { $limit = 50; $offset = ($page - 1) * $limit; $lists = $this->make_request('contacts/lists?limit='.$limit.'&offset='.$offset.'&sort=desc', [], 'GET'); if(is_wp_error($lists) || empty($lists['lists'])) { return []; } if($page == 1 && $lists['count'] > $limit) { $nextLists = $this->getLists(2); return array_merge($nextLists, $lists['lists']); } return $lists['lists']; } public function attributes() { $attributes = $this->make_request('contacts/attributes', [], 'GET'); if(!empty($lists['error'])) { return []; } return $attributes; } public function addContact($data) { $response = $this->make_request('contacts/', $data, 'POST'); if(!empty($response['id'])) { return $response; } else { // TODO: Check if error is "contact already exists" // Add contact to the lists //return $this->addContactToList($data); return $this->updateContact($data); } return new \WP_Error('error', $response['message']); } public function addContactToList($data) { // Create new data object $add_contact_to_list = []; $add_contact_to_list['emails'] = [$data['email']]; $response = $this->make_request('contacts/lists/' . $data['listIds'][0] . '/contacts/add', $add_contact_to_list, 'POST'); if (!empty($response['contacts']['success'])) { $response_success = []; $response_success['id'] = 1; return $response_success; } return new \WP_Error('error', $response['message']); } public function updateContact($data) { $response = $this->make_request('contacts/' . urlencode($data['email']), $data, 'PUT'); if (empty($response)) { $response_success = []; $response_success['id'] = 1; return $response_success; } return new \WP_Error('error', $response['message']); } }PK!*++'src/Integrations/Telegram/Bootstrap.phpnu[logo = fluentFormMix('img/integrations/telegram.png'); $this->description = 'Send notification to Telegram channel or group when a form is submitted.'; $this->registerAdminHooks(); // add_filter('fluentform/notifying_async_' . $this->integrationKey, '__return_false'); } public function getGlobalFields($fields) { return [ 'logo' => $this->logo, 'menu_title' => __($this->title . ' Settings', 'fluentformpro'), 'menu_description' => __('Create a Bot by sending /newbot command to @BotFather in telegram. After completing the steps @BotFather will provide you the Bot Token.
    Create a Channel/group/supergroup. Add the Bot as Administrator to your Channel/Group.
    Please read the documentation for step by step tutorial', 'fluentformpro'), 'valid_message' => __($this->title . ' integration is complete', 'fluentformpro'), 'invalid_message' => __($this->title . ' integration is not complete', 'fluentformpro'), 'save_button_text' => __('Save Settings', 'fluentformpro'), 'fields' => [ 'bot_token' => [ 'type' => 'password', 'placeholder' => __('bot_token', 'fluentformpro'), 'label_tips' => __("Enter your Telegram Bot Token", 'fluentformpro'), 'label' => __(' Bot Token', 'fluentformpro'), ], 'chat_id' => [ 'type' => 'text', 'placeholder' => __('Channel Username/ID', 'fluentformpro'), 'label_tips' => __("Enter your Telegram API channel user ID, You can also use message id. Please check documentation for more details.", 'fluentformpro'), 'label' => __('Default Channel/Group Chat ID', 'fluentformpro'), ], 'message' => [ 'type' => 'textarea', 'placeholder' => __('Test Message', 'fluentformpro'), 'label_tips' => __("Enter your Test Message", 'fluentformpro'), 'label' => __('Test Message (optional)', 'fluentformpro'), 'tips' => __('Provide a message if you want to send a test message now', 'fluentformpro') ], ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your ' . $this->title . ' API integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect ' . $this->title, 'fluentformpro'), 'data' => [ 'chat_id' => '', 'bot_token' => '', 'message' => '' ], 'show_verify' => true ] ]; } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = [ 'status' => '' ]; } $defaults = [ 'status' => '', 'chat_id' => '', 'bot_token' => '' ]; return wp_parse_args($globalSettings, $defaults); } public function saveGlobalSettings($settings) { if (empty($settings['chat_id']) || empty($settings['bot_token'])) { $settings['status'] = false; update_option($this->optionKey, $settings, 'no'); wp_send_json_success([ 'message' => __('Your settings has been updated', 'fluentformpro'), 'status' => false ], 200); } $responseMessage = __('Your ' . $this->integrationKey . ' api key has been verified and successfully set', 'fluentformpro'); $status = false; // Verify API key now try { $api = $this->getApiClient($settings['bot_token']); $apiStatus = $api->getMe(); if (is_wp_error($apiStatus)) { throw new \Exception($apiStatus->get_error_message()); } $apiSettings = [ 'bot_token' => sanitize_textarea_field($settings['bot_token']), 'status' => true, 'chat_id' => sanitize_textarea_field($settings['chat_id']) ]; $message = ArrayHelper::get($settings, 'message', ''); if ($message) { $api->setChatId($apiSettings['chat_id']); $result = $api->sendMessage($message); if (is_wp_error($result)) { $apiSettings['status'] = false; $responseMessage = 'Your api key is right but, the message could not be sent to the provided chat id. Error: ' . $result->get_error_message(); } } $status = $apiSettings['status']; update_option($this->optionKey, $apiSettings, 'no'); } catch (\Exception $exception) { $settings ['status'] = false; update_option($this->optionKey, $settings, 'no'); wp_send_json_error([ 'message' => $exception->getMessage() ], 400); } $responseCode = 200; if (!$status) { $responseCode = 423; } wp_send_json_success([ 'message' => __($responseMessage, 'fluentformpro'), 'status' => $status ], $responseCode); } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => $this->title . ' Integration', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-' . $this->integrationKey . '-settings'), 'configure_message' => __($this->title . ' is not configured yet! Please configure your api first', 'fluentformpro'), 'configure_button_text' => __('Set ' . $this->title . ' API', 'fluentformpro') ]; return $integrations; } public function getIntegrationDefaults($settings, $formId) { return [ 'name' => '', 'send_message' => '', 'custom_chat_id' => '', 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { return [ 'fields' => [ [ 'key' => 'name', 'label' => __('Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'send_message', 'label' => __('Message to Send', 'fluentformpro'), 'required' => true, 'placeholder' => __('Telegram Message', 'fluentformpro'), 'component' => 'value_textarea' ], [ 'key' => 'custom_chat_id', 'label' => __('Custom Chat/Channel ID', 'fluentformpro'), 'required' => false, 'placeholder' => __('Custom Chat ID', 'fluentformpro'), 'component' => 'text', 'inline_tip' => __('Provide custom chat id if you want to send a different channel or chat ID. Leave blank for global chat ID', 'fluentformpro') ], [ 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow ' . $this->title . ' integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable This feed', 'fluentformpro'), ], ], 'button_require_list' => false, 'integration_title' => $this->title ]; } public function getMergeFields($list = false, $listId = false, $formId = false) { return []; } /* * Form Submission Hooks Here */ public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; if (empty ($feedData['send_message'])) { // for now single file upload only otherwise skip this return; } $settings = $this->getGlobalSettings([]); if(!$settings['status']) { return; } if ($chatId = ArrayHelper::get($feedData, 'custom_chat_id')) { if (trim($chatId)) { $settings['chat_id'] = $chatId; } } $api = $this->getApiClient($settings['bot_token'], $settings['chat_id']); $response = $api->sendMessage($feedData['send_message']); if (is_wp_error($response)) { do_action('fluentform/integration_action_result', $feed, 'failed', $response->get_error_message()); return; } $messageId = ArrayHelper::get($response, 'result.message_id'); do_action( 'fluentform/integration_action_result', $feed, 'success', __('Telegram feed has been successfully initialed and pushed data. Message ID: ', 'fluentformpro') . $messageId ); } protected function getApiClient($token, $chatId = '') { return new TelegramApi( $token, $chatId ); } } PK!]  )src/Integrations/Telegram/TelegramApi.phpnu[token = $token; $this->chatId = $chatId; } public function setChatId($chatId) { $this->chatId = $chatId; return $this; } public function setToken($token) { $this->token = $token; return $this; } public function setParseMode($mode) { $this->parseMode = $mode; return $this; } public function sendMessage($message, $parseMode = '') { if (!$message) { return new \WP_Error(300, 'Message is required', []); } if(!$this->token) { return new \WP_Error(300, 'Token is required', []); } if (!$parseMode) { $parseMode = $this->parseMode; } if($parseMode == 'none') { $message = $this->clearText($message); } return $this->sendRequest('sendMessage', [ 'chat_id' => $this->chatId, 'parse_mode' => $parseMode, 'text' => urlencode($message) ]); } public function getMe() { return $this->sendRequest('getMe'); } private function getBaseUrl() { return $this->apiBase . $this->token . '/'; } private function clearText($html) { return preg_replace( "/\n\s+/", "\n", rtrim(html_entity_decode(strip_tags($html))) ); } public function sendRequest($endPont, $args = []) { if(!$this->token) { return new \WP_Error(300, 'Token is required', []); } $url = add_query_arg($args, $this->getBaseUrl() . $endPont); $ch = curl_init(); $optArray = array( CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true ); curl_setopt_array($ch, $optArray); $result = curl_exec($ch); curl_close($ch); $result = \json_decode($result, true); if (isset($result['ok'])) { if(!empty($result['ok'])) { return $result; } return new \WP_Error($result['error_code'], $result['description'], $result); } return new \WP_Error(300, __('Unknown API error from Telegram', 'fluentformpro'), $result); } }PK!wEwE%src/Integrations/Trello/Bootstrap.phpnu[logo = fluentFormMix('img/integrations/trello.png'); $this->description = 'Fluent Forms Trello Module allows you to create Trello card from submitting forms.'; $this->registerAdminHooks(); add_action('wp_ajax_fluentform_pro_trello_board_config', array($this, 'getBoardConfigOptions')); // add_filter('fluentform/notifying_async_trello', '__return_false'); } public function getGlobalFields($fields) { return [ 'logo' => $this->logo, 'menu_title' => __('Trello API Settings', 'fluentformpro'), 'menu_description' => __('Trello is an integrated email marketing, marketing automation, and small business CRM. Save time while growing your business with sales automation. Use Fluent Forms to collect customer information and automatically add it to your Trello list. If you don\'t have an Trello account, you can sign up for one here.', 'fluentformpro'), 'valid_message' => __('Your Trello configuration is valid', 'fluentformpro'), 'invalid_message' => __('Your Trello configuration is invalid', 'fluentformpro'), 'save_button_text' => __('Verify Trello ', 'fluentformpro'), 'config_instruction' => $this->getConfigInstractions(), 'fields' => [ 'accessToken' => [ 'type' => 'text', 'placeholder' => 'access token Key', 'label_tips' => __("Enter your Trello access token Key, if you do not have
    Please click here to get yours", 'fluentformpro'), 'label' => __('Trello access Key', 'fluentformpro'), ], ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your Trello API integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect Trello', 'fluentformpro'), 'data' => [ 'accessToken' => '' ], 'show_verify' => true ] ]; } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'accessToken' => '', 'status' => '' ]; return wp_parse_args($globalSettings, $defaults); } public function getBoardConfigOptions() { Acl::verify('fluentform_forms_manager'); $requestInfo = $this->app->request->get('settings'); $boardConfig = ArrayHelper::get($requestInfo, 'board_config'); $boardId = ArrayHelper::get($boardConfig, 'board_id'); $data = [ 'board_id' => $this->getBoards(), 'board_list_id' => [], 'board_label_id' => [], 'member_ids' => [] ]; if ($boardId) { $data['board_list_id'] = $this->getBoardLists($boardId); $data['board_label_id'] = $this->getBoardLabels($boardId); $data['member_ids'] = $this->getBoardMembers($boardId); } wp_send_json_success([ 'fields_options' => $data ], 200); } /* * Saving The Global Settings * */ public function saveGlobalSettings($settings) { if (!$settings['accessToken']) { $integrationSettings = [ 'accessToken' => '', 'status' => false ]; // Update the reCaptcha details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your settings has been updated and discarded', 'fluentformpro'), 'status' => false ], 200); } try { $settings['status'] = false; update_option($this->optionKey, $settings, 'no'); $api = new TrelloApi($settings['accessToken'], null); $auth = $api->auth_test(); if (isset($auth['id'])) { $settings['status'] = true; update_option($this->optionKey, $settings, 'no'); wp_send_json_success([ 'status' => true, 'message' => __('Your settings has been updated!', 'fluentformpro') ], 200); } throw new \Exception(__('Invalid Credentials', 'fluentformpro'), 400); } catch (\Exception $e) { wp_send_json_error([ 'status' => false, 'message' => $e->getMessage() ], $e->getCode()); } } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => $this->title . ' Integration', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-trello-settings'), 'configure_message' => __('Trello is not configured yet! Please configure your Trello API first', 'fluentformpro'), 'configure_button_text' => __('Set Trello API', 'fluentformpro') ]; return $integrations; } protected function getConfigInstractions() { ob_start(); ?>

    To Authenticate Trello you need an access token.

    1. Click here to Get Access Token.
    2. Then login and allow with your trello account.
    3. Copy your access token and paste bellow field then click Verify Trello.
    '', 'list_id' => '', // This is the borad id 'board_config' => [ 'board_id' => '', 'board_list_id' => '', 'board_label_id' => '', 'member_ids' => [] ], 'card_name' => '', 'card_description' => '', 'card_pos' => 'bottom', 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { return [ 'fields' => [ [ 'key' => 'name', 'label' => __('Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'board_config', 'label' => __('Trello Configuration', 'fluentformpro'), 'required' => true, 'component' => 'chained_select', 'primary_key' => 'board_id', 'fields_options' => [ 'board_id' => [], 'board_list_id' => [], 'board_label_id' => [], 'member_ids' => [] ], 'options_labels' => [ 'board_id' => [ 'label' => __('Select Board', 'fluentformpro'), 'type' => 'select', 'placeholder' => __('Select Board', 'fluentformpro') ], 'board_list_id' => [ 'label' => __('Select List', 'fluentformpro'), 'type' => 'select', 'placeholder' => __('Select Board List', 'fluentformpro') ], 'board_label_id' => [ 'label' => __('Select Card Label', 'fluentformpro'), 'type' => 'multi-select', 'placeholder' => __('Select Card Label', 'fluentformpro') ], 'member_ids' => [ 'label' => __('Select Members', 'fluentformpro'), 'type' => 'multi-select', 'placeholder' => __('Select Members', 'fluentformpro') ] ], 'remote_url' => admin_url('admin-ajax.php?action=fluentform_pro_trello_board_config') ], [ 'key' => 'card_name', 'label' => __('Card Title', 'fluentformpro'), 'required' => true, 'placeholder' => __('Trello Card Title', 'fluentformpro'), 'component' => 'value_text' ], [ 'key' => 'card_description', 'label' => __('Card Content', 'fluentformpro'), 'placeholder' => __('Trello Card Content', 'fluentformpro'), 'component' => 'value_textarea' ], [ 'key' => 'card_pos', 'label' => __('Card Position', 'fluentformpro'), 'required' => true, 'placeholder' => __('Position', 'fluentformpro'), 'component' => 'radio_choice', 'options' => [ 'bottom' => __('Bottom', 'fluentformpro'), 'top' => __('Top', 'fluentformpro') ] ], [ 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow Gist integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable This feed', 'fluentformpro') ] ], 'button_require_list' => false, 'integration_title' => $this->title ]; } protected function getBoards() { $api = $this->getApiClient(); if (!$api) { return []; } $boards = $api->getBoards(); $formattedBoards = []; foreach ($boards as $board) { if (is_array($board)) { $formattedBoards[$board['id']] = $board['name']; } } return $formattedBoards; } protected function getBoardLists($boardId) { $api = $this->getApiClient(); if (!$api) { return []; } $lists = $api->getLists($boardId); if(is_wp_error($lists)) { return []; } $formattedLists = []; foreach ($lists as $list) { if (is_array($list)) { $formattedLists[$list['id']] = $list['name']; } } return $formattedLists; } protected function getBoardLabels($boardId) { $api = $this->getApiClient(); if (!$api) { return []; } $labels = $api->getLabels($boardId); if(is_wp_error($labels)) { return []; } $formattedLabels = []; foreach ($labels as $label) { if (is_array($label)) { $formattedLabels[$label['id']] = $label['name'] ?: $label['color']; } } return $formattedLabels; } protected function getBoardMembers($boardId) { $api = $this->getApiClient(); if (!$api) { return []; } $members = $api->getMembers($boardId); if(is_wp_error($members)) { return []; } $formattedMembers = []; foreach ($members as $member) { if (is_array($member)) { $formattedMembers[$member['id']] = $member['fullName'] . ' (@' . $member['username'] . ')'; } } return $formattedMembers; } /** * Prepare Trello forms for feed field. * * @return array */ /* * Submission Broadcast Handler */ public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; $listId = ArrayHelper::get($feedData, 'board_config.board_list_id'); if(!$listId) { return; } $cardDescription = ArrayHelper::get($feedData, 'card_description'); $cardDescShortcode = ArrayHelper::get($feed, 'settings.card_description'); if ($cardDescShortcode) { $inputs = FormFieldsParser::getEntryInputs($form, ['raw']); $cardDescInputName = Helper::getInputNameFromShortCode($cardDescShortcode); if ($cardDescInputName && $element = ArrayHelper::get($inputs, $cardDescInputName)) { if ( 'tabular_grid' == ArrayHelper::get($element, 'element') && $value = Helper::getTabularGridFormatValue($formData[$cardDescInputName], $element, "\n", ", ") ) { $cardDescription = $value; } elseif ( 'repeater_field' == ArrayHelper::get($element, 'element') && $value = RepeaterField::getResponseAsText(ArrayHelper::get($formData, $cardDescInputName), ArrayHelper::get($element, 'raw.fields')) ) { $cardDescription = $value; } } } $data = [ 'name' => ArrayHelper::get($feedData, 'card_name'), 'desc' => str_replace("
    ", '', $cardDescription), 'pos' => ArrayHelper::get($feedData, 'card_pos'), 'idList' => $listId ]; if($members = ArrayHelper::get($feedData, 'board_config.member_ids')) { $data['idMembers'] = implode(',', $members); } $labels = ArrayHelper::get($feedData, 'board_config.board_label_id'); if($labels) { if(is_array($labels)) { $data['idLabels'] = implode(',', $labels); } else { $data['idLabels'] = $labels; } } $data = apply_filters_deprecated( 'fluentform_integration_data_' . $this->integrationKey, [ $data, $feed, $entry ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/integration_data_' . $this->integrationKey, 'Use fluentform/integration_data_' . $this->integrationKey . ' instead of fluentform_integration_data_' . $this->integrationKey ); $data = apply_filters('fluentform/integration_data_' . $this->integrationKey, $data, $feed, $entry); // Now let's prepare the data and push to Trello $api = $this->getApiClient(); $response = $api->addCard($data); if (!is_wp_error($response) && isset($response['id'])) { do_action('fluentform/integration_action_result', $feed, 'success', __('Trello feed has been successfully initialed and pushed data', 'fluentformpro')); } else { $error = is_wp_error($response) ? $response->get_error_messages() : __('API Error when submitting Data in trello server', 'fluentformpro'); do_action('fluentform/integration_action_result', $feed, 'failed', $error); } } protected function getApiClient() { $settings = get_option($this->optionKey); return new TrelloApi( $settings['accessToken'] ); } function getMergeFields($list, $listId, $formId) { return $list; } } PK!焪W W %src/Integrations/Trello/TrelloApi.phpnu[appKey = FF_TRELLO_APP_KEY; } $this->accessToken = $accessToken; } private function getApiUrl($resource, $data = []) { $parameters = [ 'key' => $this->appKey, 'token' => $this->accessToken ]; if ($data) { $parameters = wp_parse_args($parameters, $data); } $paramString = http_build_query($parameters); return $this->apiUrl . $resource . '?' . $paramString; } public function make_request($resource, $data, $method = 'GET') { $requestApi = $this->getApiUrl($resource, $data); if ($method == 'GET') { $response = wp_remote_get($requestApi); } else if ($method == 'POST') { $response = wp_remote_post($requestApi); } else { return (new \WP_Error(423, 'Request method could not be found')); } /* If WP_Error, die. Otherwise, return decoded JSON. */ if (is_wp_error($response)) { return (new \WP_Error(423, $response->get_error_message())); } return json_decode($response['body'], true); } /** * Test the provided API credentials. * * @access public * @return Array */ public function auth_test() { return $this->make_request('members/me', [], 'GET'); } public function getBoards() { return $this->make_request('members/my/boards', [], 'GET'); } public function getLists($boardId) { return $this->make_request('boards/' . $boardId . '/lists', [], 'GET'); } public function getLabels($boardId) { return $this->make_request('boards/' . $boardId . '/labels', [], 'GET'); } public function getMembers($boardId) { return $this->make_request('boards/' . $boardId . '/members', 'GET'); } public function addCard($card) { return $this->make_request('cards', $card, 'POST'); } }PK!P>P>/src/Integrations/UserRegistration/Bootstrap.phpnu[regApi = new UserRegistrationApi(); $this->updateApi = new UserUpdateFormHandler(); $this->logo = fluentFormMix('img/integrations/user_registration.png'); $this->description = 'Create WordPress user or update user when a form is submitted.'; $this->registerAdminHooks(); $this->registerHooks(); } protected function registerHooks() { $isEnabled = $this->isEnabled(); if(!$isEnabled){ return; } add_filter('fluentform/notifying_async_UserRegistration', '__return_false'); add_filter('fluentform/save_integration_value_' . $this->integrationKey, [$this, 'handleValidate'], 10, 3); add_filter('fluentform/validation_user_registration_errors', [$this->regApi, 'validateSubmittedForm'], 10, 3); add_filter('fluentform/validation_user_update_errors', [$this->updateApi, 'validateSubmittedForm'], 10, 3); add_filter('fluentform/rendering_form', [ $this->updateApi, 'maybePopulateUserUpdateForm' ], 10, 3); add_filter( 'fluentform/get_integration_values_' . $this->integrationKey, [$this, 'resolveIntegrationSettings'], 100, 3 ); } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'category' => 'wp_core', 'disable_global_settings' => 'yes', 'logo' => $this->logo, 'title' => $this->title . ' Integration', 'is_active' => $this->isConfigured() ]; return $integrations; } public function getIntegrationDefaults($settings, $formId = null) { $listId = $this->app->request->get('serviceId', 'user_registration'); if ($listId == 'user_registration') { $name = $this->app->request->get('serviceName', 'User Registration'); $this->title = 'User Registration'; } else { $name = $this->app->request->get('serviceName', 'User Update'); $this->title = 'User Update'; } $fields = [ 'name' => $name, 'list_id' => $listId, 'Email' => '', 'username' => '', 'CustomFields' => (object)[], 'userRole' => 'subscriber', 'userMeta' => [ [ 'label' => '', 'item_value' => '' ] ], 'enableAutoLogin' => false, 'sendEmailToNewUser' => false, 'validateForUserEmail' => true, 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'enabled' => true ]; $fields = apply_filters_deprecated( 'fluentform_user_registration_field_defaults', [ $fields, $formId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/user_registration_field_defaults', 'Use fluentform/user_registration_field_defaults instead of fluentform_user_registration_field_defaults.' ); return apply_filters('fluentform/user_registration_field_defaults', $fields, $formId); } public function getSettingsFields($settings, $formId = null) { $fieldSettings = [ 'fields' => [ [ 'key' => 'name', 'label' => __('Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'list_id', 'label' => __('Services', 'fluentformpro'), 'placeholder' => __('Choose Service', 'fluentformpro'), 'required' => true, 'component' => 'refresh', 'options' => [ 'user_registration' => __('User Registration', 'fluentformpro'), 'user_update' => __('User Update', 'fluentformpro') ] ], ], 'button_require_list' => false, 'integration_title' => $this->title ]; $listId = $this->app->request->get('serviceId', ArrayHelper::get($settings, 'list_id')); $inline_msg =''; if ($listId) { $fields = $this->getFields($listId); $fields = array_merge($fieldSettings['fields'], $fields); $fieldSettings['fields'] = $fields; if ($listId == 'user_update') { $this->title = __('User Update', 'fluentformpro'); $inline_msg = __('Please note that, This action will only run if the user is logged in.', 'fluentformpro'); } else { $this->title = __('User Registration', 'fluentformpro'); } } $fieldSettings['fields'] = array_merge($fieldSettings['fields'], [ [ 'require_list' => false, 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow '. $this->title . ' integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => false, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable This feed', 'fluentformpro'), 'inline_tip' => $inline_msg ?: __('Please note that, This action will only run if the visitor is logged out state and the email is not registered yet', 'fluentformpro'), ] ]); if ($listId && $listId == 'user_registration') { $fieldSettings['fields'] = apply_filters_deprecated( 'fluentform_user_registration_feed_fields', [ $fieldSettings['fields'], $formId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/user_registration_feed_fields', 'Use fluentform/user_registration_feed_fields instead of fluentform_user_registration_feed_fields.' ); $fieldSettings['fields'] = apply_filters('fluentform/user_registration_feed_fields', $fieldSettings['fields'], $formId); } if ($listId && $listId == 'user_update') { $fieldSettings['fields'] = apply_filters_deprecated( 'fluentform_user_update_feed_fields', [ $fieldSettings['fields'], $formId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/user_update_feed_fields', 'Use fluentform/user_update_feed_fields instead of fluentform_user_update_feed_fields.' ); $fieldSettings['fields'] = apply_filters('fluentform/user_update_feed_fields', $fieldSettings['fields'], $formId); } return $fieldSettings; } public function handleValidate($settings, $integrationId, $formId) { $parseSettings = $this->validate( $settings, $this->getSettingsFields($settings) ); if (ArrayHelper::get($parseSettings, 'list_id') == 'user_update') { Helper::setFormMeta($formId, '_has_user_update', 'yes'); } else { Helper::setFormMeta($formId, '_has_user_registration', 'yes'); } return $parseSettings; } /* * Form Submission Hooks Here */ public function notify($feed, $formData, $entry, $form) { $feedValue = ArrayHelper::get($feed,'processedValues'); $this->resolveCustomMetaValue($feed, $formData, $form); if ( $feedValue && ArrayHelper::get($feedValue, 'list_id') && ArrayHelper::get($feedValue, 'list_id') === 'user_update' ) { $this->updateApi->handleUpdateUser($feed, $formData, $entry, $form, $this->integrationKey); } else { $this->regApi->registerUser( $feed, $formData, $entry, $form, $this->integrationKey ); } } // There is no global settings, so we need // to return true to make this module work. public function isConfigured() { return true; } // This is an absttract method, so it's required. public function getMergeFields($list, $listId, $formId) { // ... } // This method should return global settings. It's not required for // this class. So we should return the default settings otherwise // there will be an empty global settings page for this module. public function addGlobalMenu($setting) { return $setting; } protected function getFields($listId) { if ($listId == 'user_update') { $map_primary_field = $this->updateApi->userUpdateMapFields(); } else { $map_primary_field = $this->regApi->userRegistrationMapFields(); } $customFieldMsg = $listId == 'user_update' ? 'update' : 'registration'; $fields = [ [ 'key' => 'CustomFields', 'require_list' => false, 'label' => __('Map Fields', 'fluentformpro'), 'tips' => __('Associate your user '. $customFieldMsg .' fields to the appropriate Fluent Forms fields by selecting the appropriate form field from the list.', 'fluentformpro'), 'component' => 'map_fields', 'field_label_remote' => __('User ' . ucfirst($customFieldMsg) . ' Field', 'fluentformpro'), 'field_label_local' => __('Form Field', 'fluentformpro'), 'primary_fileds' => $map_primary_field ], ]; if ($listId == 'user_registration') { $fields[] = [ 'require_list' => false, 'required' => true, 'key' => 'userRole', 'label' => __('Default User Role', 'fluentformpro'), 'tips' => __('Set default user role when registering a new user.', 'fluentformpro'), 'component' => 'radio_choice', 'options' => $this->regApi->getUserRoles() ]; $fields[] = [ 'require_list' => false, 'key' => 'userMeta', 'label' => __('User Meta', 'fluentformpro'), 'tips' => __('Add user meta.', 'fluentformpro'), 'component' => 'dropdown_label_repeater', 'field_label' => __('User Meta Key', 'fluentformpro'), 'value_label' => __('User Meta Value', 'fluentformpro') ]; $fields[] = [ 'require_list' => false, 'key' => 'enableAutoLogin', 'label' => __('Auto Login', 'fluentformpro'), 'checkbox_label' => __('Allow the user login automatically after registration', 'fluentformpro'), 'component' => 'checkbox-single', ]; $fields[] = [ 'require_list' => false, 'key' => 'sendEmailToNewUser', 'label' => __('Email Notification', 'fluentformpro'), 'checkbox_label' => __('Send default WordPress welcome email to user after registration', 'fluentformpro'), 'component' => 'checkbox-single', ]; $fields[] = [ 'require_list' => false, 'key' => 'validateForUserEmail', 'label' => __('Form Validation', 'fluentformpro'), 'checkbox_label' => __('Do not submit the form if user already exist in Database', 'fluentformpro'), 'component' => 'checkbox-single', ]; } else { $fields[] = [ 'require_list' => false, 'key' => 'userMeta', 'label' => __('User Meta', 'fluentformpro'), 'tips' => __('Add user meta.', 'fluentformpro'), 'component' => 'dropdown_label_repeater', 'field_label' => __('User Meta Key', 'fluentformpro'), 'value_label' => __('User Meta Value', 'fluentformpro') ]; } return $fields; } private function resolveCustomMetaValue(&$feed, $formData, $form) { if (!ArrayHelper::get($feed, 'processedValues.userMeta', [])) { return; } $userMetaMapping = ArrayHelper::get($feed, 'settings.userMeta', []); $inputs = FormFieldsParser::getInputs($form, ['element', 'attributes']); $resolvableElement = ['input_checkbox', 'multi_select']; foreach ($feed['processedValues']['userMeta'] as $index => &$userMeta) { if ( $userMeta['label'] === ArrayHelper::get($userMetaMapping, $index . '.label', '') && $inputName = Helper::getInputNameFromShortCode(ArrayHelper::get($userMetaMapping, $index . '.item_value', '')) ) { $elementType = ArrayHelper::get($inputs, $inputName . '.element'); if ($elementType == 'select' && ArrayHelper::get($inputs, $inputName . '.attributes.multiple', false)) { $elementType = 'multi_select'; } if (in_array($elementType, $resolvableElement) && isset($formData[$inputName])) { $userMeta['item_value'] = $formData[$inputName]; } } } } public function resolveIntegrationSettings($settings, $feed, $formId) { $serviceId = $this->app->request->get('serviceId', ''); $serviceName = $this->app->request->get('serviceName', ''); if ($serviceName) { $settings['name'] = $serviceName; } if ($serviceId) { $settings['list_id'] = $serviceId; } if ( $serviceId = ArrayHelper::get($settings,'list_id')) { if ($serviceId == 'user_update') { $this->title = __('User Update', 'fluentformpro'); } else { $this->title = __('User Registration', 'fluentformpro'); } } else { $this->title = __('User Registration', 'fluentformpro'); } return $settings; } } PK!&&,src/Integrations/UserRegistration/Getter.phpnu[table('fluentform_form_meta') ->where('form_id', $form->id) ->where('meta_key', 'user_registration_feeds') ->get(); } public function validate($settings, $settingsFields) { foreach ($settingsFields['fields'] as $field) { if ($field['key'] != 'CustomFields') continue; $errors = []; foreach ($field['primary_fileds'] as $primaryField) { if (!empty($primaryField['required'])) { if (empty($settings[$primaryField['key']])) { $errors[$primaryField['key']] = $primaryField['label'] . ' is required.'; } } } if ($errors) { wp_send_json_error([ 'message' => array_shift($errors), 'errors' => $errors ], 422); } } return $settings; } protected function updateUser($parsedData, $userId, $feed = []) { $name = trim(ArrayHelper::get($parsedData, 'first_name'). ' ' . ArrayHelper::get($parsedData, 'last_name')); $data = array_filter([ 'ID' => $userId, 'user_nicename' => ArrayHelper::get($parsedData, 'username', ""), 'display_name' => $name, 'user_url' => ArrayHelper::get($parsedData, 'user_url'), 'first_name' => ArrayHelper::get($parsedData, 'first_name'), 'last_name' => ArrayHelper::get($parsedData, 'last_name'), 'nickname' => $this->filteredNickname(ArrayHelper::get($parsedData, 'nickname'), $parsedData), 'description' => ArrayHelper::get($parsedData, 'description'), ]); $listId = ArrayHelper::get($feed, 'settings.list_id'); if ($listId === 'user_update') { $data = array_merge($data, array_filter([ 'user_pass' => ArrayHelper::get($parsedData, 'password'), 'user_email' => ArrayHelper::get($parsedData, 'email') ])); } if ($data) { return wp_update_user($data); } return new \WP_Error(301, 'Update Failed'); } protected function addLog($title, $status, $description, $formId, $entryId, $integrationKey) { $logData = [ 'title' => $title, 'status' => $status, 'description' => $description, 'parent_source_id' => $formId, 'source_id' => $entryId, 'component' => $integrationKey, 'source_type' => 'submission_item' ]; do_action('fluentform/log_data', $logData); return true; } protected function filteredNickname($nickname, $parseDate) { if (defined('BP_VERSION')){ $nickname = trim($nickname); if (!$nickname) { $nickname = ArrayHelper::get($parseDate, 'username', ''); } $nickname = preg_replace("/\\s/", '-', trim($nickname)); return sanitize_user($nickname, true); } return $nickname; } } PK!N?=?=;src/Integrations/UserRegistration/UserUpdateFormHandler.phpnu[getFormUserFeeds($form); if (!$feeds) { return $form; } foreach ($feeds as $feed) { $feed->value = json_decode($feed->value, true); if ( ArrayHelper::isTrue($feed->value, 'enabled') && ArrayHelper::get($feed->value, 'list_id') === 'user_update' ) { return $this->populateUserUpdateForm($form, $feed->value); } } return $form; } protected function populateUserUpdateForm($form, $feed) { if (!get_current_user_id()) { return $form; } $populateFieldsKeys = $this->getFilterUserUpdateFieldsKey($feed); $formFields = $form->fields['fields']; $populateFields = []; foreach ($formFields as $index => $formField) { if ('container' == ArrayHelper::get($formField, 'element')) { foreach ($formField['columns'] as &$column) { foreach ($column['fields'] as &$field) { $this->populateUserUpdateFormField($field, $populateFieldsKeys); } } } else { $this->populateUserUpdateFormField($formField, $populateFieldsKeys); } $populateFields[$index] = $formField; } $form->fields['fields'] = $populateFields; return $form; } protected function populateUserUpdateFormField(&$formField, $populateFieldsKeys) { foreach ($populateFieldsKeys as $key => $value) { $name = ''; if (preg_match('/\./', $value)) { $value = explode('.', $value); $name = $value[0]; $value = $value[1]; } if ( ArrayHelper::get($formField, 'element') === 'input_name' && ArrayHelper::get($formField, 'attributes.name') === $name && ArrayHelper::has($formField['fields'], $value) ) { $subValue = 'fields.' . $value; $subFiled = ArrayHelper::get($formField, $subValue); if ( $subFiled && ArrayHelper::get($subFiled,'attributes.name') === $value ) { $subFiled['attributes']['value'] = $this->getUserMetaValue($key); $subFiled['attributes']['data-user-update-key'] = $key; if ($key === 'username') { $subFiled['attributes']['readonly'] = true; $subFiled['attributes']['disable'] = true; } $formField['fields'][$value] = $subFiled; } } elseif (ArrayHelper::get($formField, 'attributes.name') === $value) { $formField['attributes']['value'] = $this->getUserMetaValue($key); $formField['attributes']['data-user-update-key'] = $key; if ($key === 'username') { $formField['attributes']['readonly'] = true; $formField['attributes']['disable'] = true; } } } } public function validateSubmittedForm($errors, $data, $form) { $feeds = $this->getFormUserFeeds($form); if (!$feeds) { return $errors; } foreach ($feeds as $feed) { $feed->value = json_decode($feed->value, true); if ( $feed->value && ArrayHelper::isTrue($feed->value, 'enabled') && ArrayHelper::get($feed->value, 'list_id') === 'user_update' ) { $isConditionMatched = $this->checkCondition($feed->value, $data); if (!$isConditionMatched) { continue; } $updateFields = $this->getFilterUserUpdateFieldsKey($feed->value); if ($errors = $this->handleUsernameErrors($errors, $data, $updateFields)){ return $errors; } if ($errors = $this->handleEmailErrors($errors, $data, $updateFields)){ return $errors; } if ( ArrayHelper::get($updateFields, 'password') && $errors = $this->handlePasswordErrors($errors, $data, $updateFields) ) { return $errors; } } } return $errors; } protected function getUserMetaValue($key) { $userId = get_current_user_id(); $profileUser = get_userdata($userId); if ($customMetaKey = $this->getOriginalMetaKey('u_custom_meta_', $key)) { $value = get_user_meta($userId, $customMetaKey); if(count($value)) { return maybe_unserialize($value[0]); } return ''; } if ($bbFieldKey = $this->getOriginalMetaKey('u_buddyboss_field_key_', $key)) { if (defined('BP_VERSION')) { return xprofile_get_field_data(trim($bbFieldKey), get_current_user_id()); } return ''; } switch ($key) { case 'username' : return $profileUser->user_login; case 'email': return $profileUser->user_email; case 'first_name': return $profileUser->first_name; case 'last_name': return $profileUser->last_name; case 'nickname': return $profileUser->nickname; case 'user_url': return $profileUser->user_url; case 'description': return $profileUser->description; default: return ''; } } protected function getOriginalMetaKey ($filterStr, $key) { if (preg_match("/^$filterStr/", $key, $matches)) { return str_replace($filterStr, '', $key); } return false; } protected function getFilterUserUpdateFieldsKey($feed) { $keys = $this->supportedFieldsKey(); $keys[] = 'userMeta'; $keys[] = 'bboss_profile_fields'; $formatFields = []; foreach ($keys as $key) { $value = ArrayHelper::get($feed, $key); if ( $value ) { if ( $key === 'userMeta' ) { foreach ( $value as $meta ) { $formatFields[ "u_custom_meta_" . $meta['label'] ] = $this->getUserUpdateFormFieldName( $meta['item_value'] ); } } else if ($key === 'bboss_profile_fields') { foreach ( $value as $meta ) { $formatFields[ "u_buddyboss_field_key_" . $meta['label'] ] = $this->getUserUpdateFormFieldName( $meta['item_value'] ); } } else { $formatFields[ $key ] = $this->getUserUpdateFormFieldName( $value ); } } } return $formatFields; } protected function getUserUpdateFormFieldName($value) { $formFieldName = ''; if (!$value) return $formFieldName; preg_match('/{+(.*?)}/', $value, $matches); if (count($matches) > 1 && strpos($matches[1], 'inputs.') !== false) { $field = substr( $matches[1], strlen( 'inputs.' ) ); $formFieldName = $field; } return $formFieldName; } public function supportedFieldsKey () { $supportedFields = $this->userUpdateMapFields(); $fieldsKey = []; foreach ($supportedFields as $supportedField) { $fieldsKey[] = $supportedField['key']; } return $fieldsKey; } public function userUpdateMapFields() { $fields = [ [ 'key' => 'username', 'label' => __('Username', 'fluentformpro'), 'required' => true, 'help_text' => __('simple text field for username reference.', 'fluentformpro') ], [ 'key' => 'email', 'label' => __('Email Address', 'fluentformpro'), 'required' => true, 'help_text' => __('email reference field', 'fluentformpro') ], [ 'key' => 'first_name', 'label' => __('First Name', 'fluentformpro'), 'help_text' => __('first name reference field', 'fluentformpro') ], [ 'key' => 'last_name', 'label' => __('Last Name', 'fluentformpro'), 'help_text' => __('last name reference field', 'fluentformpro') ], [ 'key' => 'nickname', 'label' => __('Nickname', 'fluentformpro'), 'help_text' => __('nickname reference field', 'fluentformpro') ], [ 'key' => 'user_url', 'label' => __('Website Url', 'fluentformpro'), 'help_text' => __('website reference field', 'fluentformpro') ], [ 'key' => 'description', 'label' => __('Biographical Info', 'fluentformpro'), 'help_text' => __('description reference field', 'fluentformpro') ], [ 'key' => 'password', 'label' => __('Password', 'fluentformpro'), 'help_text' => __('password reference field', 'fluentformpro') ], [ 'key' => 'repeat_password', 'label' => __('Repeat Password', 'fluentformpro'), 'help_text' => __('repeat password reference field', 'fluentformpro') ] ]; $fields = apply_filters_deprecated( 'fluentform_user_update_map_fields', [ $fields ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/user_update_map_fields', 'Use fluentform/user_update_map_fields instead of fluentform_user_update_map_fields.' ); return apply_filters('fluentform/user_update_map_fields', $fields); } protected function getDataValueByKey($data, $fields, $key) { if (ArrayHelper::get($fields, $key)) { $value = ArrayHelper::get($data, $fields[$key]); if ($value) { return $value; } } if ('username' === $key) { return $this->getUserMetaValue($key); } return ''; } protected function handleEmailErrors($errors = [], $data = [], $fields = []) { $email = $this->getDataValueByKey($data, $fields, 'email'); if (!$email) { return $this->resetErrormessage($errors, __('Email is required. Please provide an email', 'fluentformpro')); } if ($email != $this->getUserMetaValue('email') && email_exists($email)) { return $this->resetErrormessage($errors, __('This email is already registered. Please choose another one.', 'fluentformpro')); } return $errors; } protected function handleUsernameErrors($errors = [], $data = [], $fields = []) { $username = $this->getDataValueByKey($data, $fields, 'username'); if (!$username || $username != $this->getUserMetaValue('username')) { return $this->resetErrormessage($errors, __('Username cannot be changed.', 'fluentformpro')); } return $errors; } protected function handlePasswordErrors($errors, $data, $fields) { $password = $this->getDataValueByKey($data, $fields, 'password'); $confirmPass = $this->getDataValueByKey($data, $fields, 'repeat_password'); if( ArrayHelper::get($fields, 'repeat_password') && $password && $password !== $confirmPass ) { return $this->resetErrormessage($errors, __('Confirm password not match', 'fluentformpro')); } return $errors; } public function handleUpdateUser($feed, $formData, $entry, $form, $integrationKey) { $userId = get_current_user_id(); if (!$userId) { return $this->addLog( $feed['settings']['name'], 'failed', __("user update skip because form submitted from logout session.", 'fluentformpro'), $form->id, $entry->id, $integrationKey ); } $parsedData = ArrayHelper::get($feed, 'processedValues'); $username = $this->getUserMetaValue('username'); if ($username !== ArrayHelper::get($parsedData, 'username')) { return $this->addLog( $feed['settings']['name'], 'failed', __('user update skip because trying to change username.', 'fluentformpro'), $form->id, $entry->id, $integrationKey ); }; $email = ArrayHelper::get($parsedData, 'email'); if (!$email) { return $this->addLog( $feed['settings']['name'], 'failed', __("user update skip because form submitted without email.", 'fluentformpro'), $form->id, $entry->id, $integrationKey ); } $this->updateUserMeta($parsedData, $userId, $form->id); $userId = $this->updateUser($parsedData, $userId, $feed); if (is_wp_error($userId)) { return $this->addLog( $feed['settings']['name'], 'failed', $userId->get_error_message(), $form->id, $entry->id, $integrationKey ); } Helper::setSubmissionMeta($entry->id, '__updated_user_id', $userId); $this->addLog( $feed['settings']['name'], 'success', __('user has been successfully updated. Updated User ID: ', 'fluentformpro') . $userId, $form->id, $entry->id, $integrationKey ); do_action_deprecated( 'fluentform_user_update_completed', [ $userId, $feed, $entry, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/user_update_completed', 'Use fluentform/user_update_completed instead of fluentform_user_update_completed.' ); do_action('fluentform/user_update_completed', $userId, $feed, $entry, $form); } protected function updateUserMeta($parsedData, $userId, $formId) { $userMetas = []; foreach ($parsedData['userMeta'] as $userMeta) { $userMetas[$userMeta['label']] = $userMeta['item_value']; } foreach ($userMetas as $metaKey => $metaValue) { if (AcfHelper::maybeUpdateWithAcf($metaKey, $metaValue)) { continue; } $metaValue = maybe_serialize($metaValue); update_user_meta($userId, $metaKey, trim($metaValue)); } update_user_meta($userId, 'fluentform_user_id', $formId); } } PK!^n5n59src/Integrations/UserRegistration/UserRegistrationApi.phpnu[ $role) { if (!ArrayHelper::get($role, 'capabilities.manage_options')) { $validRoles[$roleKey] = $role['name']; } } $validRoles = apply_filters_deprecated( 'fluentorm_UserRegistration_creatable_roles', [ $validRoles ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/user_registration_creatable_roles', 'Use fluentform/user_registration_creatable_roles instead of fluentorm_UserRegistration_creatable_roles.' ); return apply_filters('fluentform/user_registration_creatable_roles', $validRoles); } public function validateSubmittedForm($errors, $data, $form) { $feeds = $this->getFormUserFeeds($form); if (!$feeds) { return $errors; } foreach ($feeds as $feed) { $parsedValue = json_decode($feed->value, true); if ( ArrayHelper::get($parsedValue, 'list_id') === 'user_update' || !ArrayHelper::isTrue($parsedValue, 'validateForUserEmail') ) { continue; } if ($parsedValue && ArrayHelper::isTrue($parsedValue, 'enabled')) { // Now check if conditions matched or not $isConditionMatched = $this->checkCondition($parsedValue, $data); if (!$isConditionMatched) { continue; } $email = ArrayHelper::get($data, $parsedValue['Email']); if (!$email) { continue; } if (email_exists($email)) { if (!isset($errors['restricted'])) { $errors['restricted'] = []; } $validationMsg = __('This email is already registered. Please choose another one.', 'fluentformpro'); $errors['restricted'][] = apply_filters('fluentform/email_exists_validation_message', $validationMsg, $form, $feed, $email); return $errors; } if(!empty($parsedValue['username'])) { $userName = $this->getUsername($parsedValue['username'], $data); if ($userName) { if (username_exists($userName)) { if (!isset($errors['restricted'])) { $errors['restricted'] = []; } $errors['restricted'][] = __('This username is already registered. Please choose another one.', 'fluentformpro'); return $errors; } } } } } return $errors; } public function registerUser($feed, $formData, $entry, $form, $integrationKey) { $notFromAdminApproval = !(new AdminApproval())->isEntryOnAdminApprovalMode($entry->status); if ($notFromAdminApproval && get_current_user_id()) { return $this->addLog( $feed['settings']['name'], 'failed', __("user registration skip because form submitted from login session.", 'fluentformpro'), $form->id, $entry->id, $integrationKey ); } $parsedValue = $feed['processedValues']; if (!is_email($parsedValue['Email'])) { $parsedValue['Email'] = ArrayHelper::get( $formData, $parsedValue['Email'] ); } if (!is_email($parsedValue['Email'])) return $this->addLog( $feed['settings']['name'], 'failed', __("user registration skip because email is not valid.", 'fluentformpro'), $form->id, $entry->id, $integrationKey ); if (email_exists($parsedValue['Email'])) return $this->addLog( $feed['settings']['name'], 'failed', __("user registration skip because email is already taken other.", 'fluentformpro'), $form->id, $entry->id, $integrationKey ); if (!empty($parsedValue['username'])) { $userName = $this->getUsername($parsedValue['username'], $formData); if (is_array($userName)) { return $this->addLog( $feed['settings']['name'], 'failed', __("user registration skip because username is not valid data-type.", 'fluentformpro'), $form->id, $entry->id, $integrationKey ); } if ($userName && username_exists(sanitize_user($userName))) { return $this->addLog( $feed['settings']['name'], 'failed', __("user registration skip because username is already taken other.", 'fluentformpro'), $form->id, $entry->id, $integrationKey ); } if ($userName) { $parsedValue['username'] = sanitize_user($userName); } } if (empty($parsedValue['username'])) { $parsedValue['username'] = sanitize_user($parsedValue['Email']); } $feed['processedValues'] = $parsedValue; do_action_deprecated( 'fluentform_user_registration_before_start', [ $feed, $entry, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/user_registration_before_start', 'Use fluentform/user_registration_before_start instead of fluentform_user_registration_before_start.' ); do_action('fluentform/user_registration_before_start', $feed, $entry, $form); $this->createUser($feed, $formData, $entry, $form, $integrationKey); } protected function createUser($feed, $formData, $entry, $form, $integrationKey) { $feed = apply_filters_deprecated( 'fluentform_user_registration_feed', [ $feed, $entry, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/user_registration_feed', 'Use fluentform/user_registration_feed instead of fluentform_user_registration_feed.' ); $feed = apply_filters('fluentform/user_registration_feed', $feed, $entry, $form); $parsedData = $feed['processedValues']; $email = $parsedData['Email']; $userName = $parsedData['username']; if (empty($parsedData['password'])) { $password = wp_generate_password(8); } else { $password = $parsedData['password']; } $userId = wp_create_user($userName, $password, $email); if (is_wp_error($userId)) { return $this->addLog( $feed['settings']['name'], 'failed', $userId->get_error_message(), $form->id, $entry->id, $integrationKey ); } do_action_deprecated( 'fluentform_created_user', [ $userId, $feed, $entry, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/created_user', 'Use fluentform/created_user instead of fluentform_created_user.' ); do_action('fluentform/created_user', $userId, $feed, $entry, $form); Helper::setSubmissionMeta($entry->id, '__created_user_id', $userId); $this->updateUser($parsedData, $userId); $this->addUserRole($parsedData, $userId); $this->addUserMeta($parsedData, $userId, $form->id); $this->maybeLogin($parsedData, $userId, $entry); $this->maybeSendEmail($parsedData, $userId); $this->addLog( $feed['settings']['name'], 'success', __('user has been successfully created. Created User ID: ', 'fluentformpro') . $userId, $form->id, $entry->id, $integrationKey ); wpFluent()->table('fluentform_submissions') ->where('id', $entry->id) ->update([ 'user_id' => $userId ]); do_action_deprecated( 'fluentform_user_registration_completed', [ $userId, $feed, $entry, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/user_registration_completed', 'Use fluentform/user_registration_completed instead of fluentform_user_registration_completed.' ); do_action('fluentform/user_registration_completed', $userId, $feed, $entry, $form); } protected function addUserRole($parsedData, $userId) { $userRoles = $this->getUserRoles(); $assignedRole = $parsedData['userRole']; if (!isset($userRoles[$assignedRole])) { $assignedRole = 'subscriber'; } $user = new \WP_User($userId); $user->set_role($assignedRole); } protected function addUserMeta($parsedData, $userId, $formId) { $userMetas = []; foreach ($parsedData['userMeta'] as $userMeta) { $userMetas[$userMeta['label']] = $userMeta['item_value']; } $firstName = ArrayHelper::get($parsedData, 'first_name'); $lastName = ArrayHelper::get($parsedData, 'last_name'); $userMetas = array_merge($userMetas, [ 'first_name' => $firstName, 'last_name' => $lastName ]); if (!isset($userMetas['nickname'])) { $nickname = $firstName . ' ' . $lastName; // filter nickname for buddyboss integration $userMetas['nickname'] = $this->filteredNickname($nickname, $parsedData); } foreach ($userMetas as $metaKey => $metaValue) { if (AcfHelper::maybeUpdateWithAcf($metaKey, $metaValue, 'user_'.$userId)) { continue; } $metaValue = maybe_serialize($metaValue); if ($value = trim($metaValue)) { update_user_meta($userId, $metaKey, $value); } } update_user_meta($userId, 'fluentform_user_id', $formId); } protected function maybeLogin($parsedData, $userId, $entry = false) { if (ArrayHelper::isTrue($parsedData, 'enableAutoLogin')) { // check if it's payment success page // or direct url if(isset($_REQUEST['fluentform_payment_api_notify']) && $entry) { // This payment IPN request so let's keep a reference for real request Helper::setSubmissionMeta($entry->id, '_make_auto_login', $userId, $entry->form_id); return; } wp_clear_auth_cookie(); wp_set_current_user($userId); wp_set_auth_cookie($userId); } } protected function maybeSendEmail($parsedData, $userId) { if (ArrayHelper::isTrue($parsedData, 'sendEmailToNewUser')) { // This will send an email with password setup link \wp_new_user_notification($userId, null, 'user'); } } public function userRegistrationMapFields() { $fields = [ [ 'key' => 'Email', 'label' => __('Email Address', 'fluentformpro'), 'input_options' => 'emails', 'required' => true, ], [ 'key' => 'username', 'label' => __('Username', 'fluentformpro'), 'required' => false, 'input_options' => 'all', 'help_text' => __('Keep empty if you want the username and user email is the same', 'fluentformpro'), ], [ 'key' => 'first_name', 'label' => __('First Name', 'fluentformpro') ], [ 'key' => 'last_name', 'label' => __('Last Name', 'fluentformpro') ], [ 'key' => 'password', 'label' => __('Password', 'fluentformpro'), 'help_text' => __('Keep empty to be auto generated', 'fluentformpro') ] ]; $fields = apply_filters_deprecated( 'fluentform_user_registration_map_fields', [ $fields ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/user_registration_map_fields', 'Use fluentform/user_registration_map_fields instead of fluentform_user_registration_map_fields.' ); return apply_filters('fluentform/user_registration_map_fields', $fields); } } PK!D>>&src/Integrations/WebHook/Bootstrap.phpnu[app = $app; $this->registerHooks(); } public function registerHooks() { $isEnabled = $this->isEnabled(); add_filter('fluentform/global_addons', function ($addons) use ($isEnabled) { $addons['webhook'] = [ 'title' => 'Webhooks', 'category' => 'crm', 'description' => __('Broadcast your Fluent Forms Submission to any web api endpoint with the powerful webhook module.', 'fluentformpro'), 'logo' => fluentFormMix('img/integrations/webhook.png'), 'enabled' => ($isEnabled) ? 'yes' : 'no' ]; return $addons; }); if (!$isEnabled) { return; } // add_filter('fluentform/notifying_async_webhook', '__return_false'); add_filter('fluentform/global_notification_active_types', function ($types) { $types['fluentform_webhook_feed'] = 'webhook'; return $types; }, 20, 1); add_action('fluentform/integration_notify_fluentform_webhook_feed', array($this, 'notify'), 20, 4); add_filter('fluentform/form_settings_menu', array($this, 'addFormMenu'), 99, 1); add_action('wp_ajax_fluentform-get-webhooks', function () { Acl::verify('fluentform_forms_manager'); $this->getApiClient()->getWebHooks(); }); add_action('wp_ajax_fluentform-save-webhook', function () { Acl::verify('fluentform_forms_manager'); $this->getApiClient()->saveWebHook(); }); add_action('wp_ajax_fluentform-delete-webhook', function () { Acl::verify('fluentform_forms_manager'); $this->getApiClient()->deleteWebHook(); }); } public function addFormMenu($settingsMenus) { $settingsMenus['webhook'] = array( 'slug' => 'form_settings', 'hash' => 'webhook', 'route' => '/webhook', 'title' => $this->title, ); return $settingsMenus; } /* * For Handling Notifications broadcast */ public function notify($feed, $formData, $entry, $form) { $api = $this->getApiClient(); $response = $api->notify($feed, $formData, $entry, $form); if(is_wp_error($response)) { do_action('fluentform/integration_action_result', $feed, 'failed', $response->get_error_message()); return; } $code = ArrayHelper::get($response, 'response.code'); $responseBody = ArrayHelper::get($response, 'body'); if(!is_string($responseBody)) { $responseBody = 'unknown'; } if($code < 300) { // it's a success do_action('fluentform/integration_action_result', $feed, 'success', __('Webhook payload has been fired. Status Code: ' . $code . '& Response Body: ' . $responseBody, 'fluentformpro')); return; } do_action('fluentform/integration_action_result', $feed, 'failed', __('FAILED. Status Code: ' . '& Response Body: ' . $responseBody, 'fluentformpro')); } protected function getApiClient() { return new Client($this->app); } public function isEnabled() { $globalModules = get_option('fluentform_global_modules_status'); return $globalModules && isset($globalModules['webhook']) && $globalModules['webhook'] == 'yes'; } } PK!8bE (src/Integrations/WebHook/NotifyTrait.phpnu[getWebHookRequestHeaders($settings, $formData, $form, $entry->id); $requestMethod = $this->getWebHookRequestMethod($settings, $formData, $form, $entry->id); $requestData = $this->getWebHookRequestData($feed, $formData, $form, $entry); $requestUrl = $this->getWebHookRequestUrl( $settings, $formData, $form, $entry->id, $requestMethod, $requestData ); $requestFormat = $settings['request_format']; if (in_array($requestMethod, ['POST', 'PUT', 'PATCH']) && $requestFormat == 'JSON') { $requestHeaders['Content-Type'] = 'application/json'; $requestData = json_encode($requestData); } $sslVerify = apply_filters_deprecated( 'ff_webhook_ssl_verify', [ false ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/webhook_ssl_verify', 'Use fluentform/webhook_ssl_verify instead of ff_webhook_ssl_verify.' ); $payload = [ 'body' => !in_array($requestMethod, ['GET', 'DELETE']) ? $requestData : null, 'method' => $requestMethod, 'headers' => $requestHeaders, 'sslverify' => apply_filters('fluentform/webhook_ssl_verify', $sslVerify), ]; $payload = apply_filters_deprecated( 'fluentform_webhook_request_args', [ $payload, $settings, $formData, $form, $entry->id ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/webhook_request_args', 'Use fluentform/webhook_request_args instead of fluentform_webhook_request_args.' ); $payload = apply_filters( 'fluentform/webhook_request_args', $payload, $settings, $formData, $form, $entry->id ); $response = wp_remote_request($requestUrl, $payload); if (is_wp_error($response)) { $code = ArrayHelper::get($response, 'response.code'); throw new \Exception($response->get_error_message() .', with response code: '.$code, (int)$response->get_error_code()); } else { return $response; } } catch (\Exception $e) { return new \WP_Error('broke', $e->getMessage()); } } protected function getWebHookRequestMethod($settings, $data, $form, $entryId) { $method = $settings['request_method']; $method = apply_filters_deprecated( 'fluentform_webhook_request_method', [ $method, $settings, $data, $form, $entryId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/webhook_request_method', 'Use fluentform/webhook_request_method instead of fluentform_webhook_request_method.' ); $method = apply_filters( 'fluentform/webhook_request_method', $method, $settings, $data, $form, $entryId ); return strtoupper($method); } protected function getWebHookRequestHeaders($settings, $data, $form, $entryId) { if ($settings['with_header'] == 'nop') return []; $parsedHeaders = $settings['request_headers']; $requestHeaders = []; foreach ($parsedHeaders as $header) { $requestHeaders[$header['key']] = $header['value']; } $requestHeaders = apply_filters_deprecated( 'fluentform_webhook_request_headers', [ $requestHeaders, $settings, $data, $form, $entryId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/webhook_request_headers', 'Use fluentform/webhook_request_headers instead of fluentform_webhook_request_headers.' ); $requestHeaders = apply_filters( 'fluentform/webhook_request_headers', $requestHeaders, $settings, $data, $form, $entryId ); unset($requestHeaders[null]); return $requestHeaders; } protected function getWebHookRequestData($feed, $data, $form, $entry) { $settings = $feed['processedValues']; $formData = ArrayHelper::except($data, [ '_wp_http_referer', '__fluent_form_embded_post_id', '_fluentform_15_fluentformnonce' ]); $selectedData = []; if ($settings['request_body'] == 'all_fields') { $selectedData = $formData; $entry->user_inputs = Helper::replaceBrTag($entry->user_inputs); $submission = clone $entry; unset($submission->response); $selectedData['__submission'] = $submission; if($entry->payment_total) { $selectedData['__order_items'] = OrderData::getOrderItems($entry); $selectedData['__transactions'] = OrderData::getTransactions($entry->id); } } else { foreach ($settings['fields'] as $index => $input) { if ($name = Helper::getInputNameFromShortCode(ArrayHelper::get($feed, "settings.fields.$index.value", ''))) { $hasRepeaterOrGridField = FormFieldsParser::getField($form, ['repeater_field', 'tabular_grid'], $name); if ($hasRepeaterOrGridField && $value = ArrayHelper::get($formData, $name)) { $input['value'] = $value; } } $input['value'] = Helper::replaceBrTag($input['value']); if ("[]" == substr($input['key'], -2)) { // merge array data for same key inserting '[]' at last key $input['key'] = substr($input['key'], 0, -2); $selectedData[$input['key']][] = $input['value']; } else { $selectedData[$input['key']] = $input['value']; } } } $selectedData = apply_filters_deprecated( 'fluentform_webhook_request_data', [ $selectedData, $settings, $data, $form, $entry ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/webhook_request_data', 'Use fluentform/webhook_request_data instead of fluentform_webhook_request_data.' ); return apply_filters( 'fluentform/webhook_request_data', $selectedData, $settings, $data, $form, $entry ); } protected function getWebHookRequestUrl($settings, $data, $form, $entryId, $requestMethod, $requestData) { $url = $settings['request_url']; if (in_array($requestMethod, ['GET', 'DELETE']) && !empty($requestData)) { $url = add_query_arg($requestData, $url); } $url = apply_filters_deprecated( 'fluentform_webhook_request_url', [ $url, $settings, $data, $form, $entryId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/webhook_request_url', 'Use fluentform/webhook_request_url instead of fluentform_webhook_request_url.' ); return apply_filters( 'fluentform/webhook_request_url', $url, $settings, $data, $form, $entryId ); } } PK!Z%%#src/Integrations/WebHook/Client.phpnu[app = $app; parent::__construct( $this->metaKey, $app->request->get('form_id', false), true ); } /** * Get all notifications/feeds * @return JSON Response */ public function getWebHooks() { $response = [ 'integrations' => $this->getAll(), 'request_headers' => $this->getHeaders() ]; wp_send_json_success($response); } /** * Save GetResponse Feed * @return JSON Response */ public function saveWebHook() { $notification = $this->app->request->get('notification'); $notification_id = $this->app->request->get('notification_id'); $notification = json_decode($notification, true); $notification = fluentFormSanitizer( $this->validate($notification) ); if ($notification_id) { $this->update($notification_id, $notification); $message = __('Feed successfully updated', 'fluentformpro'); } else { $notification_id = $this->save($notification); $message = __('Feed successfully created', 'fluentformpro'); } wp_send_json_success(array( 'message' => $message, 'notification_id' => $notification_id ), 200); } /** * Delete GetResponse Feed * @return JSON Response */ public function deleteWebHook() { $this->delete($this->app->request->get('id')); wp_send_json_success(array( 'message' => __('Selected WebHook Feed is deleted', 'fluentformpro'), 'integrations' => $this->getAll() )); } /** * Validate inputs * @param array $notification * @return array $notification */ protected function validate($notification) { $validator = fluentValidator($notification, [ 'name' => 'required', 'request_body' => 'required', 'request_url' => 'required|url' ], [ 'name.required' => __('Feed Name is required', 'fluentformpro'), 'request_url.required' => __('Request URL is required', 'fluentformpro'), 'request_url.url' => __('Request URL format is invalid', 'fluentformpro'), 'request_body.required' => __('Request body is required', 'fluentformpro') ])->validate(); $errors = $validator->errors(); if (!$this->validateFields($notification)) { $errors['fields']['required'] = __('Field name is required', 'fluentformpro'); } if (!$this->validateHeaders($notification)) { $errors['headers']['required'] = __('Header name is required', 'fluentformpro'); } if ($errors) { wp_send_json_error(array( 'errors' => $errors, 'message' => __('Please fix the errors', 'fluentformpro') ), 400); } return $notification; } protected function validateFields($notification) { if ($notification['request_body'] != 'all_fields') { foreach ($notification['fields'] as $field) { if (empty($field['key'])) { return false; } } } return true; } protected function validateHeaders(&$notification) { if ($notification['with_header'] == 'yup') { foreach ($notification['request_headers'] as $key => &$header) { if (empty($header['key'])) { return false; } } } return true; } protected function getHeaders() { return array( array( 'label' => 'Accept', 'value' => 'Accept', 'possible_values' => [ 'title' => 'Accept Header Samples', 'shortcodes' => [ 'Accept: text/plain' => 'text/plain', 'Accept: text/html' => 'text/html', 'Accept: text/*' => 'text/*' ] ] ), array( 'label' => 'Accept-Charset', 'value' => 'Accept-Charset', 'possible_values' => [ 'title' => 'Accept-Charset Header Samples', 'shortcodes' => [ 'Accept-Charset: utf-8' => 'utf-8', 'Accept-Charset: iso-8859-1' => 'iso-8859-1' ] ] ), array( 'label' => 'Accept-Encoding', 'value' => 'Accept-Encoding', 'possible_values' => [ 'title' => 'Accept-Encoding Header Samples', 'shortcodes' => [ 'Accept-Encoding: gzip' => 'gzip', 'Accept-Encoding: compress' => 'compress', 'Accept-Encoding: deflate' => 'deflate', 'Accept-Encoding: br' => 'br', 'Accept-Encoding: identity' => 'identity', 'Accept-Encoding: *' => '*' ] ] ), array( 'label' => 'Accept-Language', 'value' => 'Accept-Language', 'possible_values' => [ 'title' => 'Accept-Language Header Samples', 'shortcodes' => [ 'Accept-Language: en' => 'en', 'Accept-Language: en-US' => 'en-US', 'Accept-Language: en-GR' => 'en-GR', 'Accept-Language: en-US,en;q=0.5' => 'en-US,en;q=0.5' ] ] ), array( 'label' => 'Accept-Datetime', 'value' => 'Accept-Datetime', ), array( 'label' => 'Authorization', 'value' => 'Authorization', ), array( 'label' => 'Cache-Control', 'value' => 'Cache-Control', ), array( 'label' => 'Connection', 'value' => 'Connection', ), array( 'label' => 'Cookie', 'value' => 'Cookie', ), array( 'label' => 'Content-Length', 'value' => 'Content-Length', ), array( 'label' => 'Content-Type', 'value' => 'Content-Type', ), array( 'label' => 'Date', 'value' => 'Date', ), array( 'label' => 'Expect', 'value' => 'Expect', ), array( 'label' => 'Forwarded', 'value' => 'Forwarded', ), array( 'label' => 'From', 'value' => 'From', ), array( 'label' => 'Host', 'value' => 'Host', ), array( 'label' => 'If-Match', 'value' => 'If-Match', ), array( 'label' => 'If-Modified-Since', 'value' => 'If-Modified-Since', ), array( 'label' => 'If-None-Match', 'value' => 'If-None-Match', ), array( 'label' => 'If-Range', 'value' => 'If-Range', ), array( 'label' => 'If-Unmodified-Since', 'value' => 'If-Unmodified-Since', ), array( 'label' => 'Max-Forwards', 'value' => 'Max-Forwards', ), array( 'label' => 'Origin', 'value' => 'Origin', ), array( 'label' => 'Pragma', 'value' => 'Pragma', ), array( 'label' => 'Proxy-Authorization', 'value' => 'Proxy-Authorization', ), array( 'label' => 'Range', 'value' => 'Range', ), array( 'label' => 'Referer', 'value' => 'Referer', ), array( 'label' => 'TE', 'value' => 'TE', ), array( 'label' => 'User-Agent', 'value' => 'User-Agent', ), array( 'label' => 'Upgrade', 'value' => 'Upgrade', ), array( 'label' => 'Via', 'value' => 'Via', ), array( 'label' => 'Warning', 'value' => 'Warning', ), ); } } PK!Rc%src/Integrations/Zapier/Bootstrap.phpnu[app = $app; $this->register(); } public function register() { $isEnabled = $this->isEnabled(); add_filter('fluentform/global_addons', function ($addons) use ($isEnabled) { $addons['zapier'] = [ 'title' => 'Zapier', 'category' => 'crm', 'description' => __('Fluent Forms Zapier module allows you to connect your WordPress forms with over 6000+ web apps.', 'fluentformpro'), 'logo' => fluentFormMix('img/integrations/zapier.png'), 'enabled' => ($isEnabled) ? 'yes' : 'no' ]; return $addons; }); if(!$isEnabled) { return; } // add_filter('fluentform/notifying_async_zapier', '__return_false'); add_filter('fluentform/global_notification_active_types', function ($types) { $types['fluentform_zapier_feed'] = 'zapier'; return $types; }, 20, 1); add_action('fluentform/integration_notify_fluentform_zapier_feed', array($this, 'notify'), 20, 4); add_filter('fluentform/form_settings_menu', array($this, 'addFormMenu')); add_action('wp_ajax_fluentform-get-zapier-notifications', function () { Acl::verify('fluentform_forms_manager'); $this->getApiClient()->getNotifications(); }); add_action('wp_ajax_fluentform-save-zapier-notification', function () { Acl::verify('fluentform_forms_manager'); $this->getApiClient()->saveNotification(); }); add_action('wp_ajax_fluentform-delete-zapier-notification', function () { Acl::verify('fluentform_forms_manager'); $this->getApiClient()->deleteNotification(); }); add_action('wp_ajax_fluentform-verify-endpoint-zapier', function () { Acl::verify('fluentform_forms_manager'); $this->getApiClient()->verifyEndpoint(); }); } public function addFormMenu($settingsMenus) { $settingsMenus['zapier'] = array( 'slug' => 'form_settings', 'hash' => 'zapier', 'route' => '/zapier', 'title' => $this->title, ); return $settingsMenus; } public function notify($feed, $formData, $entry, $form) { $response = $this->getApiClient()->notify($feed, $formData, $entry, $form); if(is_wp_error($response)) { do_action('fluentform/integration_action_result', $feed, 'failed', $response->get_error_message()); return; } $code = ArrayHelper::get($response, 'response.code'); if($code < 300) { // it's a success do_action('fluentform/integration_action_result', $feed, 'success', __('Zapier payload has been fired. Status Code: ', 'fluentformpro') . $code); return; } do_action('fluentform/integration_action_result', $feed, 'failed', __('Zapier payload maybe failed to the target server. Status Code: ', 'fluentformpro') . $code); } protected function getApiClient() { return new Client($this->app); } public function isEnabled() { $globalModules = get_option('fluentform_global_modules_status'); return $globalModules && isset($globalModules['zapier']) && $globalModules['zapier'] == 'yes'; } } PK!s/ 'src/Integrations/Zapier/NotifyTrait.phpnu[ $formData]; $payload = apply_filters_deprecated( 'fluentform_integration_data_zapier', [ $payload, $feed, $entry ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/integration_data_zapier', 'Use fluentform/integration_data_zapier instead of fluentform_integration_data_zapier.' ); $payload = apply_filters('fluentform/integration_data_zapier', $payload, $feed, $entry); $response = wp_remote_post($values['url'], $payload); if (is_wp_error($response)) { $code = ArrayHelper::get($response, 'response.code'); throw new \Exception($response->get_error_message() .', with response code: '.$code, (int)$response->get_error_code()); } else { return $response; } } catch (\Exception $e) { return new \WP_Error('broke', $e->getMessage()); } } public function verifyEndpoint() { $formId = intval($this->app->request->get('form_id')); $form = wpFluent()->table('fluentform_forms')->find($formId); $fields = array_map(function ($f) { return str_replace('.*', '', $f); }, array_keys(FormFieldsParser::getInputs($form))); $webHook = wpFluent() ->table($this->table) ->where('form_id', $formId) ->where('meta_key', $this->metaKey) ->first(); $webHook = json_decode($webHook->value); $requestData = json_encode( array_combine($fields, array_fill(0, count($fields), '')) ); $requestHeaders['Content-Type'] = 'application/json'; $payload = [ 'body' => $requestData, 'method' => 'POST', 'headers' => $requestHeaders ]; $response = wp_remote_request($webHook->url, $payload); if (is_wp_error($response)) { wp_send_json_error(array( 'message' => $response->get_error_message() ), 400); } wp_send_json_success(array( 'message' => __(__('Sample sent successfully.', 'fluentformpro')), )); } } PK!8n\u "src/Integrations/Zapier/Client.phpnu[app = $app; } /** * Get Zapier Feeds * @return JSON Response */ public function getNotifications() { $hooks = wpFluent() ->table($this->table) ->where('form_id', intval($this->app->request->get('form_id'))) ->where('meta_key', $this->metaKey) ->get(); if ($hooks) { $hooks = array_map(function($hook) { $hook->value = json_decode($hook->value); return $hook; }, $hooks); } wp_send_json_success($hooks); } /** * Save Zapier Feed * @return JSON Response */ public function saveNotification() { $request = $this->validate($this->app->request->all()); if (empty($request['id'])) { $id = $this->insertNotification($request); } else { $id = $this->updateNotification($request); } wp_send_json_success(['id' => $id]); } protected function insertNotification($request) { return wpFluent() ->table($this->table) ->insertGetId([ 'meta_key' => $this->metaKey, 'form_id' => $request['form_id'], 'value' => $request['value'] ]); } protected function updateNotification($request) { wpFluent() ->table($this->table) ->where('id', $id = $request['id']) ->update(['value' => $request['value']]); return $id; } /** * Delete Zapier Feed * @return JSON Response */ public function deleteNotification() { try { wpFluent() ->table($this->table) ->where('id', $this->app->request->get('id')) ->delete(); wp_send_json_success(); } catch(Exception $e) { wp_send_json_error(); } } protected function validate($request) { $validator = fluentValidator($request['value'], [ 'name' => 'required', 'url' => 'required|url' ]); if ($validator->validate()->fails()) { wp_send_json_error($validator->errors(), 422); } $request['value']['url'] = esc_url_raw($request['value']['url']); $request['value']['name'] = sanitize_text_field($request['value']['name']); $request['value'] = json_encode($request['value']); return $request; } } PK!<}a\a\&src/Integrations/ZohoCRM/Bootstrap.phpnu[logo = fluentFormMix('img/integrations/zohocrm.png'); $this->description = 'Zoho CRM is an online Sales CRM software that manages your sales, marketing and support in one CRM platform.'; $this->registerAdminHooks(); add_filter('fluentform/save_integration_value_' . $this->integrationKey, [$this, 'validate'], 10, 3); add_action('admin_init', function () { if (isset($_REQUEST['ff_zohocrm_auth'])) { $client = $this->getRemoteClient(); if (isset($_REQUEST['code'])) { // Get the access token now $code = sanitize_text_field($_REQUEST['code']); $settings = $this->getGlobalSettings([]); $settings = $client->generateAccessToken($code, $settings); if (!is_wp_error($settings)) { $settings['status'] = true; update_option($this->optionKey, $settings, 'no'); } wp_redirect(admin_url('admin.php?page=fluent_forms_settings#general-zohocrm-settings')); exit(); } else { $client->redirectToAuthServer(); } die(); } }); // add_filter('fluentform/notifying_async_zohocrm', '__return_false'); add_filter( 'fluentform/get_integration_values_zohocrm', [$this, 'resolveIntegrationSettings'], 100, 3 ); } public function getGlobalFields($fields) { return [ 'logo' => $this->logo, 'menu_title' => __('Zoho CRM Settings', 'fluentformpro'), 'menu_description' => __($this->description, 'fluentformpro'), 'valid_message' => __('Your Zoho CRM API Key is valid', 'fluentformpro'), 'invalid_message' => __('Your Zoho CRM API Key is not valid', 'fluentformpro'), 'save_button_text' => __('Save Settings', 'fluentformpro'), 'config_instruction' => $this->getConfigInstructions(), 'fields' => [ 'accountUrl' => [ 'type' => 'select', 'placeholder' => __('Your Zoho CRM Account URL', 'fluentformpro'), 'label_tips' => __("Please Choose your Zoho CRM Account URL", 'fluentformpro'), 'label' => __('Account URL', 'fluentformpro'), 'options' => [ 'https://accounts.zoho.com' => 'US', 'https://accounts.zoho.com.au' => 'AU', 'https://accounts.zoho.eu' => 'EU', 'https://accounts.zoho.in' => 'IN', 'https://accounts.zoho.com.cn' => 'CN', ] ], 'client_id' => [ 'type' => 'text', 'placeholder' => __('Zoho CRM Client ID', 'fluentformpro'), 'label_tips' => __("Enter your Zoho CRM Client ID, if you do not have
    Please login to your Zoho CRM account and go to Zoho Developer Console
    ", 'fluentformpro'), 'label' => __('Zoho CRM Client ID', 'fluentformpro'), ], 'client_secret' => [ 'type' => 'password', 'placeholder' => __('Zoho CRM Client Secret', 'fluentformpro'), 'label_tips' => __("Enter your Zoho CRM Key, if you do not have
    Please login to your Zoho CRM account and go to Zoho Developer Console", 'fluentformpro'), 'label' => __('Zoho CRM Client Secret', 'fluentformpro'), ], ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your Zoho CRM integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect Zoho CRM', 'fluentformpro'), 'data' => [ 'accountUrl' => '', 'client_id' => '', 'client_secret' => '' ], 'show_verify' => true ] ]; } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'accountUrl' => '', 'client_id' => '', 'client_secret' => '', 'status' => '', 'access_token' => '', 'refresh_token' => '', 'expire_at' => false ]; return wp_parse_args($globalSettings, $defaults); } public function saveGlobalSettings($settings) { $integrationSettings = array(); $err_msg = 'Error: Authorization info missing.'; $err = false; if (empty($settings['client_secret'])) { $integrationSettings['client_secret'] = ''; $err_msg = 'Client Secret is required'; $err = true; } if (empty($settings['client_id'])) { $integrationSettings['client_id'] = ''; $err_msg = 'Client Id is required'; $err = true; } if (empty($settings['accountUrl'])) { $integrationSettings['accountUrl'] = ''; $err_msg = 'Choose an account Url.'; $err = true; } if ($err) { $integrationSettings['status'] = false; update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_error([ 'message' => __($err_msg, 'fluentformpro'), 'status' => false ], 400); } // Verify API key now try { $oldSettings = $this->getGlobalSettings([]); $oldSettings['accountUrl'] = esc_url_raw($settings['accountUrl']); $oldSettings['client_id'] = sanitize_text_field($settings['client_id']); $oldSettings['client_secret'] = sanitize_text_field($settings['client_secret']); $oldSettings['status'] = false; update_option($this->optionKey, $oldSettings, 'no'); wp_send_json_success([ 'message' => __('You are being redirected to authenticate', 'fluentformpro'), 'redirect_url' => admin_url('?ff_zohocrm_auth=1') ], 200); } catch (\Exception $exception) { wp_send_json_error([ 'message' => $exception->getMessage() ], 400); } } public function getIntegrationDefaults($settings, $formId) { $name = $this->app->request->get('serviceName', ''); $listId = $this->app->request->get('serviceId', ''); return [ 'name' => $name, 'list_id' => $listId, 'other_fields' => [ [ 'item_value' => '', 'label' => '' ] ], 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'enabled' => true ]; } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => $this->title . ' Integration', 'logo' => $this->logo, 'is_active' => $this->isConfigured(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-zohocrm-settings'), 'configure_message' => __('Zoho CRM is not configured yet! Please configure your Zoho CRM api first', 'fluentformpro'), 'configure_button_text' => __('Set Zoho CRM API', 'fluentformpro') ]; return $integrations; } public function getSettingsFields($settings, $formId) { $fieldSettings = [ 'fields' => [ [ 'key' => 'name', 'label' => __('Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'list_id', 'label' => __('Services', 'fluentformpro'), 'placeholder' => __('Choose Service', 'fluentformpro'), 'required' => true, 'component' => 'refresh', 'options' => $this->getServices() ], ], 'button_require_list' => false, 'integration_title' => $this->title ]; $listId = $this->app->request->get( 'serviceId', Arr::get($settings, 'list_id') ); if ($listId) { $fields = $this->getFields($listId); $fields = array_merge($fieldSettings['fields'], $fields); $fieldSettings['fields'] = $fields; } $fieldSettings['fields'] = array_merge($fieldSettings['fields'], [ [ 'require_list' => false, 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow this integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => false, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable This feed', 'fluentformpro') ] ]); return $fieldSettings; } public function resolveIntegrationSettings($settings, $feed, $formId) { $serviceName = $this->app->request->get('serviceName', ''); $serviceId = $this->app->request->get('serviceId', ''); if ($serviceName) { $settings['name'] = $serviceName; } if ($serviceId) { $settings['list_id'] = $serviceId; } return $settings; } public function getMergeFields($list, $listId, $formId) { return false; } public function validate($settings, $integrationId, $formId) { $error = false; $errors = array(); foreach ($this->getFields($settings['list_id']) as $field){ if ($field['required'] && empty($settings[$field['key']])) { $error = true; $errors[$field['key']] = [__($field['label'].' is required', 'fluentformpro')]; } } if ($error){ wp_send_json_error([ 'message' => __('Validation Failed', 'fluentformpro'), 'errors' => $errors ], 423); } return $settings; } public function notify($feed, $formData, $entry, $form) { $feedData = $feed['processedValues']; $list_id = $feedData['list_id']; if (!$list_id) { do_action('fluentform/integration_action_result', $feed, 'failed', __('Skipped insert Zoho CRM feed data for missing Service Id.', 'fluentformpro')); return false; } list ($formattedMainFields, $formattedOtherFields) = $this->getFormattedFields($list_id); $postData = []; $tags = null; foreach ($formattedMainFields as $fieldName => $mainField) { $fieldValue = Arr::get($feedData, $fieldName); if ($mainField['required'] && empty($fieldValue)) { do_action('fluentform/integration_action_result', $feed, 'failed', __("Skipped insert Zoho CRM $list_id data for missing required value. Field: " . $fieldName . '.' , 'fluentformpro')); return false; } if (!empty($fieldValue)) { if ('Tag' == $fieldName) { $tags = $fieldValue; continue; } switch ($mainField['data_type']) { case 'email' : $value = sanitize_email($fieldValue); break; case 'date' : if (strstr($fieldValue, '/')) { $fieldValue = str_replace('/', '.', $fieldValue); } $date = new \Datetime($fieldValue); $value = $date->format('Y-m-d'); break; case 'datetime': if (strstr($fieldValue, '/')) { $fieldValue = str_replace('/', '.', $fieldValue); } $datetime = new \Datetime($fieldValue); $value = $datetime->format("c"); break; default: $value = sanitize_text_field($fieldValue); break; } $postData[$fieldName] = $value; } } if(!empty($feedData['other_fields'])){ foreach ($feedData['other_fields'] as $otherField){ $fieldName = Arr::get($otherField, 'label'); $fieldValue = Arr::get($otherField, 'item_value'); if(!empty($fieldName) && !empty($fieldValue)){ $fieldType = Arr::get($formattedOtherFields, $fieldName . '.data_type'); if ('textarea' == $fieldType) { $fieldValue = sanitize_textarea_field($fieldValue); } $postData[$fieldName] = $fieldValue; } } } $client = $this->getRemoteClient(); $response = $client->insertModuleData($list_id, $postData); if (is_wp_error($response)) { // it's failed do_action('fluentform/integration_action_result', $feed, 'failed', __('Failed to insert Zoho CRM feed. Details : ', 'fluentformpro') . $response->get_error_message()); } else { // It's success do_action('fluentform/integration_action_result', $feed, 'success', __('Zoho CRM feed has been successfully inserted ', 'fluentformpro') . $list_id . __(' data.', 'fluentformpro')); // update record tags if ($tags && $recordId = Arr::get($response, 'data.0.details.id')) { try { $client->addTags($list_id, $recordId, $tags); } catch (\Exception $e) { // ... } } } } protected function getFormattedFields($list_id) { $mainFields = $otherFields = array(); $client = $this->getRemoteClient(); $response = $client->getAllFields($list_id); if (!is_wp_error($response) && $fields = Arr::get($response,'fields')) { foreach ($fields as $field) { $fieldName = Arr::get($field, 'api_name'); $fieldType = Arr::get($field, 'data_type'); if (!$fieldName || !$fieldType) { continue; } if ($this->isMainField($field)) { $mainFields[$fieldName] = [ 'required' => Arr::isTrue($field,'system_mandatory'), 'data_type' => $fieldType, ]; } elseif ($this->isOtherField($field)) { $otherFields[$fieldName] = [ 'required' => Arr::isTrue($field,'system_mandatory'), 'data_type' => $fieldType, ]; } } } return [$mainFields, $otherFields]; } protected function getServices() { $client = $this->getRemoteClient(); $response = $client->getAllModules(); $services_options = array(); if (is_wp_error($response)) { return $services_options; } if ($response['modules']) { $services = $response['modules']; $availableServices = [ 'Leads', 'Contacts', 'Accounts', 'Deals', 'Tasks', 'Cases', 'Vendors', 'Solutions', 'Campaigns' ]; foreach ($services as $service) { $validService = $service['creatable'] && $service['global_search_supported'] && in_array($service['api_name'], $availableServices); if ($validService) { $services_options[$service['api_name']] = $service['singular_label']; } } } return $services_options; } protected function getFields($module_key) { $client = $this->getRemoteClient(); $response = $client->getAllFields($module_key); if (is_wp_error($response)) { return false; } $fields = array(); if ($response['fields']) { $others_fields = array(); foreach ($response['fields'] as $field) { if ($this->isMainField($field)) { $data = array( 'key' => $field['api_name'], 'placeholder' => __($field['display_label'], 'fluentformpro'), 'label' => __($field['field_label'], 'fluentformpro'), 'required' => false, 'tips' => __('Enter ' . $field['display_label'] . ' value or choose form input provided by shortcode.', 'fluentformpro'), 'component' => 'value_text' ); if ($field['system_mandatory']) { $data['required'] = true; $data['tips'] = __($field['display_label'] . ' is a required field. Enter value or choose form input provided by shortcode.', 'fluentformpro'); } if($field['data_type'] == 'datetime'){ $data['tips'] = __($field['display_label'] . ' is a required field. Enter value or choose form input shortcode.
    Make sure format is (01/01/2022 00:00 +0:00)', 'fluentformpro'); } if ($field['data_type'] == 'picklist' && $field['pick_list_values']) { $data['component'] = 'select'; $data['tips'] = __("Choose " . $field['display_label'] . " type in select list.", 'fluentformpro'); $data_options= array(); foreach ($field['pick_list_values'] as $option) { $data_options[$option['display_value']] = $option['display_value']; } $data['options'] = $data_options; } if ($field['data_type'] == 'textarea') { $data['component'] = 'value_textarea'; } $fields[] = $data; } elseif ($this->isOtherField($field)) { $others_fields[$field['api_name']] = $field['field_label']; } } if (!empty($others_fields)) { $fields[] = [ 'key' => 'other_fields', 'require_list' => false, 'required' => false, 'label' => __('Other Fields', 'fluentformpro'), 'tips' => __('Select which Fluent Forms fields pair with their respective Zoho crm modules fields.
    Field value must be string type.', 'fluentformpro'), 'component' => 'dropdown_many_fields', 'field_label_remote' => __('Others Field', 'fluentformpro'), 'field_label_local' => __('Others Field', 'fluentformpro'), 'options' => $others_fields ]; } } return $fields; } protected function isMainField($field) { return $field['system_mandatory'] || 'picklist' == $field['data_type'] || 'email' == $field['data_type'] || 'Tag' == $field['api_name']; } protected function isOtherField($field) { return in_array(Arr::get($field, 'data_type'), ['text', 'textarea', 'integer', 'website', 'phone', 'double', 'currency']); } protected function getConfigInstructions() { ob_start(); ?>

    To Authenticate Zoho CRM First you need to register your application with Zoho CRM.

    1. To register, Go to Zoho Developer Console.
    2. Choose a client type:
      Web Based: Applications that are running on a dedicated HTTP server.
      Note: No other client type allowed.
    3. Enter the following details:
      Client Name: The name of your application you want to register with Zoho.
      Homepage URL: The URL of your web page. Your site url
      Authorized Redirect URIs: Your app redirect url must be
    4. Click CREATE. You will receive the Client ID and Client Secret. Copy the Client Id and Client Secret.
    5. Then go back to your Zoho CRM setting page and choose your account URL, also paste the Client Id and Secret Id in the input bellow.
    6. Then save settings. You will be redirect to the Zoho CRM authorized page. Click Allow button for authorized.
    7. Note: If authorized successful you wil be redirected to the Zoho CRM settings page. If not you will see the error message on that page.
    getGlobalSettings([]); return new ZohoCRM( $settings['accountUrl'], $settings ); } }PK!I*t$src/Integrations/ZohoCRM/ZohoCRM.phpnu[apiUrl = 'https://www.zohoapis.com.'. end($apiDataServer).'/crm/v2/'; } else { $this->apiUrl = 'https://www.zohoapis.'. end($apiDataServer).'/crm/v2/'; } $this->accountUrl = $accountUrl; $this->clientId = $settings['client_id']; $this->clientSecret = $settings['client_secret']; $this->settings = $settings; $this->callBackUrl = admin_url('?ff_zohocrm_auth=1'); } public function redirectToAuthServer() { $url = add_query_arg([ 'scope' => 'ZohoCRM.users.ALL,ZohoCRM.modules.ALL,ZohoCRM.settings.ALL', 'client_id' => $this->clientId, 'access_type' => 'offline', 'redirect_uri' => $this->callBackUrl, 'response_type' => 'code' ], $this->accountUrl . '/oauth/v2/auth'); wp_redirect($url); exit(); } public function generateAccessToken($code, $settings) { $response = wp_remote_post($this->accountUrl . '/oauth/v2/token', [ 'body' => [ 'client_id' => $this->clientId, 'client_secret' => $this->clientSecret, 'grant_type' => 'authorization_code', 'redirect_uri' => $this->callBackUrl, 'code' => $code ] ]); if (is_wp_error($response)) { return $response; } $body = wp_remote_retrieve_body($response); $body = \json_decode($body, true); if (isset($body['error_description'])) { return new \WP_Error('invalid_client', $body['error_description']); } $settings['access_token'] = $body['access_token']; $settings['refresh_token'] = $body['refresh_token']; $settings['expire_at'] = time() + intval($body['expires_in']); return $settings; } public function make_request($action, $data = array(), $method = 'GET') { $settings = $this->getApiSettings(); if (is_wp_error($settings)) { return $settings; } $url = $this->apiUrl . $action; $response = false; $args = [ 'headers' => [ 'Authorization' => 'Zoho-oauthtoken ' . $settings['access_token'] ] ]; if ($method == 'GET') { $url = add_query_arg($data, $url); $response = wp_remote_get($url, $args); } else if ($method == 'POST') { $args['body'] = json_encode(['data' => [$data]]); $response = wp_remote_post($url, $args); } if (!$response) { return new \WP_Error('invalid', 'Request could not be performed'); } if (is_wp_error($response)) { return new \WP_Error('wp_error', $response->get_error_message()); } $body = wp_remote_retrieve_body($response); $body = \json_decode($body, true); if (isset($body['status']) && $body['status'] == 'error') { $message = $body['message']; return new \WP_Error('request_error', $message); } return $body; } protected function getApiSettings() { $this->maybeRefreshToken(); $apiSettings = $this->settings; if (!$apiSettings['status'] || !$apiSettings['expire_at']) { return new \WP_Error('invalid', 'API key is invalid'); } return array( 'baseUrl' => $this->apiUrl, 'version' => 'OAuth2', 'clientKey' => $this->clientId, 'clientSecret' => $this->clientSecret, 'callback' => $this->callBackUrl, 'access_token' => $apiSettings['access_token'], 'refresh_token' => $apiSettings['refresh_token'], 'expire_at' => $apiSettings['expire_at'] ); } protected function maybeRefreshToken() { $settings = $this->settings; $expireAt = $settings['expire_at']; if ($expireAt && $expireAt <= (time() - 10)) { // we have to regenerate the tokens $response = wp_remote_post($this->accountUrl . '/oauth/v2/token', [ 'body' => [ 'client_id' => $this->clientId, 'client_secret' => $this->clientSecret, 'grant_type' => 'refresh_token', 'refresh_token' => $settings['refresh_token'], 'redirect_uri' => $this->callBackUrl ] ]); if (is_wp_error($response)) { $settings['status'] = false; } $body = wp_remote_retrieve_body($response); $body = \json_decode($body, true); if (isset($body['error_description'])) { $settings['status'] = false; } $settings['access_token'] = $body['access_token']; $settings['expire_at'] = time() + intval($body['expires_in']); $this->settings = $settings; update_option('_fluentform_zohocrm_settings', $settings, 'no'); } } public function getAllModules() { return $this->make_request('settings/modules', [], 'GET'); } public function getAllFields($module_name) { return $this->make_request("settings/fields?module=$module_name", [], 'GET'); } public function insertModuleData($module_name, $data) { $response = $this->make_request($module_name, $data, 'POST'); if(!empty($response['data'][0]['details']['id'])){ return $response; } $err_msg = 'Date insert failed'; if($response['data'][0]['status'] == 'error'){ $err_msg = $response['data'][0]['message']; } return new \WP_Error('error', $err_msg); } public function addTags($module_name, $recordId, $tags) { return $this->make_request("$module_name/$recordId/actions/add_tags?tag_names=$tags", null, 'POST'); } }PK!B++'src/Payments/Classes/PaymentEntries.phpnu[
    '; } public function getPayments() { Acl::verify('fluentform_view_payments'); $perPage = intval($_REQUEST['per_page']); if(!$perPage) { $perPage = 10; } $paymentsQuery = wpFluent()->table('fluentform_transactions') ->select([ 'fluentform_transactions.id', 'fluentform_transactions.form_id', 'fluentform_transactions.submission_id', 'fluentform_transactions.transaction_type', 'fluentform_transactions.payment_method', 'fluentform_transactions.payment_mode', 'fluentform_transactions.charge_id', 'fluentform_transactions.card_brand', 'fluentform_transactions.payment_total', 'fluentform_transactions.created_at', 'fluentform_transactions.payer_name', 'fluentform_transactions.status', 'fluentform_transactions.currency', 'fluentform_forms.title' ]) ->join('fluentform_forms', 'fluentform_forms.id', '=', 'fluentform_transactions.form_id') ->orderBy('fluentform_transactions.id', 'DESC'); if ($selectedFormId = ArrayHelper::get($_REQUEST, 'form_id')) { $paymentsQuery = $paymentsQuery->where('fluentform_transactions.form_id', intval($selectedFormId)); } if ($paymentStatus = ArrayHelper::get($_REQUEST, 'payment_statuses')) { $paymentsQuery = $paymentsQuery->where('fluentform_transactions.status', sanitize_text_field($paymentStatus)); } if ($paymentMethods = ArrayHelper::get($_REQUEST, 'payment_methods')) { $paymentsQuery = $paymentsQuery->where('fluentform_transactions.payment_method', sanitize_text_field($paymentMethods)); } $paymentsPaginate = $paymentsQuery->paginate($perPage); $payments = $paymentsPaginate->items(); foreach ($payments as $payment) { $payment->formatted_payment_total = PaymentHelper::formatMoney($payment->payment_total, $payment->currency); $payment->entry_url = admin_url('admin.php?page=fluent_forms&route=entries&form_id='.$payment->form_id.'#/entries/'.$payment->submission_id); if($payment->payment_method == 'test') { $payment->payment_method = 'offline'; } $status = apply_filters_deprecated( 'ff_payment_entries_human_date', [ true ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_entries_human_date', 'Use fluentform/payment_entries_human_date instead of ff_payment_entries_human_date.' ); if(apply_filters('fluentform/payment_entries_human_date', $status)){ $payment->created_at = human_time_diff(strtotime($payment->created_at), strtotime(current_time('mysql'))); } } wp_send_json_success([ 'payments' => $payments, 'total' => $paymentsPaginate->total(), 'current_page' => $paymentsPaginate->currentPage(), 'per_page' => $paymentsPaginate->perPage(), 'last_page' => $paymentsPaginate->lastPage() ]); } public function handleBulkAction() { Acl::verify('fluentform_forms_manager'); $entries = wp_unslash($_REQUEST['entries']); $actionType = sanitize_text_field($_REQUEST['action_type']); if (!$actionType || !count($entries)) { wp_send_json_error([ 'message' => __('Please select entries & action first', 'fluentformpro') ], 400); } $message = __("Invalid action", 'fluentformpro'); $statusCode = 400; // permanently delete payment entries from transactions if ($actionType == 'delete_items') { // get submission ids to delete order items $transactionData = wpFluent()->table('fluentform_transactions') ->select(['form_id','submission_id']) ->whereIn ('fluentform_transactions.id',$entries) ->get(); $submission_ids = []; foreach ($transactionData as $transactionDatum) { $submission_ids[] = $transactionDatum->submission_id; } try { if( !$submission_ids || !$transactionData ){ throw new \Exception(__('Invalid transaction id', 'fluentformpro')); } do_action_deprecated( 'fluentform_before_entry_payment_deleted', [ $entries, $transactionData ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/before_entry_payment_deleted', 'Use fluentform/before_entry_payment_deleted instead of fluentform_before_entry_payment_deleted.' ); do_action('fluentform/before_entry_payment_deleted', $entries, $transactionData); //delete data from transaction table wpFluent()->table('fluentform_transactions') ->whereIn('id', $entries)->delete(); //delete data from order table wpFluent()->table('fluentform_order_items') ->whereIn('submission_id', $submission_ids)->delete(); // delete data from subscriptions table wpFluent()->table('fluentform_subscriptions') ->whereIn('submission_id', $submission_ids)->delete(); //add log in each form that payment record has been deleted foreach ($transactionData as $data){ $logData = [ 'parent_source_id' => $data->form_id, 'source_type' => 'submission_item', 'source_id' => $data->submission_id, 'component' => 'payment', 'status' => 'info', 'title' => __('Payment data successfully deleted', 'fluentformpro'), 'description' => __('Payment record cleared from transaction history and order items', 'fluentformpro'), ]; do_action('fluentform/log_data', $logData); } do_action_deprecated( 'fluentform_after_entry_payment_deleted', [ $entries, $transactionData ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/after_entry_payment_deleted', 'Use fluentform/after_entry_payment_deleted instead of fluentform_after_entry_payment_deleted.' ); do_action('fluentform/after_entry_payment_deleted', $entries, $transactionData); $message = __('Selected entries successfully deleted', 'fluentformpro'); $statusCode = 200; } catch (\Exception $exception) { $message = $exception->getMessage(); $statusCode = 400; } } wp_send_json_success([ 'message' => $message ], $statusCode); } public function getFilters() { $statuses = wpFluent()->table('fluentform_transactions') ->select('status') ->groupBy('status') ->get(); $statusTypes = PaymentHelper::getPaymentStatuses(); $formattedStatuses = []; foreach ($statuses as $status) { $formattedStatuses[] = ArrayHelper::get($statusTypes, $status->status, $status->status); } $forms = wpFluent()->table('fluentform_transactions') ->select('fluentform_transactions.form_id', 'fluentform_forms.title') ->groupBy('fluentform_transactions.form_id') ->orderBy('fluentform_transactions.form_id', 'DESC') ->join('fluentform_forms', 'fluentform_forms.id', '=', 'fluentform_transactions.form_id') ->get(); $formattedForms = []; foreach ($forms as $form) { $formattedForms[] = [ 'form_id' => $form->form_id, 'title' => $form->title ]; } $paymentMethods = wpFluent()->table('fluentform_transactions') ->select('payment_method') ->groupBy('payment_method') ->get(); $formattedMethods = []; foreach ($paymentMethods as $method) { if(!$method->payment_method){ continue; } if ($method->payment_method == 'test') { $formattedMethods[] = ['value' => __('Offline', 'fluentformpro'), 'key' => $method->payment_method]; } else { $formattedMethods[] = ['value' => ucfirst($method->payment_method), 'key' => $method->payment_method]; } } wp_send_json_success([ 'available_statuses' => $formattedStatuses, 'available_forms' => $formattedForms, 'available_methods' => array_filter($formattedMethods), ]); } } PK!]k&src/Payments/Classes/PaymentAction.phpnu[form = $form; $this->data = $data; $this->setSubmissionData($insertData); $this->setupData(); } private function setSubmissionData($insertData) { $insertData = (array)$insertData; $insertData['response'] = json_decode($insertData['response'], true); $this->submissionData = $insertData; } private function setupData() { $formFields = FormFieldsParser::getPaymentFields($this->form, ['admin_label', 'attributes', 'settings']); $paymentInputElements = ['custom_payment_component', 'multi_payment_component']; $quantityItems = []; $paymentInputs = []; $subscriptionInputs = []; $paymentMethod = false; $couponField = false; foreach ($formFields as $fieldKey => $field) { $element = ArrayHelper::get($field, 'element'); if (in_array($element, $paymentInputElements)) { $paymentInputs[$fieldKey] = $field; } else if ($element == 'item_quantity_component' || $element == 'rangeslider') { if ('rangeslider' == $element && 'yes' != ArrayHelper::get($field, 'settings.enable_target_product')) { continue; } if ($targetProductName = ArrayHelper::get($field, 'settings.target_product')) { $quantityItems[$targetProductName] = ArrayHelper::get($field, 'attributes.name'); } } else if ($element == 'payment_method') { $paymentMethod = $field; } else if ($element == 'payment_coupon') { $couponField = $field; } else if ($element === 'subscription_payment_component') { $subscriptionInputs[$fieldKey] = $field; } } $this->paymentInputs = $paymentInputs; $this->quantityItems = $quantityItems; $this->subscriptionInputs = $subscriptionInputs; if ($paymentMethod) { $this->methodField = $paymentMethod; if ($this->isConditionPass()) { $methodName = ArrayHelper::get($paymentMethod, 'attributes.name'); $this->selectedPaymentMethod = ArrayHelper::get($this->data, $methodName); $this->methodSettings = ArrayHelper::get($paymentMethod, 'settings.payment_methods.' . $this->selectedPaymentMethod); } } if ($couponField) { $couponCodes = ArrayHelper::get($this->data, '__ff_all_applied_coupons', ''); if ($couponCodes) { $couponCodes = \json_decode($couponCodes, true); if ($couponCodes) { $couponCodes = array_unique($couponCodes); $this->discountCodes = (new CouponModel())->getCouponsByCodes($couponCodes); $this->couponField = $couponField; } } } if ($this->subscriptionInputs) { // Maybe we have subscription items with bill times = 1 // Or if we have discount codes then we have to apply the discount codes $this->validateSubscriptionInputs(); } $this->applyDiscountCodes(); } public function isConditionPass() { $conditionSettings = ArrayHelper::get($this->methodField, 'settings.conditional_logics', []); if ( !$conditionSettings || !ArrayHelper::isTrue($conditionSettings, 'status') || !count(ArrayHelper::get($conditionSettings, 'conditions')) ) { return true; } $conditionFeed = ['conditionals' => $conditionSettings]; return ConditionAssesor::evaluate($conditionFeed, $this->data); } public function draftFormEntry() { // Record Payment Items $subscriptionItems = $this->getSubscriptionItems(); if (count($subscriptionItems) >= 2) { // We are not supporting multiple subscription items at this moment wp_send_json_error([ 'message' => __('Sorry, multiple subscription item is not supported', 'fluentformpro') ]); } $items = $this->getOrderItems(); /* * Some Payment Gateway like Stripe may add signup fee based on the $subscriptionItems. * So we are providing filter hook to do the much needed calculations. */ // if ($subscriptionItems) { // $items = apply_filters( // 'fluentform/submitted_payment_items_' . $this->selectedPaymentMethod, // $items, // $this->form, // $this->data, // $subscriptionItems // ); // // $this->orderItems = $items; // } $existingSubmission = $this->checkForExistingSubmission(); $formSettings = PaymentHelper::getFormSettings($this->form->id, 'public'); $submission = $this->submissionData; $submission['payment_status'] = 'pending'; $submission['payment_method'] = $this->selectedPaymentMethod; $submission['payment_type'] = $this->getPaymentType(); $submission['currency'] = $formSettings['currency']; $submission['response'] = json_encode($submission['response']); $submission['payment_total'] = $this->getCalculatedAmount(); $submission = apply_filters_deprecated( 'fluentform_with_payment_submission_data', [ $submission, $this->form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_submission_data', 'Use fluentform/payment_submission_data instead of fluentform_with_payment_submission_data.' ); $submission = apply_filters('fluentform/payment_submission_data', $submission, $this->form); if ($existingSubmission) { $insertId = $existingSubmission->id; wpFluent()->table('fluentform_submissions') ->where('id', $insertId) ->update($submission); // delete the existing transactions here if any wpFluent()->table('fluentform_transactions') ->where('submission_id', $insertId) ->delete(); } else { $insertId = wpFluent()->table('fluentform_submissions')->insertGetId($submission); $uidHash = md5(wp_generate_uuid4() . $insertId); Helper::setSubmissionMeta($insertId, '_entry_uid_hash', $uidHash, $this->form->id); $intermediatePaymentHash = md5('payment_' . wp_generate_uuid4() . '_' . $insertId . '_' . $this->form->id); Helper::setSubmissionMeta($insertId, '__entry_intermediate_hash', $intermediatePaymentHash, $this->form->id); } $submission['id'] = $insertId; $this->setSubmissionData($submission); $this->submissionId = $insertId; $paymentTotal = 0; if ($items) { foreach ($items as $index => $item) { $paymentTotal += $item['line_total']; $items[$index]['submission_id'] = $insertId; $items[$index]['form_id'] = $submission['form_id']; } } $this->insertOrderItems($items, $existingSubmission); $subsTotal = 0; if ($subscriptionItems && $existingSubmission) { wpFluent()->table('fluentform_subscriptions')->where('submission_id', $existingSubmission->id)->delete(); } foreach ($subscriptionItems as $subscriptionItem) { $quantity = isset($subscriptionItem['quantity']) ? $subscriptionItem['quantity'] : 1; $linePrice = $subscriptionItem['recurring_amount'] * $quantity; $subsTotal += intval($linePrice); $subscriptionItem['submission_id'] = $insertId; wpFluent()->table('fluentform_subscriptions')->insert($subscriptionItem); } do_action('fluentform/notify_on_form_submit', $this->submissionId, $this->submissionData['response'], $this->form); $totalPayable = $paymentTotal + $subsTotal; // We should make a transaction for subscription if ($this->selectedPaymentMethod) { Helper::setSubmissionMeta($insertId, '_selected_payment_method', $this->selectedPaymentMethod); do_action_deprecated( 'fluentform_process_payment', [ $this->submissionId, $this->submissionData, $this->form, $this->methodSettings, !!$subscriptionItems, $totalPayable ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/process_payment', 'Use fluentform/process_payment instead of fluentform_process_payment.' ); do_action('fluentform/process_payment', $this->submissionId, $this->submissionData, $this->form, $this->methodSettings, !!$subscriptionItems, $totalPayable); do_action_deprecated( 'fluentform_process_payment_' . $this->selectedPaymentMethod, [ $this->submissionId, $this->submissionData, $this->form, $this->methodSettings, !!$subscriptionItems, $totalPayable ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/process_payment_' . $this->selectedPaymentMethod, 'Use fluentform/process_payment_' . $this->selectedPaymentMethod . ' instead of fluentform_process_payment_' . $this->selectedPaymentMethod ); do_action('fluentform/process_payment_' . $this->selectedPaymentMethod, $this->submissionId, $this->submissionData, $this->form, $this->methodSettings, !!$subscriptionItems, $totalPayable); } /* * The following code will run only if no payment method catch and process the payment * In the payment method, ideally they will send the response. But if no payment method exist then * we will handle here */ $submission = wpFluent()->table('fluentform_submissions')->find($insertId); $returnData = (new SubmissionHandlerService())->processSubmissionData( $submission->id, $this->submissionData['response'], $this->form ); wp_send_json_success($returnData, 200); } public function getOrderItems($forced = false) { if ($forced) { $this->orderItems = []; } if ($this->orderItems) { return $this->orderItems; } $paymentInputs = $this->paymentInputs; if (!$paymentInputs && !$this->hookedOrderItems) { return []; } $data = $this->submissionData['response']; foreach ($paymentInputs as $paymentInput) { $name = ArrayHelper::get($paymentInput, 'attributes.name'); if (!$name || !isset($data[$name])) { continue; } $price = 0; $inputType = ArrayHelper::get($paymentInput, 'attributes.type'); if (!$data[$name]) { continue; } if ($inputType == 'number') { $price = $data[$name]; } else if ($inputType == 'single') { $price = ArrayHelper::get($paymentInput, 'attributes.value'); if (ArrayHelper::get($paymentInput, 'settings.dynamic_default_value')) { $price = $data[$name]; } } else if ($inputType == 'radio' || $inputType == 'select') { $item = $this->getItemFromVariables($paymentInput, $data[$name]); if ($item) { $quantity = $this->getQuantity($item['parent_holder']); if (!$quantity) { continue; } $item['quantity'] = $quantity; $this->pushItem($item); } continue; } else if (ArrayHelper::get($paymentInput, 'attributes.type') == 'checkbox') { $selectedItems = $data[$name]; foreach ($selectedItems as $selectedItem) { $item = $this->getItemFromVariables($paymentInput, $selectedItem); if ($item) { $quantity = $this->getQuantity($item['parent_holder']); if (!$quantity) { continue; } $item['quantity'] = $quantity; $this->pushItem($item); } } continue; } if (!is_numeric($price) || !$price) { continue; } $productName = ArrayHelper::get($paymentInput, 'attributes.name'); $quantity = $this->getQuantity($productName); if (!$quantity) { continue; } $this->pushItem([ 'parent_holder' => $productName, 'item_name' => ArrayHelper::get($paymentInput, 'admin_label'), 'item_price' => $price, 'quantity' => $quantity ]); } // We may have initial amount from the subscription if ($this->hookedOrderItems) { $this->orderItems = array_merge($this->orderItems, $this->hookedOrderItems); } $this->orderItems = apply_filters_deprecated( 'fluentform_submission_order_items', [ $this->orderItems, $this->submissionData, $this->form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/submission_order_items', 'Use fluentform/submission_order_items instead of fluentform_submission_order_items.' ); $this->orderItems = apply_filters('fluentform/submission_order_items', $this->orderItems, $this->submissionData, $this->form); return $this->orderItems; } private function getQuantity($productName) { $quantity = 1; if (!$this->quantityItems) { return $quantity; } if (!isset($this->quantityItems[$productName])) { return $quantity; } $inputName = $this->quantityItems[$productName]; $quantity = ArrayHelper::get($this->submissionData['response'], $inputName); if (!$quantity) { return 0; } return intval($quantity); } private function pushItem($data) { if (!$data['item_price']) { return; } $data['item_price'] = floatval($data['item_price'] * 100); $defaults = [ 'type' => 'single', 'form_id' => $this->form->id, 'quantity' => !empty($data['quantity']) ? $data['quantity'] : 1, 'created_at' => current_time('mysql'), 'updated_at' => current_time('mysql') ]; $item = wp_parse_args($data, $defaults); $item['line_total'] = $item['item_price'] * $item['quantity']; if (!$this->orderItems) { $this->orderItems = []; } $this->orderItems[] = $item; } private function getItemFromVariables($item, $key) { $elementName = $item['element']; $pricingOptions = ArrayHelper::get($item, 'settings.pricing_options'); $pricingOptions = apply_filters_deprecated( 'fluentform_payment_field_' . $elementName . '_pricing_options', [ $pricingOptions, $item, $this->form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_field_' . $elementName . '_pricing_options', 'Use fluentform/payment_field_' . $elementName . '_pricing_options instead of fluentform_payment_field_' . $elementName . '_pricing_options.' ); $pricingOptions = apply_filters('fluentform/payment_field_' . $elementName . '_pricing_options', $pricingOptions, $item, $this->form); $selectedOption = []; foreach ($pricingOptions as $priceOption) { $label = sanitize_text_field($priceOption['label']); $value = sanitize_text_field($priceOption['value']); if ($label == $key || $value == $key) { $selectedOption = $priceOption; } } if (!$selectedOption || empty($selectedOption['value']) || !is_numeric($selectedOption['value'])) { return false; } return [ 'parent_holder' => ArrayHelper::get($item, 'attributes.name'), 'item_name' => $selectedOption['label'], 'item_price' => $selectedOption['value'] ]; } public function getCalculatedAmount() { $items = $this->getOrderItems(); $total = 0; foreach ($items as $item) { if ($item['type'] == 'discount') { $total -= $item['line_total']; } else { $total += $item['line_total']; } } return $total; } public function getPaymentType() { return count($this->getSubscriptionItems()) ? 'subscription' : 'product'; // return value product|subscription|donation } private function getCurrency() { if ($this->currency !== null) { return $this->currency; } $this->currency = 'usd'; return $this->currency; } public function getSubscriptionItems() { if ($this->subscriptionItems) { return $this->subscriptionItems; } $data = $this->submissionData['response']; $subscriptionInputs = $this->subscriptionInputs; if (!$subscriptionInputs) { return []; } foreach ($subscriptionInputs as $subscriptionInput) { $name = ArrayHelper::get($subscriptionInput, 'attributes.name'); $quantity = $this->getQuantity($name); if (!$name || !isset($data[$name]) || $quantity === 0) { continue; } $label = ArrayHelper::get($subscriptionInput, 'settings.label', $name); $subscriptionOptions = ArrayHelper::get($subscriptionInput, 'settings.subscription_options'); $plan = $subscriptionOptions[$data[$name]]; if (!$plan) { continue; } if (ArrayHelper::get($plan, 'user_input') === 'yes') { $plan['subscription_amount'] = ArrayHelper::get($data, $name . '_custom_' . $data[$name]); $plan['subscription_amount'] = $plan['subscription_amount'] ?: 0; } $noTrial = ArrayHelper::get($plan, 'has_trial_days') === 'no' || !ArrayHelper::get($plan, 'trial_days'); if (!$plan['subscription_amount'] && $noTrial) { continue; } if (ArrayHelper::get($plan, 'bill_times') == 1 && ArrayHelper::get($plan, 'has_trial_days') != 'yes') { // Since the billing times is 1 and no trial days, // the subscription acts like as an one time payment. // We'll convert this as a payment item. $signupFee = 0; if ($plan['has_signup_fee'] === 'yes') { $signupFee = PaymentHelper::convertToCents($plan['signup_fee']); } $onetimeTotal = $signupFee + PaymentHelper::convertToCents($plan['subscription_amount']); $this->pushItem([ 'parent_holder' => $name, 'item_name' => $label, 'quantity' => $quantity, 'item_price' => $onetimeTotal, 'line_total' => $quantity * $onetimeTotal, 'created_at' => current_time('mysql'), 'updated_at' => current_time('mysql') ]); } else { $subscription = array( 'element_id' => $name, 'item_name' => $label, 'form_id' => $this->form->id, 'plan_name' => $plan['name'], 'billing_interval' => $plan['billing_interval'], 'trial_days' => 0, 'recurring_amount' => PaymentHelper::convertToCents($plan['subscription_amount']), 'bill_times' => (isset($plan['bill_times'])) ? $plan['bill_times'] : 0, 'initial_amount' => 0, 'status' => 'pending', 'original_plan' => maybe_serialize($plan), 'created_at' => current_time('mysql'), 'updated_at' => current_time('mysql'), ); if (ArrayHelper::get($plan, 'has_signup_fee') === 'yes' && ArrayHelper::get($plan, 'signup_fee')) { $subscription['initial_amount'] = PaymentHelper::convertToCents($plan['signup_fee']); } if (ArrayHelper::get($plan, 'has_trial_days') === 'yes' && ArrayHelper::get($plan, 'trial_days')) { $subscription['trial_days'] = $plan['trial_days']; $dateTime = current_datetime(); $localtime = $dateTime->getTimestamp() + $dateTime->getOffset(); $expirationDate = gmdate('Y-m-d H:i:s', $localtime + absint($plan['trial_days']) * 86400); $subscription['expiration_at'] = $expirationDate; } if ($quantity > 1) { $subscription['quantity'] = $quantity; } $this->subscriptionItems[] = $subscription; } } $this->subscriptionItems = apply_filters_deprecated( 'fluentform_submission_subscription_items', [ $this->subscriptionItems, $this->submissionData, $this->form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/submission_subscription_items', 'Use fluentform/submission_subscription_items instead of fluentform_submission_subscription_items.' ); $this->subscriptionItems = apply_filters('fluentform/submission_subscription_items', $this->subscriptionItems, $this->submissionData, $this->form); return $this->subscriptionItems; } private function checkForExistingSubmission() { $entryUid = ArrayHelper::get($this->submissionData, 'response.__entry_intermediate_hash'); if (!$entryUid) { return false; } $meta = wpFluent()->table('fluentform_submission_meta') ->where('meta_key', '__entry_intermediate_hash') ->where('value', $entryUid) ->where('form_id', $this->form->id) ->first(); if (!$meta) { return false; } $submission = wpFluent()->table('fluentform_submissions')->find($meta->response_id); if ($submission && ($submission->payment_status == 'failed' || $submission->payment_status == 'pending' || $submission->payment_status == 'draft')) { return $submission; } return false; } private function insertOrderItems($items, $existing = false) { if (!$existing) { foreach ($items as $item) { wpFluent()->table('fluentform_order_items')->insert($item); } return true; } if (!$items && $existing) { wpFluent()->table('fluentform_order_items')->where('submission_id', $existing->id)->delete(); return true; } $exitingItems = wpFluent()->table('fluentform_order_items')->where('submission_id', $existing->id)->get(); if (!$exitingItems) { foreach ($items as $item) { wpFluent()->table('fluentform_order_items')->insert($item); } return true; } $existingHashes = []; foreach ($exitingItems as $exitingItem) { $hash = md5($exitingItem->type . ':' . $exitingItem->parent_holder . ':' . $exitingItem->item_name . ':' . $exitingItem->quantity . ':' . $exitingItem->item_price); $existingHashes[$exitingItem->id] = $hash; } $verifiedIds = []; $newIds = []; foreach ($items as $item) { $hash = md5($item['type'] . ':' . $item['parent_holder'] . ':' . $item['item_name'] . ':' . $item['quantity'] . ':' . $item['item_price']); if (in_array($hash, $existingHashes)) { // already exist no need to add $verifiedIds[] = array_search($hash, $existingHashes); } else { $newId = wpFluent()->table('fluentform_order_items')->insertGetId($item); $verifiedIds[] = $newId; $newIds[] = $newId; } } if ($verifiedIds) { wpFluent()->table('fluentform_order_items') ->whereNotIn('id', $verifiedIds) ->delete(); } return true; } private function validateSubscriptionInputs() { $subscriptionInputs = $this->subscriptionInputs; if (!$subscriptionInputs) { return; } $data = $this->submissionData['response']; $discountCodes = $this->discountCodes; foreach ($subscriptionInputs as $inputIndex => $subscriptionInput) { $name = ArrayHelper::get($subscriptionInput, 'attributes.name'); $quantity = $this->getQuantity($name); if (!$quantity) { continue; } if (!$name || !isset($data[$name])) { continue; } $subscriptionOptions = ArrayHelper::get($subscriptionInput, 'settings.subscription_options'); $plan = $subscriptionOptions[$data[$name]]; if (!$plan) { continue; } if ($discountCodes) { } if (ArrayHelper::get($plan, 'has_trial_days') == 'yes' && ArrayHelper::get($plan, 'trial_days')) { continue; // this is a valid subscription } if (ArrayHelper::get($plan, 'bill_times') != 1) { continue; } // We have bill times 1 so we have to remove this and push to hooked inputs and later merged to payment inputs if (ArrayHelper::get($plan, 'user_input') === 'yes') { $plan['subscription_amount'] = ArrayHelper::get($data, $name . '_custom_' . $data[$name]); $plan['subscription_amount'] = $plan['subscription_amount'] ?: 0; } $amount = PaymentHelper::convertToCents($plan['subscription_amount']); if (ArrayHelper::get($plan, 'has_signup_fee') === 'yes' && ArrayHelper::get($plan, 'signup_fee')) { $amount += PaymentHelper::convertToCents($plan['signup_fee']); } $this->hookedOrderItems[] = [ 'type' => 'single', 'form_id' => $this->form->id, 'parent_holder' => $name, 'item_name' => ArrayHelper::get($subscriptionInput, 'admin_label') . ' (' . $plan['name'] . ')', 'item_price' => $amount, 'quantity' => $quantity, 'line_total' => $quantity * $amount, 'created_at' => current_time('mysql'), 'updated_at' => current_time('mysql'), ]; unset($this->subscriptionInputs[$inputIndex]); } } protected function applyDiscountCodes() { if (!$this->discountCodes) { return false; } $orderItems = $this->getOrderItems(true); $subTotal = array_sum(array_column($orderItems, 'line_total')) / 100; $subscriptionItems = $this->getSubscriptionItems(); $subInitialTotal = 0; foreach ($subscriptionItems as $subscriptionItem) { if ($subscriptionItem['trial_days']) { continue; // it's a trial } $subInitialTotal += $subscriptionItem['recurring_amount'] + $subscriptionItem['initial_amount']; } $grandTotal = $subTotal; if ($subInitialTotal) { $grandTotal += ($subInitialTotal / 100); } $fixedAmountApplied = 0; // in cents $couponModel = new CouponModel(); $this->discountCodes = $couponModel->getValidCoupons($this->discountCodes, $this->form->id, $grandTotal); foreach ($this->discountCodes as $coupon) { $discountAmount = $coupon->amount; if ($coupon->coupon_type == 'percent') { $discountAmount = (floatval($coupon->amount) / 100) * $subTotal; } else { if ($subTotal >= $discountAmount) { $fixedAmountApplied += $discountAmount; } else { $discountAmount = $subTotal; $fixedAmountApplied += $subTotal; } } $this->pushItem([ 'parent_holder' => ArrayHelper::get($this->couponField, 'attributes.name'), 'item_name' => $coupon->title, 'item_price' => $discountAmount, // this is not cent. We convert to cent at pushItem method 'quantity' => 1, 'type' => 'discount' ]); $subTotal = $subTotal - $discountAmount; } // let's convert to cents now as all subscriptions calculations are on cents $fixedAmountApplied = intval($fixedAmountApplied * 100); if (!$subscriptionItems) { return true; } $fixedMaxTotal = 0; $hasFixedDiscounts = false; foreach ($this->discountCodes as $discountCode) { if($discountCode->coupon_type == 'fixed') { $fixedMaxTotal += intval($coupon->amount * 100); $hasFixedDiscounts = true; } } $fixedMaxTotal = $fixedMaxTotal - $fixedAmountApplied; foreach ($subscriptionItems as $subIndex => $subscriptionItem) { $recurringAmount = $subscriptionItem['recurring_amount']; $signupFee = 0; if ($subscriptionItem['initial_amount']) { $signupFee = $subscriptionItem['initial_amount']; } // Let's process the percentile discounts first foreach ($this->discountCodes as $coupon) { $discountAmount = $coupon->amount; if ($coupon->coupon_type == 'percent') { $discountRecurringAmount = floatval((floatval($discountAmount) / 100) * $recurringAmount); $recurringAmount -= $discountRecurringAmount; if ($signupFee) { $discountSignupDiscountAmount = floatval((floatval($discountAmount) / 100) * $signupFee); $signupFee -= $discountSignupDiscountAmount; } } } if($hasFixedDiscounts && $fixedMaxTotal > 0) { if($fixedMaxTotal >= $subInitialTotal) { $recurringAmount = 0; $signupFee = 0; } else { $recurringAmount = $recurringAmount - ($fixedMaxTotal / $subInitialTotal) * $recurringAmount; if($signupFee > 0) { $signupFee = $signupFee - ($fixedMaxTotal / $subInitialTotal) * $signupFee; } } } $subscriptionItems[$subIndex]['recurring_amount'] = intval($recurringAmount); $subscriptionItems[$subIndex]['initial_amount'] = intval($signupFee); $originalPlan = maybe_unserialize($subscriptionItem['original_plan']); $originalPlan['subscription_amount'] = round($recurringAmount / 100, 2); $originalPlan['signup_fee'] = round($recurringAmount / 100, 2); $subscriptionItems[$subIndex]['original_plan'] = maybe_serialize($originalPlan); } $this->subscriptionItems = $subscriptionItems; return true; } } PK!R4a*src/Payments/Classes/PaymentManagement.phpnu[status, $validStatuses)) { return new \WP_Error('wrong_status', 'Sorry, You can not cancel this subscription'); } $oldStatus = $subscription->status; $newStatus = 'cancelled'; $submission = fluentFormApi('submissions')->find($subscription->submission_id); // Now let's try to cancel this subscription $handler = apply_filters_deprecated( 'fluentform_payment_manager_class_' . $submission->payment_method, [ false ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_manager_class_' . $submission->payment_method, 'Use fluentform/payment_manager_class_' . $submission->payment_method . ' instead of fluentform_payment_manager_class_' . $submission->payment_method ); $handler = apply_filters('fluentform/payment_manager_class_' . $submission->payment_method, $handler); $message = 'Subscription has been marked as cancelled'; if($handler) { // we have handler so the subscription cancellation will be managed by them $response = $handler->cancelSubscription($subscription, 'admin', $submission); if(is_wp_error($response)) { return $response; } } else { PaymentHelper::recordSubscriptionCancelled($subscription, false, [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'General', 'status' => 'info', 'title' => __('Subscription has been cancelled by admin', 'fluentformpro'), 'description' => __('Subscription has been cancelled locally. Subscription may not cancelled at ', 'fluentformpro') . $submission->payment_method ]); } do_action_deprecated( 'fluentform_payment_subscription_status_to_cancelled', [ $subscription, $submission, $oldStatus ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_subscription_status_to_cancelled', 'Use fluentform/payment_subscription_status_to_cancelled instead of fluentform_payment_subscription_status_to_cancelled.' ); do_action('fluentform/payment_subscription_status_to_cancelled', $subscription, $submission, $oldStatus); do_action_deprecated( 'fluentform_payment_subscription_status_' . $submission->payment_method . '_to_' . $newStatus, [ $subscription, $submission, $oldStatus ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_subscription_status_' . $submission->payment_method . '_to_' . $newStatus, 'Use fluentform/payment_subscription_status_' . $submission->payment_method . '_to_' . $newStatus . ' instead of fluentform_payment_subscription_status_' . $submission->payment_method . '_to_' . $newStatus ); do_action('fluentform/payment_subscription_status_' . $submission->payment_method . '_to_' . $newStatus, $subscription, $submission, $oldStatus); return $message; } } PK!-/L})})'src/Payments/Classes/PaymentReceipt.phpnu[entry = $entry; } public function getItem($property) { $methodMaps = [ 'receipt' => 'renderReceipt', 'summary' => 'paymentInfo', 'summary_list' => 'paymentInfoTable', 'order_items' => 'itemDetails', 'subscription_items' => 'subscriptionDetails' ]; $submissionMaps = [ 'payment_status', 'payment_total', 'payment_method' ]; if(isset($methodMaps[$property])) { $html = $this->{$methodMaps[$property]}(); $html .= $this->loadCss(); return $html; } if(in_array($property, $submissionMaps)) { return $this->getSubmissionValue($property); } return ''; } public function getSubmissionValue($property) { if($property == 'payment_total') { return OrderData::getTotalPaid($this->entry); } $value = ''; if(property_exists($this->entry, $property)) { $value = $this->entry->{$property}; } if($property == 'payment_method' && $value == 'test') { return __('Offline', 'fluentformpro'); } return ucfirst($value); } public function getOrderItems() { if (!is_null($this->orderItems)) { return $this->orderItems; } $this->orderItems = OrderData::getOrderItems($this->entry); return $this->orderItems; } private function getSubscriptions() { if (!is_null($this->subscriptions)) { return $this->subscriptions; } list($subscriptions, $total) = OrderData::getSubscriptionsAndPaymentTotal($this->entry); $this->subscriptions = $subscriptions; $this->subscriptionTotal = PaymentHelper::formatMoney($total, $this->entry->currency); return $this->subscriptions; } public function getDiscountItems() { if (!is_null($this->discountItems)) { return $this->discountItems; } $this->discountItems = OrderData::getDiscounts($this->entry); return $this->discountItems; } public function renderReceipt() { $submission = $this->entry; if (!$submission) { return '

    ' . __('Invalid submission. No receipt found', 'fluentformpro') . '

    '; } $html = $this->beforePaymentReceipt(); $html .= $this->paymentInfo(); if ($this->orderItems) { $html .= '

    ' . __('Order Details', 'fluentformpro') . '

    '; $html .= $this->itemDetails(); } if ($this->subscriptions) { $html .= '

    ' . __('Subscriptions', 'fluentformpro') . '

    '; $html .= $this->subscriptionDetails(); } $html .= $this->customerDetails(); $html .= $this->afterPaymentReceipt(); $html .= $this->loadCss(); return $html; } private function beforePaymentReceipt() { ob_start(); echo '
    '; do_action_deprecated( 'fluentform_payment_receipt_before_content', [ $this->entry ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_receipt_before_content', 'Use fluentform/payment_receipt_before_content instead of fluentform_partial_submission_step_completed.' ); do_action('fluentform/payment_receipt_before_content', $this->entry); return ob_get_clean(); } private function afterPaymentReceipt() { ob_start(); do_action_deprecated( 'fluentform_payment_receipt_after_content', [ $this->entry ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_receipt_after_content', 'Use fluentform/payment_receipt_after_content instead of fluentform_payment_receipt_after_content.' ); do_action('fluentform/payment_receipt_after_content', $this->entry); echo '
    '; return ob_get_clean(); } private function paymentInfo() { $preRender = apply_filters_deprecated( 'fluentform_payment_receipt_pre_render_payment_info', [ '', $this->entry ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_receipt_pre_render_payment_info', 'Use fluentform/payment_receipt_pre_render_payment_info instead of fluentform_payment_receipt_pre_render_payment_info.' ); $preRender = apply_filters('fluentform/payment_receipt_pre_render_payment_info', $preRender, $this->entry); if ($preRender) { return $preRender; } $orderItems = $this->getOrderItems(); $subscriptions = $this->getSubscriptions(); if (!$orderItems && !$subscriptions) { return; } $submission = $this->entry; if($submission->payment_method == 'test') { $submission->payment_method = __('Offline', 'fluentformpro'); } $discountItems = $this->getDiscountItems(); return $this->loadView('payment_info', array( 'submission' => $submission, 'items' => $orderItems, 'discount_items' => $discountItems, 'totalPaid' => OrderData::getTotalPaid($submission) )); } private function paymentInfoTable() { $preRender = apply_filters_deprecated( 'fluentform_payment_receipt_pre_render_payment_info_list', [ '', $this->entry ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_receipt_pre_render_payment_info_list', 'Use fluentform/payment_receipt_pre_render_payment_info_list instead of fluentform_payment_receipt_pre_render_payment_info_list.' ); $preRender = apply_filters('fluentform/payment_receipt_pre_render_payment_info_list', $preRender, $this->entry); if ($preRender) { return $preRender; } $orderItems = $this->getOrderItems(); if (!$orderItems) { return ''; } $discountItems = $this->getDiscountItems(); return $this->loadView('payment_info_list', array( 'submission' => $this->entry, 'items' => $orderItems, 'orderTotal' => OrderData::calculateOrderItemsTotal($orderItems, true, $this->entry->currency, $discountItems) )); } private function itemDetails() { $orderItems = $this->getOrderItems(); $preRender = apply_filters_deprecated( 'fluentform_payment_receipt_pre_render_item_details', [ '', $this->entry, $orderItems ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_receipt_pre_render_item_details', 'Use fluentform/payment_receipt_pre_render_item_details instead of fluentform_payment_receipt_pre_render_item_details.' ); $preRender = apply_filters('fluentform/payment_receipt_pre_render_item_details', $preRender, $this->entry, $orderItems); if ($preRender) { return $preRender; } if (!$orderItems) { return ''; } $discountItems = $this->getDiscountItems(); return $this->loadView('order_items_table', array( 'submission' => $this->entry, 'items' => $orderItems, 'discount_items' => $discountItems, 'subTotal' => OrderData::calculateOrderItemsTotal($orderItems, true, $this->entry->currency), 'orderTotal' => OrderData::calculateOrderItemsTotal($orderItems, true, $this->entry->currency, $discountItems) )); } private function customerDetails() { $preRender = apply_filters_deprecated( 'fluentform_payment_receipt_pre_render_submission_details', [ '', $this->entry ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_receipt_pre_render_submission_details', 'Use fluentform/payment_receipt_pre_render_submission_details instead of fluentform_payment_receipt_pre_render_submission_details.' ); $preRender = apply_filters('fluentform/payment_receipt_pre_render_submission_details', $preRender, $this->entry); if ($preRender) { return $preRender; } $transactions = OrderData::getTransactions($this->entry->id); if (!$transactions || empty($transactions[0])) { return; } $transaction = $transactions[0]; return $this->loadView('customer_details', array( 'submission' => $this->entry, 'transaction' => $transaction )); } private function loadCss() { return $this->loadView('custom_css', array('submission' => $this->entry)); } public function loadView($fileName, $data) { return PaymentHelper::loadView($fileName, $data); } private function subscriptionDetails() { $subscriptions = $this->getSubscriptions(); $preRender = apply_filters_deprecated( 'fluentform_payment_receipt_pre_render_subscription_details', [ '', $this->entry, $subscriptions ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_receipt_pre_render_subscription_details', 'Use fluentform/payment_receipt_pre_render_subscription_details instead of fluentform_payment_receipt_pre_render_subscription_details.' ); $preRender = apply_filters('fluentform/payment_receipt_pre_render_subscription_details', $preRender, $this->entry, $subscriptions); if ($preRender) { return $preRender; } return $this->loadView('subscriptions_table', array( 'submission' => $this->entry, 'subscriptions' => $subscriptions, 'orderTotal' => $this->subscriptionTotal )); } } PK!/$src/Payments/Classes/CouponModel.phpnu[table($this->table); if ($paginate) { if (!$perPage = intval($_REQUEST['per_page'])) { $perPage = 10; } $coupons = $query->paginate($perPage)->toArray(); $coupons['data'] = $this->processGetCoupons($coupons['data']); return $coupons; } $coupons = $query->get(); return $this->processGetCoupons($coupons); } public function getCouponByCode($code) { $coupon = wpFluent()->table($this->table) ->where('code', $code) ->first(); if (!$coupon) { return $coupon; } $coupon->settings = $this->processSettings($coupon->settings); if ($coupon->start_date == '0000-00-00') { $coupon->start_date = ''; } if ($coupon->expire_date == '0000-00-00') { $coupon->expire_date = ''; } return $coupon; } public function getCouponsByCodes($codes) { $coupons = wpFluent()->table($this->table) ->whereIn('code', $codes) ->get(); return $this->processGetCoupons($coupons); } public function insert($data) { $data['created_at'] = current_time('mysql'); $data['updated_at'] = current_time('mysql'); $data['created_by'] = get_current_user_id(); if (isset($data['settings'])) { $data['settings'] = maybe_serialize($data['settings']); } return wpFluent()->table($this->table) ->insertGetId($data); } public function update($id, $data) { $data['updated_at'] = current_time('mysql'); if (isset($data['settings'])) { $data['settings'] = maybe_serialize($data['settings']); } return wpFluent()->table($this->table) ->where('id', $id) ->update($data); } public function delete($id) { return wpFluent()->table($this->table) ->where('id', $id) ->delete(); } public function getValidCoupons($coupons, $formId, $amountTotal) { $validCoupons = []; $otherCouponCodes = []; foreach ($coupons as $coupon) { if ($coupon->status != 'active') { continue; } if ($this->isDateExpire($coupon)) { continue; } if ($formIds = ArrayHelper::get($coupon->settings, 'allowed_form_ids')) { if (!in_array($formId, $formIds)) { continue; } } if ($coupon->min_amount && $coupon->min_amount > $amountTotal) { continue; } if ($otherCouponCodes && $coupon->stackable != 'yes') { continue; } $discountAmount = $coupon->amount; if ($coupon->coupon_type == 'percent') { $discountAmount = ($coupon->amount / 100) * $amountTotal; } $amountTotal = $amountTotal - $discountAmount; $otherCouponCodes[] = $coupon->code; $validCoupons[] = $coupon; } return $validCoupons; } public function migrate() { global $wpdb; $charsetCollate = $wpdb->get_charset_collate(); $table = $wpdb->prefix . $this->table; if ($wpdb->get_var("SHOW TABLES LIKE '$table'") != $table) { $sql = "CREATE TABLE $table ( id int(11) NOT NULL AUTO_INCREMENT, title varchar(192), code varchar(192), coupon_type varchar(255) DEFAULT 'percent', amount decimal(10,2) NULL, status varchar(192) DEFAULT 'active', stackable varchar(192) DEFAULT 'no', settings longtext, created_by INT(11) NULL, min_amount INT(11) NULL, max_use INT(11) NULL, start_date date NULL, expire_date date NULL, created_at timestamp NULL, updated_at timestamp NULL, PRIMARY KEY (id) ) $charsetCollate;"; require_once ABSPATH . 'wp-admin/includes/upgrade.php'; dbDelta($sql); } } public function isCouponCodeAvailable($code, $exceptId = false) { $query = wpFluent()->table($this->table) ->where('code', $code); if ($exceptId) { $query = $query->where('id', '!=', $exceptId); } return $query->first(); } protected function processGetCoupons($coupons) { foreach ($coupons as $coupon) { if (!empty($coupon->settings)) { $coupon->settings = $this->processSettings($coupon->settings); } else { $coupon->settings = [ 'allowed_form_ids' => [], 'coupon_limit' => 0, ]; } if ($coupon->start_date == '0000-00-00') { $coupon->start_date = ''; } if ($coupon->expire_date == '0000-00-00') { $coupon->expire_date = ''; } } return $coupons; } protected function processSettings($settings) { $settings = maybe_unserialize($settings); $settings['coupon_limit'] = ArrayHelper::get($settings, 'coupon_limit', 0); return $settings; } public function hasLimit($couponCode, $couponLimit, $userId) { $couponApplied = $this->couponAppliedCount($couponCode, $userId); return (int) $couponLimit - $couponApplied > 0; } public function isDateExpire($coupon) { $start_date = ''; $expire_date = ''; if ($coupon->start_date && ("0000-00-00" != $coupon->start_date)) { $start_date = strtotime($coupon->start_date); } if ($coupon->expire_date && ("0000-00-00" != $coupon->expire_date)) { $expire_date = strtotime($coupon->expire_date); } $today = strtotime('today midnight'); if ($start_date && $expire_date) { return !($start_date <= $today && $today <= $expire_date); // start-date<=today<=expire-date } if ($start_date) { return !($start_date <= $today); } if ($expire_date) { return !($today <= $expire_date); } return false; } protected function couponAppliedCount($couponCode, $userId) { return wpFluent() ->table('fluentform_entry_details') ->where('field_name', 'payment-coupon') ->where('field_value', $couponCode) ->join('fluentform_submissions', function ($table) use ($userId) { $table->on('fluentform_submissions.id', '=', 'fluentform_entry_details.submission_id'); $table->on('fluentform_submissions.user_id', '=', wpFluent()->raw($userId)); }) ->count(); } } PK!fu-ii)src/Payments/Classes/CouponController.phpnu[getCouponByCode($code); if (!$coupon) { wp_send_json([ 'message' => __(apply_filters('fluentform/coupon_general_failure_message', 'The provided coupon is not valid', $formId), 'fluentformpro') ], 423); } $failedMessageArray = ArrayHelper::get($coupon->settings, 'failed_message'); if ($coupon->status != 'active' || $coupon->code !== $code) { wp_send_json([ 'message' => __(ArrayHelper::get($failedMessageArray, 'inactive'), 'fluentformpro') ], 423); } if ($couponModel->isDateExpire($coupon)) { wp_send_json([ 'message' => __(ArrayHelper::get($failedMessageArray, 'date_expire'), 'fluentformpro') ], 423); } if ($formIds = ArrayHelper::get($coupon->settings, 'allowed_form_ids')) { if (!in_array($formId, $formIds)) { wp_send_json([ 'message' => __(ArrayHelper::get($failedMessageArray, 'allowed_form'), 'fluentformpro') ], 423); } } $couponLimit = ArrayHelper::get($coupon->settings, 'coupon_limit', 0); if ($couponLimit) { $userId = get_current_user_id(); if ($userId) { if (!$couponModel->hasLimit($coupon->code, $couponLimit, $userId)) { wp_send_json([ 'message' => __(ArrayHelper::get($failedMessageArray, 'limit'), 'fluentformpro') ], 423); } } else { wp_send_json([ 'message' => __(ArrayHelper::get($failedMessageArray, 'limit'), 'fluentformpro') ], 423); } } if ($coupon->min_amount && $coupon->min_amount > $totalAmount) { wp_send_json([ 'message' => __(ArrayHelper::get($failedMessageArray, 'min_amount'), 'fluentformpro') ], 423); } $otherCouponCodes = wp_unslash(ArrayHelper::get($_REQUEST, 'other_coupons', '')); if ($otherCouponCodes) { $otherCouponCodes = \json_decode($otherCouponCodes, true); if ($otherCouponCodes) { $codes = $couponModel->getCouponsByCodes($otherCouponCodes); foreach ($codes as $couponItem) { if (($couponItem->stackable != 'yes' || $coupon->stackable != 'yes') && $coupon->code != $couponItem->code) { wp_send_json([ 'message' => __(ArrayHelper::get($failedMessageArray, 'stackable'), 'fluentformpro') ], 423); } } } } $successMessage = ArrayHelper::get($coupon->settings, 'success_message'); wp_send_json([ 'coupon' => [ 'code' => $coupon->code, 'title' => $coupon->title, 'amount' => $coupon->amount, 'coupon_type' => $coupon->coupon_type, 'message' => $successMessage ] ], 200); } } PK!iSHH(src/Payments/Components/Subscription.phpnu[key, function ($response, $field, $form_id, $isHtml = false) { if (!$isHtml) { return $response; } return ArrayHelper::get($field, 'raw.settings.subscription_options.' . $response . '.name', $response); }, 10, 4); add_filter('fluentform/white_listed_fields', [$this, 'addWhiteListedFields'], 10, 2); } function getComponent() { return array( 'index' => 8, 'element' => $this->key, 'attributes' => array( 'type' => 'single', // single|multiple 'name' => 'payment_input', 'value' => '10' ), 'settings' => array( 'container_class' => '', 'label' => __('Subscription Item', 'fluentformpro'), 'admin_field_label' => '', 'label_placement' => '', 'display_type' => '', 'help_message' => '', 'is_payment_field' => 'yes', 'selection_type' => 'radio', 'subscription_options' => [ [ "bill_times" => 0, "billing_interval" => "month", "has_signup_fee" => "no", "has_trial_days" => "no", "is_default" => "yes", "name" => __("Monthly Plan", 'fluentformpro'), "plan_features" => [], "signup_fee" => 0, "subscription_amount" => 9.99, "trial_days" => 0, ] ], 'price_label' => __('Price:', 'fluentformpro'), 'enable_quantity' => false, 'enable_image_input' => false, 'is_element_lock' => false, 'layout_class' => 'ff_list_buttons', 'validation_rules' => array( 'required' => array( 'value' => false, 'global' => true, 'message' => Helper::getGlobalDefaultMessage('required'), 'global_message' => Helper::getGlobalDefaultMessage('required'), ), ), 'conditional_logics' => array(), ), 'editor_options' => array( 'title' => __('Subscription', 'fluentformpro'), 'icon_class' => 'ff-edit-shopping-cart', 'element' => 'input-radio', 'template' => 'inputSubscriptionPayment' ) ); } public function getGeneralEditorElements() { return [ 'label', 'label_placement', 'admin_field_label', 'placeholder', 'subscription_options', 'validation_rules', ]; } public function getAdvancedEditorElements() { return [ 'container_class', 'help_message', 'name', 'layout_class', 'conditional_logics' ]; } function render($data, $form) { $type = ArrayHelper::get($data, 'attributes.type'); if ($type == 'single') { $this->renderSingleItem($data, $form); return ''; } $this->renderMultiProduct($data, $form); } public function renderSingleItem($data, $form) { $elementName = $data['element']; $data = apply_filters_deprecated( 'fluentform_rendering_field_data_' . $elementName, [ $data, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/rendering_field_data_' . $elementName, 'Use fluentform/rendering_field_data_' . $elementName . ' instead of fluentform_rendering_field_data_' . $elementName ); $data = apply_filters('fluentform/rendering_field_data_' . $elementName, $data, $form); $plan = ArrayHelper::get($data, 'settings.subscription_options.0', []); $plan['index'] = 0; $isCustomAmount = ArrayHelper::get($plan, 'user_input') === 'yes'; if ($isCustomAmount) { $plan['subscription_amount'] = ArrayHelper::get($plan, 'user_input_default_value'); } $inputAttributes = [ 'type' => 'hidden', 'name' => $data['attributes']['name'], 'value' => '0', 'class' => 'ff_payment_item ff_subscription_item', ]; $inputAttributes['id'] = $this->makeElementId($data, $form); $currency = PaymentHelper::getFormCurrency($form->id); $billingAttributes = $this->getPlanInputAttributes($plan); $itemInputAttributes = wp_parse_args($billingAttributes, $inputAttributes); $elMarkup = "buildAttributes($itemInputAttributes, $form) . ">"; if ($isCustomAmount) { $plan['user_input_label'] = ArrayHelper::get($plan, 'user_input_label'); $plan['user_input_label'] = $plan['user_input_label'] ?: ArrayHelper::get($data, 'settings.label'); $elMarkup = $this->makeCustomInputHtml($data, $plan, 'hidden', $elMarkup); $data['settings']['label'] = ArrayHelper::get($plan, 'user_input_label', $data['settings']['label']); $data['attributes']['id'] = ArrayHelper::get($data, 'attributes.name') . '_custom_' . $plan['index']; } $paymentSummary = $this->getPaymentSummaryText($plan, $form, $currency); $elMarkup .= $paymentSummary; $html = $this->buildElementMarkup($elMarkup, $data, $form); $html = apply_filters_deprecated( 'fluentform_rendering_field_html_' . $elementName, [ $html, $data, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/rendering_field_html_' . $elementName, 'Use fluentform/rendering_field_html_' . $elementName . ' instead of fluentform_rendering_field_html_' . $elementName ); echo apply_filters('fluentform/rendering_field_html_' . $elementName, $html, $data, $form); } public function renderMultiProduct($data, $form) { $elementName = $data['element']; $data = apply_filters_deprecated( 'fluentform_rendering_field_data_' . $elementName, [ $data, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/rendering_field_data_' . $elementName, 'Use fluentform/rendering_field_data_' . $elementName . ' instead of fluentform_rendering_field_data_' . $elementName ); $data = apply_filters('fluentform/rendering_field_data_' . $elementName, $data, $form); $currency = PaymentHelper::getFormCurrency($form->id); $type = ArrayHelper::get($data, 'settings.selection_type', 'radio'); $data['attributes']['type'] = $type; $data['settings']['container_class'] .= ' ff_subs_selections'; $isSmartUi = false; if ($type == 'radio') { $layoutClass = ArrayHelper::get($data, 'settings.layout_class'); if ($layoutClass == 'ff_list_buttons') { $isSmartUi = true; } if ($layoutClass) { $data['settings']['container_class'] .= ' ff_sub_smart_ui ' . $layoutClass; } } $data['attributes']['class'] = trim( 'ff-el-form-check-input ' . 'ff-el-form-check-' . $data['attributes']['type'] . ' ' . ArrayHelper::get($data, 'attributes.class') ); $elMarkup = ''; $customAmountMarkup = ''; $firstTabIndex = \FluentForm\App\Helpers\Helper::getNextTabIndex(); if ($type === 'select') { $selectAtts = [ 'name' => $data['attributes']['name'], 'class' => 'ff-el-form-control ff_subscription_item ff_payment_item', 'data-subscription_item' => 'yes', 'data-name' => $data['attributes']['name'], 'id' => $this->getUniqueid(str_replace(['[', ']'], ['', ''], $data['attributes']['name'])), 'data-parent_input_name' => $data['attributes']['name'], 'data-parent_input_type' => $type, ]; if ($firstTabIndex) { $selectAtts['tabindex'] = $firstTabIndex; } $elMarkup .= '" . $labelHtml . ""; $elMarkup .= "
    "; } if ($isCustomAmount) { $customAmountMarkup = $this->makeCustomInputHtml($data, $pricingPlan, $type, $customAmountMarkup); } if (!$isSmartUi) { $paymentSummary = $this->getPaymentSummaryText($pricingPlan, $form, $currency); $customAmountMarkup .= $paymentSummary; } } if ($type === 'select') { $elMarkup .= ''; } if ($customAmountMarkup) { $elMarkup .= $customAmountMarkup; } $html = $this->buildElementMarkup($elMarkup, $data, $form); $html = apply_filters_deprecated( 'fluentform_rendering_field_html_' . $elementName, [ $html, $data, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/rendering_field_html_' . $elementName, 'Use fluentform/rendering_field_html_' . $elementName . ' instead of fluentform_rendering_field_html_' . $elementName ); echo apply_filters('fluentform/rendering_field_html_' . $elementName, $html, $data, $form); } private function getPaymentSummaryText($plan, $formId, $currency) { return PaymentHelper::getPaymentSummaryText($plan, $formId, $currency, true); } private function getPlanInputAttributes($plan) { $subscriptionAmount = $plan['subscription_amount']; $currentBillableAmount = $subscriptionAmount; $initialAmount = 0; $signupFee = 0; if ($this->hasSignupFee($plan)) { $signupFee = $plan['signup_fee']; } $trialDays = false; if ($this->hasTrial($plan)) { $currentBillableAmount = 0; $trialDays = ArrayHelper::get($plan, 'trial_days'); } return [ 'data-subscription_amount' => $subscriptionAmount ?: 0, 'data-billing_interval' => $plan['billing_interval'], 'data-price' => $currentBillableAmount ?: 0, 'data-payment_value' => $currentBillableAmount ?: 0, 'data-initial_amount' => $initialAmount ?: 0, 'data-signup_fee' => $signupFee, 'data-trial_days' => $trialDays, 'data-plan_name' => esc_attr($plan['name']) ]; } private function hasTrial($plan) { $hasTrial = ArrayHelper::get($plan, 'has_trial_days') == 'yes'; $trialDays = ArrayHelper::get($plan, 'trial_days'); return $hasTrial && $trialDays; } private function hasSignupFee($plan) { $hasSignup = ArrayHelper::get($plan, 'has_signup_fee') == 'yes'; $signUpFee = ArrayHelper::get($plan, 'signup_fee'); return $hasSignup && $signUpFee; } private function makeCustomInputHtml($field, $plan, $parentInputType, $markup) { $htmlID = ArrayHelper::get($field, 'attributes.name') . '_custom_' . $plan['index']; $isDefault = ArrayHelper::get($plan, 'is_default') === 'yes'; $customAmountInputAttributes = $this->buildAttributes([ 'name' => $htmlID, 'type' => 'number', 'value' => ArrayHelper::get($plan, 'user_input_default_value'), 'min' => $isDefault ? ArrayHelper::get($plan, 'user_input_min_value', 0) : '0', 'data-min' => ArrayHelper::get($plan, 'user_input_min_value', 0), 'step' => 'any', 'placeholder' => ArrayHelper::get($plan, 'user_input_label'), 'class' => 'ff-el-form-control ff-custom-user-input ' . ($isDefault ? 'is-default' : ''), 'id' => $htmlID, 'data-parent_input_name' => $field['attributes']['name'], 'data-parent_input_type' => $parentInputType, 'data-plan_index' => $plan['index'], 'data-plan_trial_days' => ArrayHelper::get($plan, 'trial_days', 0) ]); $class = $isDefault ? '' : 'hidden_field'; $style = $parentInputType === 'hidden' ? '' : "style='margin-top: 5px'"; $markup .= "
    "; if ($parentInputType !== 'hidden') { $markup .= "'; } $markup .= ""; $markup .= '
    '; return $markup; } public function addWhiteListedFields($whiteListedFields, $formId) { $form = wpFluent()->table('fluentform_forms')->find($formId); if (!$form->has_payment) { return $whiteListedFields; } $inputs = FormFieldsParser::getInputsByElementTypes($form, ['subscription_payment_component'], ['settings', 'attributes']); $customInputNames = []; foreach ($inputs as $subscriptionInput) { $index = 0; $subscriptionOptions = ArrayHelper::get($subscriptionInput, 'settings.subscription_options'); foreach ($subscriptionOptions as $plan) { if (ArrayHelper::get($plan, 'user_input') === 'yes') { $customInputNames[] = ArrayHelper::get($subscriptionInput, 'attributes.name') . '_custom_' . $index; } $index++; } } return array_merge($whiteListedFields, $customInputNames); } } PK! 957571src/Payments/Components/MultiPaymentComponent.phpnu[ 8, 'element' => $this->key, 'attributes' => array( 'type' => 'single', // single|radio|checkbox|select 'name' => 'payment_input', 'value' => '10', ), 'settings' => array( 'container_class' => '', 'label' => __('Payment Item', 'fluentformpro'), 'admin_field_label' => '', 'label_placement' => '', 'display_type' => '', 'help_message' => '', 'is_payment_field' => 'yes', 'pricing_options' => array( [ 'label' => 'Payment Item 1', 'value' => 10, 'image' => '' ] ), 'dynamic_default_value' => '', 'price_label' => __('Price:', 'fluentformpro'), 'enable_quantity' => false, 'enable_image_input' => false, 'is_element_lock' => false, 'layout_class' => '', 'validation_rules' => array( 'required' => array( 'value' => false, 'global' => true, 'message' => Helper::getGlobalDefaultMessage('required'), 'global_message' => Helper::getGlobalDefaultMessage('required'), ), ), 'conditional_logics' => array(), ), 'editor_options' => array( 'title' => __('Payment Item', 'fluentformpro'), 'icon_class' => 'ff-edit-shopping-cart', 'element' => 'input-radio', 'template' => 'inputMultiPayment' ) ); } public function getGeneralEditorElements() { return [ 'label', 'label_placement', 'admin_field_label', 'placeholder', 'pricing_options', 'validation_rules', ]; } public function getAdvancedEditorElements() { return [ 'container_class', 'help_message', 'name', 'layout_class', 'dynamic_default_value', 'conditional_logics' ]; } function render($data, $form) { $type = ArrayHelper::get($data, 'attributes.type'); if(!$this->app){ $this->app = wpFluentForm(); } if ($type == 'single') { $this->renderSingleItem($data, $form); return ''; } $this->renderMultiProduct($data, $form); } public function renderSingleItem($data, $form) { $elementName = $data['element']; $data = apply_filters_deprecated( 'fluentform_rendering_field_data_' . $elementName, [ $data, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/rendering_field_data_' . $elementName, 'Use fluentform/rendering_field_data_' . $elementName . ' instead of fluentform_rendering_field_data_' . $elementName ); $data = apply_filters('fluentform/rendering_field_data_' . $elementName, $data, $form); $priceLabel = ArrayHelper::get($data, 'settings.price_label'); $productPrice = ArrayHelper::get($data, 'attributes.value'); if ($dynamicValues = $this->extractDynamicValues($data, $form)) { $productPrice = ArrayHelper::get($dynamicValues, '0'); } if (!$productPrice || !is_numeric($productPrice)) { $productPrice = apply_filters('fluentform/single_payment_item_fallback_value', 0, $data, $form); } $inputAttributes = [ 'type' => 'hidden', 'id' => $this->makeElementId($data, $form), 'name' => $data['attributes']['name'], 'value' => $productPrice, 'class' => 'ff_payment_item', 'data-payment_item' => 'yes', 'data-payment_value' => $productPrice, 'data-quantity_remaining' => ArrayHelper::get($data, 'settings.quantity_remaining', false) ]; $money = PaymentHelper::formatMoney( $productPrice * 100, PaymentHelper::getFormCurrency($form->id) ); $elMarkup = $input = "buildAttributes($inputAttributes, $form) . ">"; $elMarkup .= '' . $priceLabel . ''; $elMarkup .= ' ' . $money . ''; $html = $this->buildElementMarkup($elMarkup, $data, $form); $html = apply_filters_deprecated( 'fluentform_rendering_field_html_' . $elementName, [ $html, $data, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/rendering_field_html_' . $elementName, 'Use fluentform/rendering_field_html_' . $elementName . ' instead of fluentform_rendering_field_html_' . $elementName ); echo apply_filters('fluentform/rendering_field_html_' . $elementName, $html, $data, $form); } public function renderMultiProduct($data, $form) { $elementName = $data['element']; $data = apply_filters_deprecated( 'fluentform_rendering_field_data_' . $elementName, [ $data, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/rendering_field_data_' . $elementName, 'Use fluentform/rendering_field_data_' . $elementName . ' instead of fluentform_rendering_field_data_' . $elementName ); $data = apply_filters('fluentform/rendering_field_data_' . $elementName, $data, $form); $data['attributes']['class'] = trim( 'ff-el-form-check-input ' . 'ff-el-form-check-'.$data['attributes']['type'].' '. ArrayHelper::get($data, 'attributes.class') ); if ($data['attributes']['type'] == 'checkbox') { $data['attributes']['name'] = $data['attributes']['name'] . '[]'; } $defaultValues = (array)$this->extractValueFromAttributes($data); if ($dynamicValues = $this->extractDynamicValues($data, $form)) { $defaultValues = $dynamicValues; } $elMarkup = ''; $firstTabIndex = \FluentForm\App\Helpers\Helper::getNextTabIndex(); $formattedOptions = ArrayHelper::get($data, 'settings.pricing_options'); $formattedOptions = apply_filters_deprecated( 'fluentform_payment_field_' . $elementName . '_pricing_options', [ $formattedOptions, $data, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_field_' . $elementName . '_pricing_options', 'Use fluentform/payment_field_' . $elementName . '_pricing_options instead of fluentform_payment_field_' . $elementName . '_pricing_options' ); $formattedOptions = apply_filters('fluentform/payment_field_' . $elementName . '_pricing_options', $formattedOptions, $data, $form); $hasImageOption = ArrayHelper::get($data, 'settings.enable_image_input'); $type = ArrayHelper::get($data, 'attributes.type'); if ($type == 'select') { $selectAtts = [ 'name' => $data['attributes']['name'], 'class' => 'ff-el-form-control ff_payment_item', 'data-payment_item' => 'yes', 'data-name' => $data['attributes']['name'], 'id' => $this->getUniqueid(str_replace(['[', ']'], ['', ''], $data['attributes']['name'])) ]; if ($firstTabIndex) { $selectAtts['tabindex'] = $firstTabIndex; } $elMarkup .= ' {$option['label']}{$quantityLabel}"; $elMarkup .= ""; } if ($type == 'select') { $elMarkup .= ''; } else if ($hasImageOption) { $elMarkup .= ' '; } if($layoutClass = ArrayHelper::get($data, 'settings.layout_class')) { $data['settings']['container_class'] = $data['settings']['container_class'].' '.$layoutClass; } $html = $this->buildElementMarkup($elMarkup, $data, $form); $html = apply_filters_deprecated( 'fluentform_rendering_field_html_' . $elementName, [ $html, $data, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/rendering_field_html_' . $elementName, 'Use fluentform/rendering_field_html_' . $elementName . ' instead of fluentform_rendering_field_html_' . $elementName ); echo apply_filters('fluentform/rendering_field_html_' . $elementName, $html, $data, $form); } } PK!77*src/Payments/Components/PaymentMethods.phpnu[key, function ($value) { if ($value == 'test') { return 'Offline'; } return $value; }); } function getComponent() { $available_methods = apply_filters_deprecated( 'fluentformpro_available_payment_methods', [ [] ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/available_payment_methods', 'Use fluentform/available_payment_methods instead of fluentformpro_available_payment_methods.' ); $available_methods = apply_filters('fluentform/available_payment_methods', $available_methods); if (!$available_methods) { return; } return [ 'index' => 10, 'element' => $this->key, 'attributes' => [ 'name' => $this->key, 'type' => 'radio', 'value' => '' ], 'settings' => [ 'container_class' => '', 'label' => $this->title, 'default_method' => '', 'label_placement' => '', 'help_message' => '', 'payment_methods' => $available_methods, 'validation_rules' => array( 'required' => array( 'value' => false, 'global' => true, 'message' => Helper::getGlobalDefaultMessage('required'), 'global_message' => Helper::getGlobalDefaultMessage('required'), ) ), 'admin_field_label' => '', 'conditional_logics' => [] ], 'editor_options' => [ 'title' => $this->title, 'icon_class' => 'ff-edit-credit-card', 'template' => 'inputPaymentMethods' ], ]; } public function recheckEditorComponent($component) { if (!isset($component['settings']['validation_rules'])) { $component['settings']['validation_rules'] = array( 'required' => array( 'value' => false, 'global' => true, 'message' => Helper::getGlobalDefaultMessage('required'), 'global_message' => Helper::getGlobalDefaultMessage('required'), ), ); } $available_methods = apply_filters_deprecated( 'fluentformpro_available_payment_methods', [ [] ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/available_payment_methods', 'Use fluentform/available_payment_methods instead of fluentformpro_available_payment_methods.' ); $available_methods = apply_filters('fluentform/available_payment_methods', $available_methods); if (!$available_methods) { $component['settings']['payment_methods'] = $available_methods; return $component; } $existingMethods = ArrayHelper::get($component, 'settings.payment_methods', []); $updatedMethods = []; foreach ($available_methods as $methodName => $method) { if (isset($existingMethods[$methodName])) { $method['settings'] = wp_parse_args($existingMethods[$methodName]['settings'], $method['settings']); $method['enabled'] = $existingMethods[$methodName]['enabled']; } else { $method['enabled'] = 'no'; } $updatedMethods[$methodName] = $method; } $component['settings']['payment_methods'] = $updatedMethods; return $component; } public function getEditorCustomizationSettings() { return [ 'payment_methods' => array( 'template' => 'paymentMethodsConfig', 'label' => __('Payment Methods', 'fluentformpro'), 'help_text' => __('Please Select and Configure the payment methods for this form, At least 1 method is required. If you select only one it will not show on the form for selection but will process that payment with the selected method.', 'fluentformpro') ) ]; } public function getGeneralEditorElements() { return [ 'label', 'admin_field_label', 'label_placement', 'payment_methods', 'value', 'validation_rules' ]; } function render($data, $form) { $elementName = $data['element']; $data = apply_filters_deprecated( 'fluentform_rendering_field_data_' . $elementName, [ $data, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/rendering_field_data_' . $elementName, 'Use fluentform/rendering_field_data_' . $elementName . ' instead of fluentform_rendering_field_data_' . $elementName ); $data = apply_filters('fluentform/rendering_field_data_' . $elementName, $data, $form); $data['attributes']['class'] = trim( 'ff-el-form-check-input ' . ArrayHelper::get($data, 'attributes.class') ); $paymentMethods = ArrayHelper::get($data, 'settings.payment_methods'); $available_methods = apply_filters_deprecated( 'fluentformpro_available_payment_methods', [ [] ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/available_payment_methods', 'Use fluentform/available_payment_methods instead of fluentformpro_available_payment_methods.' ); $available_methods = apply_filters('fluentform/available_payment_methods', $available_methods); $activatedMethods = []; foreach ($paymentMethods as $methodName => $paymentMethod) { $enabled = ArrayHelper::get($paymentMethod, 'enabled'); if ($enabled == 'yes' && isset($available_methods[$methodName])) { $activatedMethods[$methodName] = $paymentMethod; } } if (!$activatedMethods) { echo wp_sprintf( '

    %s

    ', __('No activated payment method found. If you are an admin please check the payment settings', 'fluentformpro') ); return; } foreach ($activatedMethods as $methodName => $activatedMethod) { do_action_deprecated( 'fluentform_rendering_payment_method_' . $methodName, [ $activatedMethod, $data, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/rendering_payment_method_' . $methodName, 'Use fluentform/rendering_payment_method_' . $methodName . ' instead of fluentform_rendering_payment_method_' . $methodName ); do_action('fluentform/rendering_payment_method_' . $methodName, $activatedMethod, $data, $form); } $data['attributes']['class'] = $data['attributes']['class'] . ' ff_payment_method'; if (count($activatedMethods) == 1) { $methodKeys = array_keys($activatedMethods); $methodName = $methodKeys[0]; $methodElement = $activatedMethods[$methodName]; $data['attributes']['type'] = 'hidden'; $data['attributes']['value'] = $methodName; $data['attributes']['class'] .= ' ff_selected_payment_method'; $elMarkup = $html = "buildAttributes($data['attributes'], $form) . ">"; $method = $activatedMethods[$methodName]; $method['is_default'] = true; $selectedMarkups = apply_filters_deprecated( 'fluentform_payment_method_contents_' . $methodName, [ '', $method, $data, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_method_contents_' . $methodName, 'Use fluentform/payment_method_contents_' . $methodName . ' instead of fluentform_payment_method_contents_' . $methodName ); $selectedMarkups = apply_filters('fluentform/payment_method_contents_' . $methodName, $selectedMarkups, $method, $data, $form); if ($selectedMarkups) { $elMarkup .= $selectedMarkups; $data['settings']['label'] = ''; $html = $this->buildElementMarkup($elMarkup, $data, $form); } $html = apply_filters_deprecated( 'fluentform_rendering_field_html_' . $elementName, [ $html, $data, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/rendering_field_html_' . $elementName, 'Use fluentform/rendering_field_html_' . $elementName . ' instead of fluentform_rendering_field_html_' . $elementName ); echo apply_filters('fluentform/rendering_field_html_' . $elementName, $html, $data, $form); do_action_deprecated( 'fluentform_payment_method_render_' . $methodName, [ $methodElement, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_method_render_' . $methodName, 'Use fluentform/payment_method_render_' . $methodName . ' instead of fluentform_payment_method_render_' . $methodName ); do_action('fluentform/payment_method_render_' . $methodName, $methodElement, $form); return; } $elMarkup = ''; $hasImageOption = false; $defaultValue = $this->extractValueFromAttributes($data); if ($defaultValue && !isset($activatedMethods[$defaultValue])) { $defaultValue = key($activatedMethods); } if ($hasImageOption) { $data['settings']['container_class'] .= ''; $elMarkup .= '
    '; } $firstTabIndex = \FluentForm\App\Helpers\Helper::getNextTabIndex(); $selectedMarkups = ''; foreach ($activatedMethods as $methodName => $method) { $parentClass = "ff-el-form-check ff-el-payment-method-label"; if ($methodName == $defaultValue) { $method['is_default'] = true; $data['attributes']['checked'] = true; $parentClass .= ' ff_item_selected'; } else { $data['attributes']['checked'] = false; $method['is_default'] = false; } if ($firstTabIndex) { $data['attributes']['tabindex'] = $firstTabIndex; $firstTabIndex = '-1'; } $data['attributes']['value'] = $methodName; $data['attributes']['type'] = 'radio'; $methodLabel = ArrayHelper::get($method, 'settings.option_label.value'); if ($methodLabel) { $method['title'] = $methodLabel; } $atts = $this->buildAttributes($data['attributes']); $id = $this->getUniqueid(str_replace(['[', ']'], ['', ''], $data['attributes']['name'])); if ($hasImageOption) { $parentClass .= ' ff-el-image-holder'; } $elMarkup .= "
    "; $elMarkup .= ""; $elMarkup .= "
    "; $selectedMarkups .= apply_filters_deprecated( 'fluentform_payment_method_contents_' . $methodName, [ '', $method, $data, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_method_contents_' . $methodName, 'Use fluentform/payment_method_contents_' . $methodName . ' instead of fluentform_payment_method_contents_' . $methodName ); $selectedMarkups = apply_filters('fluentform/payment_method_contents_' . $methodName, $selectedMarkups, $method, $data, $form); } if ($hasImageOption) { $elMarkup .= '
    '; } $elMarkup .= $selectedMarkups; $html = $this->buildElementMarkup($elMarkup, $data, $form); $html = apply_filters_deprecated( 'fluentform_rendering_field_html_' . $elementName, [ $html, $data, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/rendering_field_html_' . $elementName, 'Use fluentform/rendering_field_html_' . $elementName . ' instead of fluentform_rendering_field_html_' . $elementName ); echo apply_filters('fluentform/rendering_field_html_' . $elementName, $html, $data, $form); } } PK!Uh2src/Payments/Components/CustomPaymentComponent.phpnu[key, function($amount, $field, $form_id, $isHtml = false) { if (!$isHtml) { return $amount; } if ($currency = PaymentHelper::getFormCurrency($form_id)) { $amount = PaymentHelper::formatMoney(PaymentHelper::convertToCents($amount), $currency); } return $amount; }, 10, 4); } function getComponent() { return array( 'index' => 6, 'element' => $this->key, 'attributes' => array( 'type' => 'number', 'name' => 'custom-payment-amount', 'value' => '', 'id' => '', 'class' => '', 'placeholder' => '', 'data-payment_item' => 'yes' ), 'settings' => array( 'container_class' => '', 'is_payment_field' => 'yes', 'label' => __('Custom Payment Amount', 'fluentformpro'), 'admin_field_label' => '', 'label_placement' => '', 'help_message' => '', 'number_step' => '', 'prefix_label' => '', 'suffix_label' => '', 'validation_rules' => array( 'required' => array( 'value' => false, 'global' => true, 'message' => Helper::getGlobalDefaultMessage('required'), 'global_message' => Helper::getGlobalDefaultMessage('required'), ), 'numeric' => array( 'value' => true, 'global' => true, 'message' => Helper::getGlobalDefaultMessage('numeric'), 'global_message' => Helper::getGlobalDefaultMessage('numeric'), ), 'min' => array( 'value' => '', 'global' => true, 'message' => Helper::getGlobalDefaultMessage('min'), 'global_message' => Helper::getGlobalDefaultMessage('min'), ), 'max' => array( 'value' => '', 'global' => true, 'message' => Helper::getGlobalDefaultMessage('max'), 'global_message' => Helper::getGlobalDefaultMessage('max'), ), ), 'conditional_logics' => array(), 'calculation_settings' => array( 'status' => false, 'formula' => '' ) ), 'editor_options' => array( 'title' => __('Custom Payment Amount', 'fluentformpro'), 'icon_class' => 'ff-edit-keyboard-o', 'template' => 'inputText' ), ); } public function getGeneralEditorElements() { return [ 'label', 'label_placement', 'admin_field_label', 'placeholder', 'validation_rules', 'numeric_formatter' ]; } public function getAdvancedEditorElements() { return [ 'value', 'container_class', 'class', 'help_message', 'prefix_label', 'suffix_label', 'name', 'conditional_logics', 'calculation_settings' ]; } function render($data, $form) { $data['attributes']['class'] .= ' ff_payment_item'; $data['attributes']['inputmode'] = 'decimal'; return (new Text())->compile($data, $form); } }PK! 5}}"src/Payments/Components/Coupon.phpnu[ true, 'disable_html' => '

    Please Activate Coupon Module First

    '. __('Activate Coupon Module', 'fluentformpro') . '

    ' . __('After creating your first coupon please reload this page.', 'fluentformpro') . '

    ' ]; } return $disables; }); } function getComponent() { return array( 'index' => 6, 'element' => $this->key, 'attributes' => array( 'type' => 'text', 'name' => 'payment-coupon', 'value' => '', 'id' => '', 'class' => '', 'placeholder' => '', 'data-is_coupon' => 'yes' ), 'settings' => array( 'container_class' => '', 'is_payment_field' => 'yes', 'label' => __('Coupon', 'fluentformpro'), 'admin_field_label' => '', 'label_placement' => '', 'suffix_label' => __('Apply Coupon', 'fluentformpro'), 'help_message' => '', 'validation_rules' => array( 'required' => array( 'value' => false, 'global' => true, 'message' => Helper::getGlobalDefaultMessage('required'), 'global_message' => Helper::getGlobalDefaultMessage('required'), ) ), 'conditional_logics' => array() ), 'editor_options' => array( 'title' => __('Coupon', 'fluentformpro'), 'icon_class' => 'el-icon-postcard', 'template' => 'inputText' ), ); } public function getGeneralEditorElements() { return [ 'label', 'label_placement', 'admin_field_label', 'placeholder', 'suffix_label' ]; } public function getAdvancedEditorElements() { return [ 'container_class', 'class', 'help_message', 'name', 'conditional_logics', 'calculation_settings' ]; } public function render($data, $form) { $data['attributes']['class'] .= ' ff_coupon_item'; $data['settings']['container_class'] .= ' ff_coupon_wrapper'; return (new Text())->compile($data, $form); } public function addCouponsToSubmission($value, $field, $submissionData) { if(isset($submissionData['__ff_all_applied_coupons'])) { $allCoupons = $submissionData['__ff_all_applied_coupons']; $allCoupons = \json_decode($allCoupons, true); if($allCoupons) { $value = implode(', ', $allCoupons); } } return $value; } }PK!F 3src/Payments/Components/PaymentSummaryComponent.phpnu[key, array($this, 'render'), 10, 2); add_filter('fluentform/editor_element_customization_settings', function ($settings) { if ($customSettings = $this->getEditorCustomizationSettings()) { $settings = array_merge($settings, $customSettings); } return $settings; }); // add_filter('fluentform/supported_conditional_fields', array($this, 'pushConditionalSupport')); } function getComponent() { return array( 'index' => 7, 'element' => $this->key, 'attributes' => array(), 'settings' => array( 'html_codes' => __('

    Payment Summary will be shown here

    ', 'fluentformpro'), 'cart_empty_text' => __('No payment items has been selected yet', 'fluentformpro'), 'conditional_logics' => array(), 'container_class' => '' ), 'editor_options' => array( 'title' => __('Payment Summary', 'fluentformpro'), 'icon_class' => 'ff-edit-html', 'template' => 'customHTML' ), ); } public function getGeneralEditorElements() { return [ 'cart_empty_text' ]; } public function generalEditorElement() { return [ 'cart_empty_text' => [ 'template' => 'inputHTML', 'label' => __('Empty Payment Selected Text', 'fluentformpro'), 'help_text' => __('The provided text will show if no payment item is selected yet', 'fluentformpro'), 'hide_extra' => 'yes' ] ]; } public function getAdvancedEditorElements() { return [ 'conditional_logics', 'container_class' ]; } function render($data, $form) { $fallBack = $data['settings']['cart_empty_text']; $data['settings']['html_codes'] = '
    '.$fallBack.'
    '; return (new CustomHtml())->compile($data, $form); } }PK!r(src/Payments/Components/ItemQuantity.phpnu[ 6, 'element' => $this->key, 'attributes' => array( 'type' => 'number', 'name' => 'item-quantity', 'value' => '', 'id' => '', 'class' => '', 'placeholder' => '', 'data-quantity_item' => 'yes' ), 'settings' => array( 'container_class' => '', 'is_payment_field' => 'yes', 'label' => __('Quantity', 'fluentformpro'), 'admin_field_label' => '', 'label_placement' => '', 'help_message' => '', 'number_step' => '', 'prefix_label' => '', 'suffix_label' => '', 'target_product' => '', 'validation_rules' => array( 'required' => array( 'value' => false, 'global' => true, 'message' => Helper::getGlobalDefaultMessage('required'), 'global_message' => Helper::getGlobalDefaultMessage('required'), ), 'numeric' => array( 'value' => true, 'global' => true, 'message' => Helper::getGlobalDefaultMessage('numeric'), 'global_message' => Helper::getGlobalDefaultMessage('numeric'), ), 'min' => array( 'value' => '', 'global' => true, 'message' => Helper::getGlobalDefaultMessage('min'), 'global_message' => Helper::getGlobalDefaultMessage('min'), ), 'max' => array( 'value' => '', 'global' => true, 'message' => Helper::getGlobalDefaultMessage('max'), 'global_message' => Helper::getGlobalDefaultMessage('max'), ), ), 'conditional_logics' => array() ), 'editor_options' => array( 'title' => __('Item Quantity', 'fluentformpro'), 'icon_class' => 'ff-edit-keyboard-o', 'template' => 'inputText' ), ); } public function getGeneralEditorElements() { return [ 'label', 'label_placement', 'admin_field_label', 'placeholder', 'target_product', 'validation_rules' ]; } public function getAdvancedEditorElements() { return [ 'value', 'container_class', 'class', 'help_message', 'number_step', 'prefix_label', 'suffix_label', 'name', 'conditional_logics', 'calculation_settings' ]; } public function getEditorCustomizationSettings() { return [ 'target_product' => array( 'template' => 'targetProduct', 'label' => __('Product Field Mapping', 'fluentformpro'), 'help_text' => __('Select which Product this field is tied to', 'fluentformpro'), ) ]; } function render($data, $form) { $data['attributes']['class'] .= ' ff_quantity_item'; $data['attributes']['data-target_product'] = ArrayHelper::get($data, 'settings.target_product'); if (ArrayHelper::get($data, 'settings.validation_rules.min.value') == '') { ArrayHelper::set($data, 'settings.validation_rules.min.value', 0); } ArrayHelper::set($data, 'attributes.min', ArrayHelper::get($data, 'settings.validation_rules.min.value')); if (ArrayHelper::get($data, 'settings.validation_rules.max.value')) { ArrayHelper::set($data, 'attributes.max', ArrayHelper::get($data, 'settings.validation_rules.max.value')); } return (new Text())->compile($data, $form); } }PK!.ć%src/Payments/Migrations/Migration.phpnu[= 4.6 provides easy to use functions for that). if (function_exists('get_sites') && function_exists('get_current_network_id')) { $site_ids = get_sites(array('fields' => 'ids', 'network_id' => get_current_network_id())); } else { $site_ids = $wpdb->get_col("SELECT blog_id FROM $wpdb->blogs WHERE site_id = $wpdb->siteid;"); } // Install the plugin for all these sites. foreach ($site_ids as $site_id) { switch_to_blog($site_id); self::migrate(); restore_current_blog(); } } else { self::migrate(); } } public static function migrate() { OrderItems::migrate(); Transactions::migrate(); OrderSubscriptions::migrate(); } }PK!.((.src/Payments/Migrations/OrderSubscriptions.phpnu[get_charset_collate(); $table = $wpdb->prefix . 'fluentform_subscriptions'; if ($wpdb->get_var("SHOW TABLES LIKE '$table'") != $table) { $sql = "CREATE TABLE $table ( id int(20) NOT NULL AUTO_INCREMENT, submission_id int(11), form_id int(11), payment_total int(11) DEFAULT 0, item_name varchar(255), plan_name varchar(255), parent_transaction_id int(11), billing_interval varchar (50), trial_days int(11), initial_amount int(11), quantity int(11) DEFAULT 1, recurring_amount int(11), bill_times int(11), bill_count int(11) DEFAULT 0, vendor_customer_id varchar(255), vendor_subscription_id varchar(255), vendor_plan_id varchar(255), status varchar(255) DEFAULT 'pending', initial_tax_label varchar(255), initial_tax int(11), recurring_tax_label varchar(255), recurring_tax int(11), element_id varchar(255), note text, original_plan text, vendor_response longtext, expiration_at timestamp NULL, created_at timestamp NULL, updated_at timestamp NULL, PRIMARY KEY (id) ) $charsetCollate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); } } }PK!½&src/Payments/Migrations/OrderItems.phpnu[get_charset_collate(); $table = $wpdb->prefix . 'fluentform_order_items'; if ($wpdb->get_var("SHOW TABLES LIKE '$table'") != $table) { $sql = "CREATE TABLE $table ( id int(11) NOT NULL AUTO_INCREMENT, form_id int(11) NOT NULL, submission_id int(11) NOT NULL, type varchar(255) DEFAULT 'single', parent_holder varchar(255), billing_interval varchar(255), item_name varchar(255), quantity int(11) DEFAULT 1, item_price int(11), line_total int(11), created_at timestamp NULL, updated_at timestamp NULL, PRIMARY KEY (id) ) $charsetCollate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); } } }PK!o ll(src/Payments/Migrations/Transactions.phpnu[get_charset_collate(); $table = $wpdb->prefix . 'fluentform_transactions'; // $cols = $wpdb->get_col("DESC {$table}", 0); $sql = "CREATE TABLE $table ( id int(11) NOT NULL AUTO_INCREMENT, transaction_hash varchar(255) NULL, payer_name varchar(255) NULL, payer_email varchar(255) NULL, billing_address varchar(255) NULL, shipping_address varchar(255) NULL, form_id int(11) NOT NULL, user_id int(11) DEFAULT NULL, submission_id int(11) NULL, subscription_id int(11) NULL, transaction_type varchar(255) DEFAULT 'onetime', payment_method varchar(255), card_last_4 int(4), card_brand varchar(255), charge_id varchar(255), payment_total int(11) DEFAULT 1, status varchar(255), currency varchar(255), payment_mode varchar(255), payment_note longtext, created_at timestamp NULL, updated_at timestamp NULL, PRIMARY KEY (id) ) $charsetCollate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); } }PK!*~!src/Payments/Orders/OrderData.phpnu[ $orderItems, 'discount_items' => $discountItems, 'transactions' => static::getTransactions($submission->id), 'refunds' => static::getRefunds($submission->id), 'order_items_subtotal' => static::calculateOrderItemsTotal($orderItems, false, false), 'order_items_total' => static::calculateOrderItemsTotal($orderItems, false, false, $discountItems), 'subscriptions' => $subscriptions, 'subscription_payment_total' => $subscriptionPaymentTotal ]; } public static function getOrderItems($submission) { $items = wpFluent()->table('fluentform_order_items') ->where('submission_id', $submission->id) ->where('type', '!=', 'discount') // type = single, signup_fee ->get(); foreach ($items as $item) { $item->formatted_item_price = PaymentHelper::formatMoney($item->item_price, $submission->currency); $item->formatted_line_total = PaymentHelper::formatMoney($item->line_total, $submission->currency); } return $items; } public static function getDiscounts($submission) { $items = wpFluent()->table('fluentform_order_items') ->where('submission_id', $submission->id) ->where('type', 'discount') ->get(); foreach ($items as $item) { $item->formatted_item_price = PaymentHelper::formatMoney($item->item_price, $submission->currency); $item->formatted_line_total = PaymentHelper::formatMoney($item->line_total, $submission->currency); } return $items; } public static function getTransactions($submissionId) { $transactions = wpFluent()->table('fluentform_transactions') ->where('submission_id', $submissionId) ->whereIn('transaction_type', ['onetime', 'subscription']) ->orderBy('id', 'ASC') ->get(); $formattedTransactions = []; foreach ($transactions as $transaction) { $transaction->payment_note = maybe_unserialize($transaction->payment_note); $transaction = apply_filters_deprecated( 'fluentform_transaction_data_' . $transaction->payment_method, [ $transaction ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/transaction_data_' . $transaction->payment_method, 'Use fluentform/transaction_data_' . $transaction->payment_method . ' instead of fluentform_transaction_data_' . $transaction->payment_method ); $transaction = apply_filters('fluentform/transaction_data_' . $transaction->payment_method, $transaction); if($transaction) { $formattedTransactions[] = $transaction; } } return $formattedTransactions; } public static function getRefunds($submissionId) { $transactions = wpFluent()->table('fluentform_transactions') ->where('submission_id', $submissionId) ->where('transaction_type', 'refund') ->orderBy('id', 'ASC') ->get(); $formattedTransactions = []; foreach ($transactions as $transaction) { $transaction->payment_note = maybe_unserialize($transaction->payment_note); $transaction = apply_filters_deprecated( 'fluentform_transaction_data_' . $transaction->payment_method, [ $transaction ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/transaction_data_' . $transaction->payment_method, 'Use fluentform/transaction_data_' . $transaction->payment_method . ' instead of fluentform_transaction_data_' . $transaction->payment_method ); $transaction = apply_filters('fluentform/transaction_data_' . $transaction->payment_method, $transaction); if($transaction) { $formattedTransactions[] = $transaction; } } return $formattedTransactions; } public static function calculateOrderItemsTotal($orderItems, $formatted = false, $currency = false, $discountItems = []) { $total = 0; foreach ($orderItems as $item) { $total += $item->line_total; } if($discountItems) { foreach ($discountItems as $discountItem) { $total -= $discountItem->line_total; } } if($formatted) { return PaymentHelper::formatMoney($total, $currency); } return $total; } public static function getSubscriptionsAndPaymentTotal($submission) { $subscriptions = wpFluent()->table('fluentform_subscriptions') ->where('submission_id', $submission->id) ->get(); $subscriptionPaymentTotal = 0; foreach ($subscriptions as $subscription) { $subscription->original_plan = maybe_unserialize($subscription->original_plan); $subscription->vendor_response = maybe_unserialize($subscription->vendor_response); $subscription->initial_amount_formatted = PaymentHelper::formatMoney($subscription->initial_amount, $submission->currency); $subscription->recurring_amount_formatted = PaymentHelper::formatMoney($subscription->recurring_amount, $submission->currency); } return [$subscriptions, $subscriptionPaymentTotal]; } public static function getSubscriptionTransactions($subscriptionId) { $transactions = wpFluent()->table('fluentform_transactions') ->where('subscription_id', $subscriptionId) ->get(); foreach ($transactions as $transaction) { $transaction->payment_note = maybe_unserialize($transaction->payment_note); $transaction->items = apply_filters_deprecated( 'fluentform_subscription_items_' . $transaction->payment_method, [ [], $transaction ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/subscription_items_' . $transaction->payment_method, 'Use fluentform/subscription_items_' . $transaction->payment_method . ' instead of fluentform_subscription_items_' . $transaction->payment_method ); $transaction->items = apply_filters('fluentform/subscription_items_'.$transaction->payment_method, [], $transaction); } $transactions = apply_filters_deprecated( 'fluentform_subscription_transactions', [ $transactions, $subscriptionId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/subscription_transactions', 'Use fluentform/subscription_transactions instead of fluentform_subscription_transactions.' ); return apply_filters('fluentform/subscription_transactions', $transactions, $subscriptionId); } public static function getTotalPaid($submission) { return PaymentHelper::formatMoney($submission->payment_total, $submission->currency); } } PK!jo.src/Payments/PaymentMethods/Mollie/API/IPN.phpnu[ 0) { // Append the data $encoded_data .= $arg_separator . $post_data; } else { // Check if POST is empty if (empty($_POST)) { // Nothing to do return; } else { // Loop through each POST foreach ($_POST as $key => $value) { // Encode the value and append the data $encoded_data .= $arg_separator . "$key=" . urlencode($value); } } } // Convert collected post data to an array parse_str($encoded_data, $encoded_data_array); foreach ($encoded_data_array as $key => $value) { if (false !== strpos($key, 'amp;')) { $new_key = str_replace('&', '&', $key); $new_key = str_replace('amp;', '&', $new_key); unset($encoded_data_array[$key]); $encoded_data_array[$new_key] = $value; } } $defaults = $_REQUEST; $encoded_data_array = wp_parse_args($encoded_data_array, $defaults); $this->handleIpn($encoded_data_array); exit(200); } protected function handleIpn($data) { $submissionId = intval(ArrayHelper::get($data, 'submission_id')); if (!$submissionId || empty($data['id'])) { return; } $submission = wpFluent()->table('fluentform_submissions')->where('id', $submissionId)->first(); if (!$submission) { return; } $vendorTransaction = $this->makeApiCall('payments/'.$data['id'], [], $submission->form_id, 'GET'); if(is_wp_error($vendorTransaction)) { $logData = [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Payment', 'status' => 'error', 'title' => __('Mollie Payment Webhook Error', 'fluentformpro'), 'description' => $vendorTransaction->get_error_message() ]; do_action('fluentform/log_data', $logData); return false; } $status = $vendorTransaction['status']; do_action_deprecated( 'fluentform_ipn_mollie_action_' . $status, [ $submission, $vendorTransaction, $data ], 'fluentform/ipn_mollie_action_' . $status, 'Use fluentform/ipn_mollie_action_' . $status . ' instead of fluentform_ipn_mollie_action_' . $status ); do_action('fluentform/ipn_mollie_action_' . $status, $submission, $vendorTransaction, $data); $refundedAmount = $refundAmount = ArrayHelper::get($vendorTransaction, 'amountRefunded.value'); if (intval($refundedAmount)) { $refundAmount = intval($refundAmount * 100); // in cents do_action_deprecated( 'fluentform_ipn_mollie_action_refunded', [ $refundAmount, $submission, $vendorTransaction, $data ], 'fluentform/ipn_mollie_action_refunded', 'Use fluentform/ipn_mollie_action_refunded instead of fluentform_ipn_mollie_action_refunded.' ); do_action('fluentform/ipn_mollie_action_refunded', $refundAmount, $submission, $vendorTransaction, $data); } } public function makeApiCall($path, $args, $formId, $method = 'GET') { $apiKey = MollieSettings::getApiKey($formId); $headers = [ 'Authorization' => 'Bearer ' . $apiKey ]; if($method == 'POST') { $response = wp_remote_post('https://api.mollie.com/v2/'.$path, [ 'headers' => $headers, 'body' => $args ]); } else { $response = wp_remote_get('https://api.mollie.com/v2/'.$path, [ 'headers' => $headers, 'body' => $args ]); } if(is_wp_error($response)) { return $response; } $body = wp_remote_retrieve_body($response); $responseData = json_decode($body, true); if(empty($responseData['id'])) { $message = ArrayHelper::get($responseData, 'detail'); if(!$message) { $message = ArrayHelper::get($responseData, 'error.message'); } if(!$message) { $message = __('Unknown Mollie API request error', 'fluentformpro'); } return new \WP_Error(423, $message, $responseData); } return $responseData; } }PK!994src/Payments/PaymentMethods/Mollie/MollieHandler.phpnu[key, array($this, 'validateSettings'), 10, 2); if(!$this->isEnabled()) { return; } add_filter('fluentform/transaction_data_' . $this->key, array($this, 'modifyTransaction'), 10, 1); add_filter( 'fluentform/available_payment_methods', [$this, 'pushPaymentMethodToForm'] ); (new MollieProcessor())->init(); } public function pushPaymentMethodToForm($methods) { $methods[$this->key] = [ 'title' => __('Mollie', 'fluentformpro'), 'enabled' => 'yes', 'method_value' => $this->key, 'settings' => [ 'option_label' => [ 'type' => 'text', 'template' => 'inputText', 'value' => 'Pay with Mollie', 'label' => __('Method Label', 'fluentformpro') ] ] ]; return $methods; } public function validateSettings($errors, $settings) { if (ArrayHelper::get($settings, 'is_active') == 'no') { return []; } $mode = ArrayHelper::get($settings, 'payment_mode'); if (!$mode) { $errors['payment_mode'] = __('Please select Payment Mode', 'fluentformpro'); } if ($mode == 'test') { if (!ArrayHelper::get($settings, 'test_api_key')) { $errors['test_api_key'] = __('Mollie Test API Key is required', 'fluentformpro'); } } elseif ($mode == 'live') { if (!ArrayHelper::get($settings, 'live_api_key')) { $errors['live_api_key'] = __('Mollie Live API Key is required', 'fluentformpro'); } } return $errors; } public function modifyTransaction($transaction) { if (is_array($transaction->payment_note) && $transactionUrl = ArrayHelper::get($transaction->payment_note, '_links.dashboard.href')) { $transaction->action_url = $transactionUrl; } return $transaction; } public function isEnabled() { $settings = $this->getGlobalSettings(); return $settings['is_active'] == 'yes'; } public function getGlobalFields() { return [ 'label' => 'Mollie', 'fields' => [ [ 'settings_key' => 'is_active', 'type' => 'yes-no-checkbox', 'label' => __('Status', 'fluentformpro'), 'checkbox_label' => __('Enable Mollie Payment Method', 'fluentformpro'), ], [ 'settings_key' => 'payment_mode', 'type' => 'input-radio', 'label' => __('Payment Mode', 'fluentformpro'), 'options' => [ 'test' => __('Test Mode', 'fluentformpro'), 'live' => __('Live Mode', 'fluentformpro'), ], 'info_help' => __('Select the payment mode. for testing purposes you should select Test Mode otherwise select Live mode.', 'fluentformpro'), 'check_status' => 'yes' ], [ 'settings_key' => 'test_api_key', 'type' => 'input-text', 'data_type' => 'password', 'placeholder' => __('Test API Key', 'fluentformpro'), 'label' => __('Test API Key', 'fluentformpro'), 'inline_help' => __('Provide your test api key for your test payments', 'fluentformpro'), 'check_status' => 'yes' ], [ 'settings_key' => 'live_api_key', 'type' => 'input-text', 'data_type' => 'password', 'label' => __('Live API Key', 'fluentformpro'), 'placeholder' => __('Live API Key', 'fluentformpro'), 'inline_help' => __('Provide your live api key for your live payments', 'fluentformpro'), 'check_status' => 'yes' ], [ 'type' => 'html', 'html' => __('

    Please read the documentation to learn how to setup Mollie Payment Gateway.

    ', 'fluentformpro') ], ] ]; } public function getGlobalSettings() { return MollieSettings::getSettings(); } } PK!Fv|!|!6src/Payments/PaymentMethods/Mollie/MollieProcessor.phpnu[method, array($this, 'handlePaymentAction'), 10, 6); add_action('fluentform/payment_frameless_' . $this->method, array($this, 'handleSessionRedirectBack')); add_action('fluentform/ipn_endpoint_' . $this->method, function () { (new IPN())->verifyIPN(); exit(200); }); add_action('fluentform/ipn_mollie_action_paid', array($this, 'handlePaid'), 10, 2); add_action('fluentform/ipn_mollie_action_refunded', array($this, 'handleRefund'), 10, 3); add_filter( 'fluentform/validate_payment_items_' . $this->method, [$this, 'validateSubmittedItems'], 10, 4 ); } public function handlePaymentAction($submissionId, $submissionData, $form, $methodSettings, $hasSubscriptions, $totalPayable) { $this->setSubmissionId($submissionId); $this->form = $form; $submission = $this->getSubmission(); if ($hasSubscriptions) { do_action('fluentform/log_data', [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Payment', 'status' => 'info', 'title' => __('Skip Subscription Item', 'fluentformpro'), 'description' => __('Mollie does not support subscriptions right now!', 'fluentformpro') ]); } $uniqueHash = md5($submission->id . '-' . $form->id . '-' . time() . '-' . mt_rand(100, 999)); $transactionId = $this->insertTransaction([ 'transaction_type' => 'onetime', 'transaction_hash' => $uniqueHash, 'payment_total' => $this->getAmountTotal(), 'status' => 'pending', 'currency' => PaymentHelper::getFormCurrency($form->id), 'payment_mode' => $this->getPaymentMode() ]); $transaction = $this->getTransaction($transactionId); $this->handleRedirect($transaction, $submission, $form, $methodSettings); } public function handleRedirect($transaction, $submission, $form, $methodSettings) { $successUrl = add_query_arg(array( 'fluentform_payment' => $submission->id, 'payment_method' => $this->method, 'transaction_hash' => $transaction->transaction_hash, 'type' => 'success' ), site_url('/')); $ipnDomain = site_url('index.php'); if(defined('FLUENTFORM_PAY_IPN_DOMAIN') && FLUENTFORM_PAY_IPN_DOMAIN) { $ipnDomain = FLUENTFORM_PAY_IPN_DOMAIN; } $listener_url = add_query_arg(array( 'fluentform_payment_api_notify' => 1, 'payment_method' => $this->method, 'submission_id' => $submission->id, 'transaction_hash' => $transaction->transaction_hash, ), $ipnDomain); $paymentArgs = array( 'amount' => [ 'currency' => $transaction->currency, 'value' => number_format((float) $transaction->payment_total / 100, 2, '.', '') ], 'description' => $form->title, 'redirectUrl' => $successUrl, 'webhookUrl' => $listener_url, 'metadata' => json_encode([ 'form_id' => $form->id, 'submission_id' => $submission->id ]), 'sequenceType' => 'oneoff' ); $paymentArgs = apply_filters_deprecated( 'fluentform_mollie_payment_args', [ $paymentArgs, $submission, $transaction, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/mollie_payment_args', 'Use fluentform/mollie_payment_args instead of fluentform_mollie_payment_args' ); $paymentArgs = apply_filters('fluentform/mollie_payment_args', $paymentArgs, $submission, $transaction, $form); $paymentIntent = (new IPN())->makeApiCall('payments', $paymentArgs, $form->id, 'POST'); if(is_wp_error($paymentIntent)) { $logData = [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Payment', 'status' => 'error', 'title' => __('Mollie Payment Redirect Error', 'fluentformpro'), 'description' => $paymentIntent->get_error_message() ]; do_action('fluentform/log_data', $logData); wp_send_json_success([ 'message' => $paymentIntent->get_error_message() ], 423); } Helper::setSubmissionMeta($submission->id, '_mollie_payment_id', $paymentIntent['id']); $logData = [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Payment', 'status' => 'info', 'title' => __('Redirect to Mollie', 'fluentformpro'), 'description' => __('User redirect to Mollie for completing the payment', 'fluentformpro') ]; do_action('fluentform/log_data', $logData); wp_send_json_success([ 'nextAction' => 'payment', 'actionName' => 'normalRedirect', 'redirect_url' => $paymentIntent['_links']['checkout']['href'], 'message' => __('You are redirecting to Mollie.com to complete the purchase. Please wait while you are redirecting....', 'fluentformpro'), 'result' => [ 'insert_id' => $submission->id ] ], 200); } protected function getPaymentMode($formId = false) { $isLive = MollieSettings::isLive($formId); if($isLive) { return 'live'; } return 'test'; } public function handlePaid($submission, $vendorTransaction) { $this->setSubmissionId($submission->id); $transaction = $this->getLastTransaction($submission->id); if (!$transaction || $transaction->payment_method != $this->method) { return; } // Check if actions are fired if ($this->getMetaData('is_form_action_fired') == 'yes') { return; } $status = 'paid'; // Let's make the payment as paid $updateData = [ 'payment_note' => maybe_serialize($vendorTransaction), 'charge_id' => sanitize_text_field($vendorTransaction['id']), ]; $this->updateTransaction($transaction->id, $updateData); $this->changeSubmissionPaymentStatus($status); $this->changeTransactionStatus($transaction->id, $status); $this->recalculatePaidTotal(); $this->completePaymentSubmission(false); $this->setMetaData('is_form_action_fired', 'yes'); } public function handleRefund($refundAmount, $submission, $vendorTransaction) { $this->setSubmissionId($submission->id); $transaction = $this->getLastTransaction($submission->id); $this->updateRefund($refundAmount, $transaction, $submission, $this->method); } public function validateSubmittedItems($errors, $paymentItems, $subscriptionItems, $form) { $singleItemTotal = 0; foreach ($paymentItems as $paymentItem) { if ($paymentItem['line_total']) { $singleItemTotal += $paymentItem['line_total']; } } if (count($subscriptionItems) && !$singleItemTotal) { $errors[] = __('Mollie Error: Mollie does not support subscriptions right now!', 'fluentformpro'); } return $errors; } } PK![]`5src/Payments/PaymentMethods/Mollie/MollieSettings.phpnu[ 'no', 'payment_mode' => 'test', 'test_api_key' => '', 'live_api_key' => '' ]; return wp_parse_args(get_option('fluentform_payment_settings_mollie', []), $defaults); } public static function isLive($formId = false) { $settings = self::getSettings(); return $settings['payment_mode'] == 'live'; } public static function getApiKey($formId = false) { $isLive = self::isLive($formId); $settings = self::getSettings(); if($isLive) { return $settings['live_api_key']; } return $settings['test_api_key']; } }PK!""8src/Payments/PaymentMethods/Offline/OfflineProcessor.phpnu[form = $form; $this->setSubmissionId($submissionId); $amountTotal = $this->getAmountTotal(); if($amountTotal || $hasSubscriptions) { $this->createInitialPendingTransaction($this->getSubmission(), $hasSubscriptions); } } public function getPaymentMode() { return $this->method; } } PK!)6src/Payments/PaymentMethods/Offline/OfflineHandler.phpnu[key, array($this, 'getSettings')); if(!$this->isEnabled()) { return; } add_filter( 'fluentform/available_payment_methods', [$this, 'pushPaymentMethodToForm'] ); add_filter('fluentform/transaction_data_' . $this->key, array($this, 'modifyTransaction'), 10, 1); add_filter('fluentform/payment_method_public_name_' . $this->key, function ($name) { return __('Offline', 'fluentformpro'); }); (new OfflineProcessor())->init(); } public function pushPaymentMethodToForm($methods) { $methods[$this->key] = [ 'title' => __('Offline Payment', 'fluentformpro'), 'enabled' => 'yes', 'method_value' => $this->key, 'settings' => [ 'option_label' => [ 'type' => 'text', 'template' => 'inputText', 'value' => 'Offline Payment', 'label' => __('Method Label', 'fluentformpro') ] ] ]; return $methods; } public function getSettings() { $defaults = [ 'is_active' => 'no', 'payment_mode' => 'test', 'payment_instruction' => '' ]; $settings = get_option('fluentform_payment_settings_test', []); $settings = wp_parse_args($settings, $defaults); return $settings; } public function isEnabled() { $settings = $this->getSettings(); return $settings['is_active'] == 'yes'; } public function modifyTransaction($transaction) { $transaction->payment_method = __('Offline', 'fluentformpro'); return $transaction; } } PK!v1]jXjX.src/Payments/PaymentMethods/PayPal/API/IPN.phpnu[ 0) { // Append the data $encoded_data .= $arg_separator . $post_data; } else { // Check if POST is empty if (empty($_POST)) { PaymentHelper::log([ 'status' => 'error', 'title' => __('Invalid PayPal IPN Notification Received. No Posted Data', 'fluentformpro'), 'description' => json_encode($_GET) ]); // Nothing to do return false; } else { // Loop through each POST foreach ($_POST as $key => $value) { // Encode the value and append the data $encoded_data .= $arg_separator . "$key=" . urlencode($value); } } } try { $encoded_data = $this->utf8_encode_custom(urldecode($encoded_data)); // Convert collected post data to an array parse_str($encoded_data, $encoded_data_array); } catch (\Exception $e) { // } foreach ($encoded_data_array as $key => $value) { if (false !== strpos($key, 'amp;')) { $new_key = str_replace('&', '&', $key); $new_key = str_replace('amp;', '&', $new_key); unset($encoded_data_array[$key]); $encoded_data_array[$new_key] = $value; } } // Check if $post_data_array has been populated if (!is_array($encoded_data_array) && !empty($encoded_data_array)) { PaymentHelper::log([ 'status' => 'error', 'title' => __('Invalid PayPal IPN Notification Received', 'fluentformpro'), 'description' => json_encode($_POST) ]); return false; } $encoded_data_array = apply_filters_deprecated( 'fluentform_process_paypal_ipn_data', [ $encoded_data_array ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/process_paypal_ipn_data', 'Use fluentform/process_paypal_ipn_data instead of fluentform_process_paypal_ipn_data.' ); $encoded_data_array = apply_filters('fluentform/process_paypal_ipn_data', $encoded_data_array); $defaults = array( 'txn_type' => '', 'payment_status' => '', 'custom' => '' ); $encoded_data_array = wp_parse_args($encoded_data_array, $defaults); $customJson = ArrayHelper::get($encoded_data_array, 'custom'); $customArray = json_decode($customJson, true); $paymentSettings = PayPalSettings::getSettings(); if (!$submissionId) { if (!$customArray || empty($customArray['fs_id'])) { $submissionId = false; } else { $submissionId = intval($customArray['fs_id']); } } $submission = false; if ($submissionId) { $submission = wpFluent()->table('fluentform_submissions')->find($submissionId); } if (!$submission) { PaymentHelper::log([ 'status' => 'error', 'title' => __('Invalid PayPal IPN Notification Received. No Submission Found', 'fluentformpro'), 'description' => json_encode($encoded_data_array) ]); return false; } $ipnVerified = false; if ($paymentSettings['disable_ipn_verification'] != 'yes') { $validate_ipn = wp_unslash($_POST); // WPCS: CSRF ok, input var ok. $validate_ipn['cmd'] = '_notify-validate'; // Send back post vars to paypal. $params = array( 'body' => $validate_ipn, 'timeout' => 60, 'httpversion' => '1.1', 'compress' => false, 'decompress' => false, 'user-agent' => 'FluentForm/' . FLUENTFORMPRO_VERSION, ); // Post back to get a response. $response = wp_safe_remote_post((!PayPalSettings::isLive()) ? 'https://www.sandbox.paypal.com/cgi-bin/webscr' : 'https://www.paypal.com/cgi-bin/webscr', $params); if (!is_wp_error($response) && $response['response']['code'] >= 200 && $response['response']['code'] < 300 && strstr($response['body'], 'VERIFIED')) { PaymentHelper::log([ 'status' => 'success', 'title' => __('Received valid response from PayPal IPN', 'fluentformpro'), 'description' => json_encode($encoded_data_array) ], $submission); $ipnVerified = true; } else { PaymentHelper::log([ 'status' => 'error', 'title' => __('PayPal IPN verification Failed', 'fluentformpro'), 'description' => json_encode($encoded_data_array) ], $submission); return false; } } if (has_action('fluentform/ipn_paypal_action_' . $encoded_data_array['txn_type'])) { do_action_deprecated( 'fluentform_ipn_paypal_action_' . $encoded_data_array['txn_type'], [ $encoded_data_array, $submissionId, $submission, $ipnVerified ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/ipn_paypal_action_' . $encoded_data_array['txn_type'], 'Use fluentform/ipn_paypal_action_' . $encoded_data_array['txn_type'] . ' instead of fluentform_ipn_paypal_action_' . $encoded_data_array['txn_type'] ); // Allow PayPal IPN types to be processed separately do_action('fluentform/ipn_paypal_action_' . $encoded_data_array['txn_type'], $encoded_data_array, $submissionId, $submission, $ipnVerified); } else { do_action_deprecated( 'fluentform_ipn_paypal_action_web_accept', [ $encoded_data_array, $submissionId, $submission, $ipnVerified ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/ipn_paypal_action_web_accept', 'Use fluentform/ipn_paypal_action_web_accept instead of fluentform_ipn_paypal_action_web_accept.' ); // Fallback to web accept just in case the txn_type isn't present do_action('fluentform/ipn_paypal_action_web_accept', $encoded_data_array, $submissionId, $submission, $ipnVerified); } exit; } public function updatePaymentStatusFromIPN($data, $submissionId, $submission) { (new PayPalProcessor())->handleWebAcceptPayment($data, $submissionId); } public function processSubscriptionSignup($data, $submissionId, $submission) { $subscription = $this->findSubscriptionBySubmissionId($submissionId); if (!$subscription) { return; } $this->updateSubmission($submissionId, [ 'payment_status' => 'paid', ]); $submission = $this->findSubmission($submissionId); $subscriptionStatus = 'active'; if ($subscription->trial_days && $subscription->status == 'pending') { $subscriptionStatus = 'trialling'; } $this->updateSubscription($subscription->id, [ 'vendor_response' => maybe_serialize($data), 'vendor_customer_id' => $data['payer_id'], 'vendor_subscription_id' => $data['subscr_id'] ]); $subscription = fluentFormApi('submissions')->getSubscription($subscription->id); $paypalProcessor = (new PayPalProcessor()); $paypalProcessor->setSubmissionId($submission->id); $paypalProcessor->updateSubscriptionStatus($subscription, $subscriptionStatus); if ($subscription->status == 'pending') { $logData = [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Subscription', 'status' => 'success', 'title' => __('PayPal Subscription Complete', 'fluentformpro'), 'description' => __('PayPal recurring payment subscription successfully initiated', 'fluentformpro') ]; do_action('fluentform/log_data', $logData); } // PayPal sometimes send subscr_payment after few second and use see empty data // So We have to entry the payment here if (isset($data['from_subscr_signup'])) { // Transaction will be added via processSubscriptionPayment return true; } // Let's check if the transaction actually added or not in the meantime $transaction = wpFluent()->table('fluentform_transactions') ->where('submission_id', $submission->id) ->first(); if ($transaction) { return true; // transaction has been added already } // We have to make a dummy transaction for now with the available data $amount = ArrayHelper::get($data, 'amount3'); if (ArrayHelper::get($data, 'amount1')) { // this for with signup fee $amount = ArrayHelper::get($data, 'amount1'); } $amount = intval($amount * 100); $paymentData = [ 'form_id' => $submission->form_id, 'submission_id' => $submission->id, 'subscription_id' => $subscription->id, 'payer_email' => ArrayHelper::get($data, 'payer_email'), 'payer_name' => trim(ArrayHelper::get($data, 'first_name') . ' ' . ArrayHelper::get($data, 'last_name')), 'transaction_type' => 'subscription', 'payment_method' => 'paypal', 'charge_id' => 'temp_' . $data['subscr_id'], // We don't know the txn id yet so we are adding the subscr_id 'payment_total' => $amount, 'status' => 'paid', 'currency' => $submission->currency, 'payment_mode' => (PayPalSettings::isLive($submission->form_id)) ? 'live' : 'test', 'payment_note' => maybe_serialize($data) ]; if ($submission->user_id) { $paymentData['user_id'] = $submission->user_id; } $paypalProcessor->maybeInsertSubscriptionCharge($paymentData); } public function processSubscriptionPayment($vendorData, $submissionId, $submission) { $subscription = $this->findSubscriptionBySubmissionId($submissionId); if (!$submission || !$subscription) { return false; // maybe the submission has been deleted } if ($subscription->status == 'pending') { $vendorData['from_subscr_signup'] = 'yes'; // somehow the subscr_signup hook could not be fired yet. So let's make it active manually $this->processSubscriptionSignup($vendorData, $submissionId, $submission); $subscription = $this->findSubscriptionBySubmissionId($submissionId); } $paymentStatus = strtolower($vendorData['payment_status']); if ($paymentStatus == 'completed') { $paymentStatus = 'paid'; } $paymentData = [ 'form_id' => $submission->form_id, 'submission_id' => $submission->id, 'subscription_id' => $subscription->id, 'payer_email' => ArrayHelper::get($vendorData, 'payer_email'), 'payer_name' => trim(ArrayHelper::get($vendorData, 'first_name') . ' ' . ArrayHelper::get($vendorData, 'last_name')), 'transaction_type' => 'subscription', 'payment_method' => 'paypal', 'charge_id' => $vendorData['txn_id'], 'payment_total' => intval($vendorData['payment_gross'] * 100), 'status' => $paymentStatus, 'currency' => $submission->currency, 'payment_mode' => (PayPalSettings::isLive($submission->form_id)) ? 'live' : 'test', 'payment_note' => maybe_serialize($vendorData) ]; if ($submission->user_id) { $paymentData['user_id'] = $submission->user_id; } // find the pending transaction $pendingTransaction = wpFluent()->table('fluentform_transactions') ->whereNull('charge_id') ->where('submission_id', $submissionId) ->first(); $payPalProcessor = new PayPalProcessor(); $payPalProcessor->setSubmissionId($submissionId); if ($pendingTransaction) { $payPalProcessor->updateTransaction($pendingTransaction->id, $paymentData); $transactionId = $pendingTransaction->id; } else { $transactionId = $payPalProcessor->maybeInsertSubscriptionCharge($paymentData); } $logData = [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Subscription', 'status' => 'success', 'title' => __('PayPal Subscription Payment', 'fluentformpro'), 'description' => __('Congratulations! New Payment has been received from your subscription', 'fluentformpro') ]; do_action('fluentform/log_data', $logData); do_action_deprecated( 'fluentform_form_submission_activity_start', [ $submission->form_id ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/form_submission_activity_start', 'Use fluentform/form_submission_activity_start instead of fluentform_form_submission_activity_start.' ); do_action('fluentform/form_submission_activity_start', $submission->form_id); $updatedSubscription = $this->findSubscription($subscription->id); $isNewPayment = $subscription->bill_count !== $updatedSubscription->bill_count; $payPalProcessor->recalculatePaidTotal(); if($pendingTransaction) { $returnData = $payPalProcessor->completePaymentSubmission(false); } if ($isNewPayment) { do_action_deprecated( 'fluentform_subscription_payment_received', [ $submission, $updatedSubscription, $submission->form_id, $subscription ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/subscription_payment_received', 'Use fluentform/subscription_payment_received instead of fluentform_subscription_payment_received.' ); do_action('fluentform/subscription_payment_received', $submission, $updatedSubscription, $submission->form_id, $subscription); do_action_deprecated( 'fluentform_subscription_payment_received_paypal', [ $submission, $updatedSubscription, $submission->form_id, $subscription ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/subscription_payment_received_paypal', 'Use fluentform/subscription_payment_received_paypal instead of fluentform_subscription_payment_received_paypal.' ); do_action('fluentform/subscription_payment_received_paypal', $submission, $updatedSubscription, $submission->form_id, $subscription); } if ($updatedSubscription->bill_count === 1) { PaymentHelper::maybeFireSubmissionActionHok($submission); $transaction = $this->findTransaction($transactionId); do_action_deprecated( 'fluentform_form_payment_success', [ $submission, $transaction, $submission->form_id, false ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/form_payment_success', 'Use fluentform/form_payment_success instead of fluentform_form_payment_success.' ); do_action('fluentform/form_payment_success', $submission, $transaction, $submission->form_id, false); } } public function processSubscriptionPaymentCancel($vendorData, $submissionId, $submission) { $subscription = $this->findSubscriptionBySubmissionId($submissionId); if ($subscription) { return; } $paypalProcess = new PayPalProcessor(); $paypalProcess->setSubmissionId($submissionId); $paypalProcess->updateSubscriptionStatus($subscription, 'cancelled'); } public function processSubscriptionPaymentEot($vendorData, $submissionId, $submission) { $subscription = $this->findSubscriptionBySubmissionId($submissionId); if (!$subscription) { return; } $paypalProcess = new PayPalProcessor(); $paypalProcess->setSubmissionId($submissionId); $paypalProcess->updateSubscriptionStatus($subscription, 'completed'); } public function processSubscriptionFailed($vendorData, $submissionId, $submission) { $subscription = $this->findSubscriptionBySubmissionId($submissionId); if (!$subscription) { return; } $paypalProcess = new PayPalProcessor(); $paypalProcess->setSubmissionId($submissionId); $paypalProcess->updateSubscriptionStatus($subscription, 'cancelled'); } private function findSubscriptionBySubmissionId($submissionId) { return wpFluent()->table('fluentform_subscriptions') ->where('submission_id', $submissionId) ->first(); } private function findSubscription($subscriptionId) { return wpFluent()->table('fluentform_subscriptions') ->where('id', $subscriptionId) ->first(); } private function findSubmission($id) { return wpFluent()->table('fluentform_submissions') ->where('id', $id) ->first(); } private function updateSubscription($id, $data) { $data['updated_at'] = current_time('mysql'); wpFluent()->table('fluentform_subscriptions') ->where('id', $id) ->update($data); } private function updateSubmission($id, $data) { $data['updated_at'] = current_time('mysql'); wpFluent()->table('fluentform_submissions') ->where('id', $id) ->update($data); } public function findTransaction($id, $transactionType = 'subscription') { return wpFluent()->table('fluentform_transactions') ->where('id', $id) ->where('transaction_type', $transactionType) ->first(); } /** * With the function it is now possible to replace * all utf8_encode calls with the new utf8_encode_custom function to avoid the deprecation notice * @return false|string */ public function utf8_encode_custom($s) { $s .= $s; $len = \strlen($s); for ($i = $len >> 1, $j = 0; $i < $len; ++$i, ++$j) { switch (true) { case $s[$i] < "\x80": $s[$j] = $s[$i]; break; case $s[$i] < "\xC0": $s[$j] = "\xC2"; $s[++$j] = $s[$i]; break; default: $s[$j] = "\xC3"; $s[++$j] = \chr(\ord($s[$i]) - 64); break; } } return substr($s, 0, $j); } } PK! 5src/Payments/PaymentMethods/PayPal/PayPalSettings.phpnu[ '', 'payment_mode' => 'test', 'is_active' => 'no', 'disable_ipn_verification' => 'yes' ]; $settings = get_option('fluentform_payment_settings_paypal', []); $settings = wp_parse_args($settings, $defaults); return $settings; } public static function getPayPalEmail($formId = false) { if ($formId) { $formPaymentSettings = PaymentHelper::getFormSettings($formId, 'admin'); if (ArrayHelper::get($formPaymentSettings, 'paypal_account_type') == 'custom') { $payPalId = ArrayHelper::get($formPaymentSettings, 'custom_paypal_id'); if($payPalId) { return $payPalId; } } } $settings = self::getSettings(); return $settings['paypal_email']; } public static function isLive($formId = false) { if ($formId) { $formPaymentSettings = PaymentHelper::getFormSettings($formId, 'admin'); if (ArrayHelper::get($formPaymentSettings, 'paypal_account_type') == 'custom') { return ArrayHelper::get($formPaymentSettings, 'custom_paypal_mode') == 'live'; } } $settings = self::getSettings(); return $settings['payment_mode'] == 'live'; } public static function getPaypalRedirect($ssl_check = false, $ipn = false) { $protocol = 'http://'; if (is_ssl() || !$ssl_check) { $protocol = 'https://'; } $isLive = self::isLive(); // Check the current payment mode if ($isLive) { // Live mode if ($ipn) { $paypal_uri = 'https://ipnpb.paypal.com/cgi-bin/webscr'; } else { $paypal_uri = $protocol . 'www.paypal.com/cgi-bin/webscr'; } } else { // Test mode if ($ipn) { $paypal_uri = 'https://ipnpb.sandbox.paypal.com/cgi-bin/webscr'; } else { $paypal_uri = $protocol . 'www.sandbox.paypal.com/cgi-bin/webscr'; } } $paypal_uri = apply_filters_deprecated( 'fluentform_paypal_url', [ $paypal_uri, $ssl_check, $ipn, $isLive ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/paypal_url', 'Use fluentform/paypal_url instead of fluentform_paypal_url.' ); return apply_filters('fluentform/paypal_url', $paypal_uri, $ssl_check, $ipn, $isLive); } }PK!fw;]]6src/Payments/PaymentMethods/PayPal/PayPalProcessor.phpnu[method, array($this, 'handlePaymentAction'), 10, 6); add_action('fluentform/payment_frameless_' . $this->method, array($this, 'handleSessionRedirectBack')); add_action('fluentform/ipn_endpoint_' . $this->method, function () { (new IPN())->verifyIPN(); exit(200); }); add_action('fluentform/ipn_paypal_action_web_accept', array($this, 'handleWebAcceptPayment'), 10, 3); add_filter( 'fluentform/validate_payment_items_' . $this->method, [$this, 'validateSubmittedItems'], 10, 4 ); } public function handlePaymentAction($submissionId, $submissionData, $form, $methodSettings, $hasSubscriptions, $totalPayable) { $this->setSubmissionId($submissionId); $this->form = $form; $submission = $this->getSubmission(); $paymentTotal = $this->getAmountTotal(); if (!$paymentTotal && !$hasSubscriptions) { return false; } // Create the initial transaction here $transaction = $this->createInitialPendingTransaction($submission, $hasSubscriptions); $this->handlePayPalRedirect($transaction, $submission, $form, $methodSettings, $hasSubscriptions); } public function handlePayPalRedirect($transaction, $submission, $form, $methodSettings, $hasSubscriptions) { $paymentSettings = PaymentHelper::getPaymentSettings(); $args = array( 'fluentform_payment' => $submission->id, 'payment_method' => $this->method, 'transaction_hash' => $transaction ? $transaction->transaction_hash : '', 'type' => 'success' ); if (empty($args['transaction_hash'])) { $args['entry_uid'] = Helper::getSubmissionMeta($submission->id, '_entry_uid_hash'); } $successUrl = add_query_arg($args, site_url('index.php')); $cancelUrl = $submission->source_url; if (!wp_http_validate_url($cancelUrl)) { $cancelUrl = home_url($cancelUrl); } $domain = site_url('index.php'); if(defined('FF_PAYPAL_IPN_DOMAIN') && FF_PAYPAL_IPN_DOMAIN) { $domain = FF_PAYPAL_IPN_DOMAIN; } $listener_url = add_query_arg(array( 'fluentform_payment_api_notify' => 1, 'payment_method' => $this->method, 'submission_id' => $submission->id ), $domain); // $customArgs = array( 'fs_id' => $submission->id ); if ($transaction) { $customArgs['transaction_hash'] = $transaction->transaction_hash; } else { $customArgs['entry_uid'] = Helper::getSubmissionMeta($submission->id, '_entry_uid_hash'); } $paypal_args = array( 'cmd' => '_cart', 'upload' => '1', 'rm' => is_ssl() ? 2 : 1, 'business' => PayPalSettings::getPayPalEmail($form->id), 'email' => $transaction->payer_email, 'no_shipping' => (ArrayHelper::get($methodSettings, 'settings.require_shipping_address.value') == 'yes') ? '0' : '1', 'shipping' => (ArrayHelper::get($methodSettings, 'settings.require_shipping_address.value') == 'yes') ? '1' : '0', 'no_note' => '1', 'currency_code' => strtoupper($submission->currency), 'charset' => 'UTF-8', 'custom' => wp_json_encode($customArgs), 'return' => esc_url_raw($successUrl), 'notify_url' => $this->limitLength(esc_url_raw($listener_url), 255), 'cancel_return' => esc_url_raw($cancelUrl) ); if ($businessLogo = ArrayHelper::get($paymentSettings, 'business_logo')) { $paypal_args['image_url'] = $businessLogo; } $paypal_args = wp_parse_args($paypal_args, $this->getCartSummery()); $paypal_args = apply_filters_deprecated( 'fluentform_paypal_checkout_args', [ $paypal_args, $submission, $transaction, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/paypal_checkout_args', 'Use fluentform/paypal_checkout_args instead of fluentform_paypal_checkout_args.' ); $paypal_args = apply_filters('fluentform/paypal_checkout_args', $paypal_args, $submission, $transaction, $form); if ($hasSubscriptions) { $this->customerName = PaymentHelper::getCustomerName($submission, $form); $paypal_args = $this->processSubscription($paypal_args, $transaction, $hasSubscriptions); } $redirectUrl = $this->getRedirectUrl($paypal_args, $form->id); $logData = [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Payment', 'status' => 'info', 'title' => __('Redirect to PayPal', 'fluentformpro'), 'description' => __('User redirect to paypal for completing the payment', 'fluentformpro') ]; do_action('fluentform/log_data', $logData); wp_send_json_success([ 'nextAction' => 'payment', 'actionName' => 'normalRedirect', 'redirect_url' => $redirectUrl, 'message' => __('You are redirecting to PayPal.com to complete the purchase. Please wait while you are redirecting....', 'fluentformpro'), 'result' => [ 'insert_id' => $submission->id ] ], 200); } private function getCartSummery() { $items = $this->getOrderItems(); $paypal_args = array(); if ($items) { $counter = 1; foreach ($items as $item) { if (!$item->item_price) { continue; } $amount = PaymentHelper::floatToString((float)round($item->item_price / 100, 2)); $itemName = PaymentHelper::formatPaymentItemString($item->item_name, 127); $paypal_args['item_name_' . $counter] = PaymentHelper::limitLength($itemName, 127); $paypal_args['quantity_' . $counter] = (int)$item->quantity; $paypal_args['amount_' . $counter] = $amount; $counter = $counter + 1; } } $discountItems = $this->getDiscountItems(); if ($discountItems) { $discountTotal = 0; foreach ($discountItems as $discountItem) { $discountTotal += $discountItem->line_total; } $paypal_args['discount_amount_cart'] = round($discountTotal / 100, 2); } return $paypal_args; } private function getRedirectUrl($args, $formId = false) { if ($this->getPaymentMode($formId) == 'test') { $paypal_redirect = 'https://www.sandbox.paypal.com/cgi-bin/webscr/?test_ipn=1&'; } else { $paypal_redirect = 'https://www.paypal.com/cgi-bin/webscr/?'; } return $paypal_redirect . http_build_query($args, '', '&'); } public function handleSessionRedirectBack($data) { $type = sanitize_text_field($data['type']); $submissionId = intval($data['fluentform_payment']); $this->setSubmissionId($submissionId); $submission = $this->getSubmission(); if (!$submission) { return; } $isNew = false; if ($type == 'success' && $submission->payment_status === 'paid') { $isNew = $this->getMetaData('is_form_action_fired') != 'yes'; $returnData = $this->getReturnData(); } else if ($type == 'success') { $transaction = $this->getLastTransaction($submission->id); $messageTxt = __('Sometimes, PayPal payments take a few moments to mark as paid. We are trying to process your payment. Please do not close or refresh the window.', 'fluentformpro'); $message = "
    {$messageTxt}
    "; $enableSandboxMode = apply_filters('fluentform/enable-paypal-sandbox-mode', true); $loader = true; if($transaction && $transaction->payment_mode != 'live' && !$enableSandboxMode) { $message = __('Looks like you are using sandbox mode. PayPal does not send instant payment notification while using sandbox mode', 'fluentformpro'); $loader = false; } $message = apply_filters_deprecated( 'fluentform_paypal_pending_message', [ $message, $submission ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/paypal_pending_message', 'Use fluentform/paypal_pending_message instead of fluentform_paypal_pending_message.' ); $message = apply_filters('fluentform/paypal_pending_message', $message, $submission); $this->addDelayedCheck($submissionId); $messageTitle = __('Payment is not marked as paid yet. ', 'fluentformpro'); $returnData = [ 'insert_id' => $submission->id, 'title' => apply_filters('fluentform/paypal_pending_message_title', $messageTitle, $submission), 'result' => false, 'error' => $message, 'loader' => $loader ]; } else { $returnData = [ 'insert_id' => $submission->id, 'title' => __('Payment Cancelled', 'fluentformpro'), 'result' => false, 'error' => __('Looks like you have cancelled the payment', 'fluentformpro') ]; } $returnData['type'] = $type; $returnData['is_new'] = $isNew; $this->showPaymentView($returnData); } public function handleWebAcceptPayment($data, $submissionId) { $this->setSubmissionId($submissionId); $submission = $this->getSubmission(); if (!$submission) { return; } $payment_status = strtolower($data['payment_status']); if ($payment_status == 'refunded' || $payment_status == 'reversed') { // Process a refund $this->processRefund($data, $submission); return; } $transaction = $this->getLastTransaction($submissionId); if (!$transaction || $transaction->payment_method != $this->method) { return; } if ($data['txn_type'] != 'web_accept' && $data['txn_type'] != 'cart' && $data['payment_status'] != 'Refunded') { return; } // Check if actions are fired if ($this->getMetaData('is_form_action_fired') == 'yes') { return; } $business_email = isset($data['business']) && is_email($data['business']) ? trim($data['business']) : trim($data['receiver_email']); $this->setMetaData('paypal_receiver_email', $business_email); if ('completed' == $payment_status || 'pending' == $payment_status) { $status = 'paid'; if ($payment_status == 'pending') { $status = 'processing'; } // Let's make the payment as paid $updateData = [ 'payment_note' => maybe_serialize($data), 'charge_id' => sanitize_text_field($data['txn_id']), 'payer_email' => sanitize_text_field($data['payer_email']), 'payer_name' => ArrayHelper::get($data, 'first_name') . ' ' . ArrayHelper::get($data, 'last_name'), 'shipping_address' => $this->getAddress($data) ]; $this->updateTransaction($transaction->id, $updateData); $this->changeSubmissionPaymentStatus($status); $this->changeTransactionStatus($transaction->id, $status); $this->recalculatePaidTotal(); $returnData = $this->completePaymentSubmission(false); $this->setMetaData('is_form_action_fired', 'yes'); if (isset($data['pending_reason'])) { $logData = [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Payment', 'status' => 'info', 'title' => __('PayPal Payment Pending', 'fluentformpro'), 'description' => $this->getPendingReason($data) ]; // Log Processing Reason do_action('fluentform/log_data', $logData); } } } private function processRefund($data, $submission) { if ($submission->payment_status == 'refunded') { return; } if ($submission->payment_status == 'refunded') { return; } // check if already refunded $refundExist = $this->getTransactionByChargeId($data['txn_id']); if ($refundExist) { return; } $transaction = $this->getTransactionByChargeId($data['parent_txn_id']); if (!$transaction) { return; } $refund_amount = $data['mc_gross'] * -100; $this->refund($refund_amount, $transaction, $submission, 'paypal', $data['txn_id'], 'Refund From PayPal'); } private function getAddress($data) { $address = array(); if (!empty($data['address_street'])) { $address['address_line1'] = sanitize_text_field($data['address_street']); } if (!empty($data['address_city'])) { $address['address_city'] = sanitize_text_field($data['address_city']); } if (!empty($data['address_state'])) { $address['address_state'] = sanitize_text_field($data['address_state']); } if (!empty($data['address_zip'])) { $address['address_zip'] = sanitize_text_field($data['address_zip']); } if (!empty($data['address_state'])) { $address['address_country'] = sanitize_text_field($data['address_country_code']); } return implode(', ', $address); } public function getPaymentMode($formId = false) { $isLive = PayPalSettings::isLive($formId); if ($isLive) { return 'live'; } return 'test'; } private function getPendingReason($data) { $note = 'Payment marked as pending'; switch (strtolower($data['pending_reason'])) { case 'echeck' : $note = __('Payment made via eCheck and will clear automatically in 5-8 days', 'fluentformpro'); break; case 'address' : $note = __('Payment requires a confirmed customer address and must be accepted manually through PayPal', 'fluentformpro'); break; case 'intl' : $note = __('Payment must be accepted manually through PayPal due to international account regulations', 'fluentformpro'); break; case 'multi-currency' : $note = __('Payment received in non-shop currency and must be accepted manually through PayPal', 'fluentformpro'); break; case 'paymentreview' : case 'regulatory_review' : $note = __('Payment is being reviewed by PayPal staff as high-risk or in possible violation of government regulations', 'fluentformpro'); break; case 'unilateral' : $note = __('Payment was sent to non-confirmed or non-registered email address.', 'fluentformpro'); break; case 'upgrade' : $note = __('PayPal account must be upgraded before this payment can be accepted', 'fluentformpro'); break; case 'verify' : $note = __('PayPal account is not verified. Verify account in order to accept this payment', 'fluentformpro'); break; case 'other' : $note = __('Payment is pending for unknown reasons. Contact PayPal support for assistance', 'fluentformpro'); break; } return $note; } public function validateSubmittedItems($errors, $paymentItems, $subscriptionItems, $form) { $singleItemTotal = 0; foreach ($paymentItems as $paymentItem) { if ($paymentItem['line_total']) { $singleItemTotal += $paymentItem['line_total']; } } $validSubscriptions = []; foreach ($subscriptionItems as $subscriptionItem) { if ($subscriptionItem['recurring_amount']) { $validSubscriptions[] = $subscriptionItem; } } if ($singleItemTotal && count($validSubscriptions)) { $errors[] = __('PayPal Error: PayPal does not support subscriptions payment and single amount payment at one request', 'fluentformpro'); } if (count($validSubscriptions) > 2) { $errors[] = __('PayPal Error: PayPal does not support multiple subscriptions at one request', 'fluentformpro'); } return $errors; } public function processSubscription($originalArgs, $transaction, $hasSubscriptions) { $paymentSettings = PaymentHelper::getPaymentSettings(); if (!$hasSubscriptions || $transaction->transaction_type != 'subscription') { return $originalArgs; } $subscriptions = $this->getSubscriptions(); $validSubscriptions = []; foreach ($subscriptions as $subscriptionItem) { if ($subscriptionItem->recurring_amount) { $validSubscriptions[] = $subscriptionItem; } } if (!$validSubscriptions || count($validSubscriptions) > 1) { // PayPal Standard does not support more than 1 subscriptions // We may add paypal express later for this on. return $originalArgs; } // We just need the first subscriptipn $subscription = $validSubscriptions[0]; if (!$subscription->recurring_amount) { return $originalArgs; } // Setup PayPal arguments $paypal_args = array( 'business' => $originalArgs['business'], 'email' => $originalArgs['email'], 'invoice' => $transaction->transaction_hash, 'no_shipping' => '1', 'shipping' => '0', 'no_note' => '1', 'currency_code' => strtoupper($originalArgs['currency_code']), 'charset' => 'UTF-8', 'custom' => $originalArgs['custom'], 'rm' => '2', 'return' => $originalArgs['return'], 'cancel_return' => $originalArgs['cancel_return'], 'notify_url' => $originalArgs['notify_url'], 'cbt' => $paymentSettings['business_name'], 'bn' => 'FluentFormPro_SP', 'sra' => '1', 'src' => '1', 'cmd' => '_xclick-subscriptions' ); $names = explode(' ', $transaction->payer_name, 2); if (count($names) == 2) { $firstName = $names[0]; $lastName = $names[1]; } else { $firstName = $transaction->payer_name; $lastName = ''; } if($firstName) { $paypal_args['first_name'] = $firstName; } if($lastName) { $paypal_args['last_name'] = $lastName; } $recurring_amount = $subscription->recurring_amount; $initial_amount = $transaction->payment_total - $recurring_amount; $recurring_amount = round($recurring_amount / 100, 2); $initial_amount = round($initial_amount / 100, 2); if ($initial_amount) { $paypal_args['a1'] = round($initial_amount + $recurring_amount, 2); $paypal_args['p1'] = 1; } else if ($subscription->trial_days) { $paypal_args['a1'] = 0; $paypal_args['p1'] = $subscription->trial_days; $paypal_args['t1'] = 'D'; } $paypal_args['a3'] = $recurring_amount; $paypal_args['item_name'] = $subscription->item_name . ' - ' . $subscription->plan_name; $paypal_args['p3'] = 1; // for now it's 1 as 1 times per period switch ($subscription->billing_interval) { case 'day': $paypal_args['t3'] = 'D'; break; case 'week': $paypal_args['t3'] = 'W'; break; case 'month': $paypal_args['t3'] = 'M'; break; case 'year': $paypal_args['t3'] = 'Y'; break; } if ($initial_amount) { $paypal_args['t1'] = $paypal_args['t3']; } if ($subscription->bill_times > 1) { if ($initial_amount) { $subscription->bill_times = $subscription->bill_times - 1; } $billTimes = $subscription->bill_times <= 52 ? absint($subscription->bill_times) : 52; $paypal_args['srt'] = $billTimes; } foreach ($paypal_args as $argName => $argValue) { if($argValue === '') { unset($paypal_args[$argName]); } } return $paypal_args; } public function addDelayedCheck($submissionId) { wp_enqueue_script('ff_paypal', FLUENTFORMPRO_DIR_URL.'public/js/ff_paypal.js', ['jquery'], FLUENTFORM_VERSION, true); $delayedCheckVars = [ 'ajax_url' => admin_url('admin-ajax.php'), 'submission_id' => $submissionId, 'timeout' => 10000, 'onFailedMessage' => __("Sorry! We couldn't mark your payment as paid. Please try again later!", 'fluentformpro') ]; wp_localize_script('ff_paypal', 'ff_paypal_vars',apply_filters('fluentform/paypal_delayed_check_vars', $delayedCheckVars)); } /** * Check if paypal payment is marked paid * @return json response */ public function isPaid() { $submissionId = intval($_REQUEST['submission_id']); $this->setSubmissionId($submissionId); $submission = $this->getSubmission(); if (!$submission ) { wp_send_json([ 'message' => __('Invalid Payment Transaction', 'fluentformpro'), ]); } if ($submission->payment_status == 'paid') { wp_send_json_success([ 'nextAction' => 'reload', ]); } else { wp_send_json_success([ 'nextAction' => 'reCheck', 'payment_status' => $submission->payment_status ]); } } } PK!%Qk k 4src/Payments/PaymentMethods/PayPal/PayPalHandler.phpnu[key, function () { return PayPalSettings::getSettings(); }); add_filter('fluentform/payment_method_settings_validation_' . $this->key, array($this, 'validateSettings'), 10, 2); if(!$this->isEnabled()) { return; } add_filter('fluentform/transaction_data_' . $this->key, array($this, 'modifyTransaction'), 10, 1); add_filter( 'fluentform/available_payment_methods', [$this, 'pushPaymentMethodToForm'] ); (new IPN())->init(); (new PayPalProcessor())->init(); } public function pushPaymentMethodToForm($methods) { $methods[$this->key] = [ 'title' => __('PayPal', 'fluentformpro'), 'enabled' => 'yes', 'method_value' => $this->key, 'settings' => [ 'option_label' => [ 'type' => 'text', 'template' => 'inputText', 'value' => 'Pay with PayPal', 'label' => __('Method Label', 'fluentformpro'), ], 'require_shipping_address' => [ 'type' => 'checkbox', 'template' => 'inputYesNoCheckbox', 'value' => 'no', 'label' => __('Require Shipping Address', 'fluentformpro'), ] ] ]; return $methods; } public function validateSettings($errors, $settings) { if (ArrayHelper::get($settings, 'is_active') == 'no') { return []; } if (!ArrayHelper::get($settings, 'paypal_email')) { $errors['paypal_email'] = __('PayPal Email Address is required', 'fluentformpro'); } if (!ArrayHelper::get($settings, 'payment_mode')) { $errors['payment_mode'] = __('Please select Payment Mode', 'fluentformpro'); } return $errors; } public function modifyTransaction($transaction) { if ($transaction->charge_id) { $sandbox = 'test' == $transaction->payment_mode ? 'sandbox.' : ''; $transaction->action_url = 'https://www.' . $sandbox . 'paypal.com/activity/payment/' . $transaction->charge_id; } if ($transaction->status == 'requires_capture') { $transaction->additional_note = __('Action Required: The payment has been authorized but not captured yet. Please Click here to capture this payment in stripe.com', 'fluentformpro'); } return $transaction; } public function isEnabled() { $settings = PayPalSettings::getSettings(); return $settings['is_active'] == 'yes'; } } PK!..:src/Payments/PaymentMethods/Paystack/PaystackProcessor.phpnu[method, array($this, 'handlePaymentAction'), 10, 6); add_action('fluentform/ipn_razorpay_action_paid', array($this, 'handlePaid'), 10, 2); add_action('fluentform/ipn_razorpay_action_refunded', array($this, 'handleRefund'), 10, 3); add_filter('fluentform/validate_payment_items_' . $this->method, [$this, 'validateSubmittedItems'], 10, 4); add_action('fluentform/rendering_payment_method_' . $this->method, array($this, 'addCheckoutJs'), 10, 3); add_action('wp_ajax_fluentform_paystack_confirm_payment', array($this, 'confirmModalPayment')); add_action('wp_ajax_nopriv_fluentform_paystack_confirm_payment', array($this, 'confirmModalPayment')); } public function handlePaymentAction($submissionId, $submissionData, $form, $methodSettings, $hasSubscriptions, $totalPayable) { $this->setSubmissionId($submissionId); $this->form = $form; $submission = $this->getSubmission(); if ($hasSubscriptions) { do_action('fluentform/log_data', [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Payment', 'status' => 'info', 'title' => __('Skip Subscription Item', 'fluentformpro'), 'description' => __('PayStack does not support subscriptions right now!', 'fluentformpro') ]); } $uniqueHash = md5($submission->id . '-' . $form->id . '-' . time() . '-' . mt_rand(100, 999)); $transactionId = $this->insertTransaction([ 'transaction_type' => 'onetime', 'transaction_hash' => $uniqueHash, 'payment_total' => $this->getAmountTotal(), 'status' => 'pending', 'currency' => PaymentHelper::getFormCurrency($form->id), 'payment_mode' => $this->getPaymentMode() ]); $transaction = $this->getTransaction($transactionId); $this->maybeShowModal($transaction, $submission, $form, $methodSettings); } protected function getPaymentMode($formId = false) { $isLive = PaystackSettings::isLive($formId); if ($isLive) { return 'live'; } return 'test'; } public function handlePaid($submission, $transaction, $vendorTransaction) { $this->setSubmissionId($submission->id); // Check if actions are fired if ($this->getMetaData('is_form_action_fired') == 'yes') { return $this->completePaymentSubmission(false); } $status = 'paid'; // Let's make the payment as paid $updateData = [ 'payment_note' => maybe_serialize($vendorTransaction), 'charge_id' => sanitize_text_field($vendorTransaction['id']), 'payer_email' => $vendorTransaction['customer']['email'], 'payment_total' => intval($vendorTransaction['amount']), 'currency' => strtoupper($vendorTransaction['currency']) ]; if ($cardBrand = ArrayHelper::get($vendorTransaction, 'authorization.brand')) { $updateData['card_brand'] = $cardBrand; } if ($last4 = ArrayHelper::get($vendorTransaction, 'authorization.last4')) { $updateData['card_last_4'] = $last4; } $this->updateTransaction($transaction->id, $updateData); $this->changeSubmissionPaymentStatus($status); $this->changeTransactionStatus($transaction->id, $status); $this->recalculatePaidTotal(); $returnData = $this->getReturnData(); $this->setMetaData('is_form_action_fired', 'yes'); if(intval($vendorTransaction['amount']) != $transaction->payment_total || strtoupper($transaction->currency) != strtoupper($vendorTransaction['currency'])) { $logData = [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Payment', 'status' => 'error', 'title' => __('Transaction Amount Mismatch - PayStack', 'fluentformpro'), 'description' => __('Transaction Amount should be '.PaymentHelper::formatMoney($transaction->payment_total, $transaction->currency).' but received '.PaymentHelper::formatMoney(intval($vendorTransaction['amount']), strtoupper($vendorTransaction['currency'])), 'fluentformpro') ]; do_action('fluentform/log_data', $logData); } return $returnData; } public function handleRefund($refundAmount, $submission, $vendorTransaction) { $this->setSubmissionId($submission->id); $transaction = $this->getLastTransaction($submission->id); $this->updateRefund($refundAmount, $transaction, $submission, $this->method); } public function validateSubmittedItems($errors, $paymentItems, $subscriptionItems, $form) { $singleItemTotal = 0; foreach ($paymentItems as $paymentItem) { if ($paymentItem['line_total']) { $singleItemTotal += $paymentItem['line_total']; } } if (count($subscriptionItems) && !$singleItemTotal) { $errors[] = __('PayStack Error: PayStack does not support subscriptions right now!', 'fluentformpro'); } return $errors; } public function addCheckoutJs($methodElement, $element, $form) { wp_enqueue_script('paystack', 'https://js.paystack.co/v1/inline.js', [], FLUENTFORMPRO_VERSION); wp_enqueue_script('ff_paystack_handler', FLUENTFORMPRO_DIR_URL . 'public/js/paystack_handler.js', ['jquery'], FLUENTFORMPRO_VERSION); } public function maybeShowModal($transaction, $submission, $form, $methodSettings) { // check if the currency is valid $currency = strtoupper($transaction->currency); if (!in_array($currency, ['NGN', 'GHS', 'ZAR', 'USD', 'KES'])) { wp_send_json([ 'errors' => $currency . __('is not supported by PayStack payment method', 'fluentformpro'), 'append_data' => [ '__entry_intermediate_hash' => Helper::getSubmissionMeta($submission->id, '__entry_intermediate_hash') ] ], 423); } $keys = PaystackSettings::getApiKeys($form->id); $modalData = [ 'key' => $keys['api_key'], 'email' => $transaction->payer_email, 'ref' => $transaction->transaction_hash, 'amount' => intval($transaction->payment_total), 'currency' => $currency, // 'label' => $form->title, 'metadata' => [ 'payment_handler' => 'Fluent Forms', 'form_id' => $form->id, 'transaction_id' => $transaction->id, 'form' => $form->title ] ]; $logData = [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Payment', 'status' => 'info', 'title' => __('PayStack Modal is initiated', 'fluentformpro'), 'description' => __('PayStack Modal is initiated to complete the payment', 'fluentformpro') ]; do_action('fluentform/log_data', $logData); # Tell the client to handle the action wp_send_json_success([ 'nextAction' => 'paystack', 'actionName' => 'initPaystackModal', 'submission_id' => $submission->id, 'modal_data' => $modalData, 'transaction_hash' => $transaction->transaction_hash, 'message' => __('Payment Modal is opening, Please complete the payment', 'fluentformpro'), 'confirming_text' => __('Confirming Payment, Please wait...', 'fluentformpro'), 'result' => [ 'insert_id' => $submission->id ], 'append_data' => [ '__entry_intermediate_hash' => Helper::getSubmissionMeta($transaction->submission_id, '__entry_intermediate_hash') ] ], 200); } public function confirmModalPayment() { $data = $_REQUEST; $transactionHash = sanitize_text_field(ArrayHelper::get($data, 'trxref')); $transaction = $this->getTransaction($transactionHash, 'transaction_hash'); if (!$transaction || $transaction->status != 'pending') { wp_send_json([ 'errors' => __('Payment Error: Invalid Request', 'fluentformpro'), ], 423); } $paymentReference = sanitize_text_field(ArrayHelper::get($data, 'reference')); $vendorPayment = (new API())->makeApiCall('transaction/verify/' . $paymentReference, [], $transaction->form_id); if (is_wp_error($vendorPayment)) { $logData = [ 'parent_source_id' => $transaction->form_id, 'source_type' => 'submission_item', 'source_id' => $transaction->submission_id, 'component' => 'Payment', 'status' => 'failed', 'title' => __('PayStack Payment is failed to verify', 'fluentformpro'), 'description' => $vendorPayment->get_error_message() ]; do_action('fluentform/log_data', $logData); wp_send_json([ 'errors' => __('Payment Error: ', 'fluentformpro') . $vendorPayment->get_error_message(), 'append_data' => [ '__entry_intermediate_hash' => Helper::getSubmissionMeta($transaction->submission_id, '__entry_intermediate_hash') ] ], 423); } $vendorData = $vendorPayment['data']; if ($vendorData['status'] == 'success') { $logData = [ 'parent_source_id' => $transaction->form_id, 'source_type' => 'submission_item', 'source_id' => $transaction->submission_id, 'component' => 'Payment', 'status' => 'success', 'title' => __('Payment Success by PayStack', 'fluentformpro'), 'description' => __('PayStack payment has been marked as paid. TransactionId: ', 'fluentformpro') . $vendorData['id'] ]; do_action('fluentform/log_data', $logData); $this->setSubmissionId($transaction->submission_id); $submission = $this->getSubmission(); $returnData = $this->handlePaid($submission, $transaction, $vendorData); $returnData['vendor_data'] = $vendorData; wp_send_json_success($returnData, 200); } wp_send_json([ 'errors' => __('Payment could not be verified. Please contact site admin', 'fluentformpro'), 'append_data' => [ '__entry_intermediate_hash' => Helper::getSubmissionMeta($transaction->submission_id, '__entry_intermediate_hash') ] ], 423); } } PK!'T9src/Payments/PaymentMethods/Paystack/PaystackSettings.phpnu[ 'no', 'payment_mode' => 'test', 'checkout_type' => 'modal', 'test_api_key' => '', 'test_api_secret' => '', 'live_api_key' => '', 'live_api_secret' => '', 'payment_channels' => [] ]; return wp_parse_args(get_option('fluentform_payment_settings_paystack', []), $defaults); } public static function isLive($formId = false) { $settings = self::getSettings(); return $settings['payment_mode'] == 'live'; } public static function getApiKeys($formId = false) { $isLive = self::isLive($formId); $settings = self::getSettings(); if($isLive) { return [ 'api_key' => $settings['live_api_key'], 'api_secret' => $settings['live_api_secret'], ]; } return [ 'api_key' => $settings['test_api_key'], 'api_secret' => $settings['test_api_secret'], ]; } }PK!Dxo,src/Payments/PaymentMethods/Paystack/API.phpnu[ 0) { // Append the data $encoded_data .= $arg_separator . $post_data; } else { // Check if POST is empty if (empty($_POST)) { // Nothing to do return; } else { // Loop through each POST foreach ($_POST as $key => $value) { // Encode the value and append the data $encoded_data .= $arg_separator . "$key=" . urlencode($value); } } } // Convert collected post data to an array parse_str($encoded_data, $encoded_data_array); foreach ($encoded_data_array as $key => $value) { if (false !== strpos($key, 'amp;')) { $new_key = str_replace('&', '&', $key); $new_key = str_replace('amp;', '&', $new_key); unset($encoded_data_array[$key]); $encoded_data_array[$new_key] = $value; } } $defaults = $_REQUEST; $encoded_data_array = wp_parse_args($encoded_data_array, $defaults); $this->handleIpn($encoded_data_array); exit(200); } protected function handleIpn($data) { $submissionId = intval(ArrayHelper::get($data, 'submission_id')); if (!$submissionId || empty($data['id'])) { return; } $submission = wpFluent()->table('fluentform_submissions')->where('id', $submissionId)->first(); if (!$submission) { return; } $vendorTransaction = $this->makeApiCall('payments/' . $data['id'], [], $submission->form_id, 'GET'); if (is_wp_error($vendorTransaction)) { $logData = [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Payment', 'status' => 'error', 'title' => __('Mollie Payment Webhook Error', 'fluentformpro'), 'description' => $vendorTransaction->get_error_message() ]; do_action('fluentform/log_data', $logData); } $status = $vendorTransaction['status']; if ($status == 'captured') { $status = 'paid'; } do_action_deprecated( 'fluentform_ipn_razorpay_action_' . $status, [ $submission, $vendorTransaction, $data ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/ipn_razorpay_action_' . $status, 'Use fluentform/ipn_razorpay_action_' . $status . ' instead of fluentform_ipn_razorpay_action_' . $status ); do_action('fluentform/ipn_razorpay_action_' . $status, $submission, $vendorTransaction, $data); if ($refundAmount = ArrayHelper::get($vendorTransaction, 'amountRefunded.value')) { $refundAmount = intval($refundAmount * 100); // in cents do_action_deprecated( 'fluentform_ipn_razorpay_action_refunded', [ $refundAmount, $submission, $vendorTransaction, $data ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/ipn_razorpay_action_refunded', 'Use fluentform/ipn_razorpay_action_refunded instead of fluentform_ipn_razorpay_action_refunded.' ); do_action('fluentform/ipn_razorpay_action_refunded', $refundAmount, $submission, $vendorTransaction, $data); } } public function makeApiCall($path, $args, $formId, $method = 'GET') { $keys = PaystackSettings::getApiKeys($formId); $headers = [ 'Authorization' => 'Bearer ' . $keys['api_secret'], 'Content-type' => 'application/json' ]; if ($method == 'POST') { $response = wp_remote_post('https://api.paystack.co/' . $path, [ 'headers' => $headers, 'body' => json_encode($args) ]); } else { $response = wp_remote_get('https://api.paystack.co/' . $path, [ 'headers' => $headers, 'body' => $args ]); } if (is_wp_error($response)) { return $response; } $body = wp_remote_retrieve_body($response); $responseData = json_decode($body, true); if(!$responseData) { return new \WP_Error(423, 'Unknown Paystack API request error', $responseData); } if (!empty($responseData['error'])) { $message = ArrayHelper::get($responseData, 'error.description'); if (!$message) { $message = __('Unknown Paystack API request error', 'fluentformpro'); } return new \WP_Error(423, $message, $responseData); } else if (empty($responseData['status']) && !$responseData['status']) { // this is an error $message = __('Paystack API Error', 'fluentformpro'); if (!empty($responseData['message'])) { $message = $responseData['message']; } return new \WP_Error(423, $message, $responseData); } return $responseData; } }PK!8src/Payments/PaymentMethods/Paystack/PaystackHandler.phpnu[key, array($this, 'validateSettings'), 10, 2); if(!$this->isEnabled()) { return; } add_filter('fluentform/transaction_data_' . $this->key, array($this, 'modifyTransaction'), 10, 1); add_filter('fluentform/available_payment_methods', [$this, 'pushPaymentMethodToForm']); (new PaystackProcessor())->init(); } public function pushPaymentMethodToForm($methods) { $methods[$this->key] = [ 'title' => __('PayStack', 'fluentformpro'), 'enabled' => 'yes', 'method_value' => $this->key, 'settings' => [ 'option_label' => [ 'type' => 'text', 'template' => 'inputText', 'value' => 'Pay with PayStack', 'label' => __('Method Label', 'fluentformpro') ] ] ]; return $methods; } public function validateSettings($errors, $settings) { if (ArrayHelper::get($settings, 'is_active') == 'no') { return []; } $mode = ArrayHelper::get($settings, 'payment_mode'); if (!$mode) { $errors['payment_mode'] = __('Please select Payment Mode', 'fluentformpro'); } if ($mode == 'test') { if (!ArrayHelper::get($settings, 'test_api_key')) { $errors['test_api_key'] = __('Please provide Test API Key', 'fluentformpro'); } if (!ArrayHelper::get($settings, 'test_api_secret')) { $errors['test_api_secret'] = __('Please provide Test API Secret', 'fluentformpro'); } } elseif ($mode == 'live') { if (!ArrayHelper::get($settings, 'live_api_key')) { $errors['live_api_key'] = __('Please provide Live API Key', 'fluentformpro'); } if (!ArrayHelper::get($settings, 'live_api_secret')) { $errors['live_api_secret'] = __('Please provide Live API Secret', 'fluentformpro'); } } return $errors; } public function modifyTransaction($transaction) { if ($transaction->charge_id) { $transaction->action_url = 'https://dashboard.paystack.com/#/transactions/'.$transaction->charge_id; } return $transaction; } public function isEnabled() { $settings = $this->getGlobalSettings(); return $settings['is_active'] == 'yes'; } public function getGlobalFields() { return [ 'label' => 'Paystack', 'fields' => [ [ 'settings_key' => 'is_active', 'type' => 'yes-no-checkbox', 'label' => __('Status', 'fluentformpro'), 'checkbox_label' => __('Enable PayStack Payment Method', 'fluentformpro') ], [ 'settings_key' => 'payment_mode', 'type' => 'input-radio', 'label' => __('Payment Mode', 'fluentformpro'), 'options' => [ 'test' => __('Test Mode', 'fluentformpro'), 'live' => __('Live Mode', 'fluentformpro') ], 'info_help' => __('Select the payment mode. for testing purposes you should select Test Mode otherwise select Live mode.', 'fluentformpro'), 'check_status' => 'yes' ], [ 'settings_key' => 'test_payment_tips', 'type' => 'html', 'html' => __('

    Your Test API Credentials

    If you use the test mode

    ', 'fluentformpro') ], [ 'settings_key' => 'test_api_key', 'type' => 'input-text', 'data_type' => 'password', 'placeholder' => __('Test API Key', 'fluentformpro'), 'label' => __('Test API Key', 'fluentformpro'), 'inline_help' => __('Provide your test api key for your test payments', 'fluentformpro'), 'check_status' => 'yes' ], [ 'settings_key' => 'test_api_secret', 'type' => 'input-text', 'data_type' => 'password', 'placeholder' => __('Test API Secret', 'fluentformpro'), 'label' => __('Test API Secret', 'fluentformpro'), 'inline_help' => __('Provide your test api secret for your test payments', 'fluentformpro'), 'check_status' => 'yes' ], [ 'settings_key' => 'live_payment_tips', 'type' => 'html', 'html' => __('

    Your Live API Credentials

    If you use the live mode

    ', 'fluentformpro') ], [ 'settings_key' => 'live_api_key', 'type' => 'input-text', 'data_type' => 'password', 'label' => __('Live API Key', 'fluentformpro'), 'placeholder' => __('Live API Key', 'fluentformpro'), 'inline_help' => __('Provide your live api key for your live payments', 'fluentformpro'), 'check_status' => 'yes' ], [ 'settings_key' => 'live_api_secret', 'type' => 'input-text', 'data_type' => 'password', 'placeholder' => __('Live API Secret', 'fluentformpro'), 'label' => __('Live API Secret', 'fluentformpro'), 'inline_help' => __('Provide your live api secret for your live payments', 'fluentformpro'), 'check_status' => 'yes' ], [ 'type' => 'html', 'html' => __('

    Please read the documentation to learn how to setup PayStack Payment Gateway.

    ', 'fluentformpro') ], // [ // 'settings_key' => 'payment_channels', // 'type' => 'input-checkboxes', // 'label' => 'Payment Channels', // 'options' => [ // 'card' => 'Card', // 'bank' => 'Bank', // 'ussd' => 'USSD', // 'qr' => 'QR', // 'mobile_money' => 'Mobile Money', // 'bank_transfer' => 'Bank Transfer', // ], // 'info_help' => '', // 'check_status' => 'yes' // ] ] ]; } public function getGlobalSettings() { return PaystackSettings::getSettings(); } } PK!$YGG:src/Payments/PaymentMethods/RazorPay/RazorPayProcessor.phpnu[method, array($this, 'handlePaymentAction'), 10, 6); add_action('fluentform/payment_frameless_' . $this->method, array($this, 'handleSessionRedirectBack')); add_action('fluentform/ipn_razorpay_action_paid', array($this, 'handlePaid'), 10, 2); add_action('fluentform/ipn_razorpay_action_refunded', array($this, 'handleRefund'), 10, 3); add_filter('fluentform/validate_payment_items_' . $this->method, [$this, 'validateSubmittedItems'], 10, 4); add_action('fluentform/rendering_payment_method_' . $this->method, array($this, 'addCheckoutJs'), 10, 3); add_action('wp_ajax_fluentform_razorpay_confirm_payment', array($this, 'confirmModalPayment')); add_action('wp_ajax_nopriv_fluentform_razorpay_confirm_payment', array($this, 'confirmModalPayment')); } public function handlePaymentAction($submissionId, $submissionData, $form, $methodSettings, $hasSubscriptions, $totalPayable) { $this->setSubmissionId($submissionId); $this->form = $form; $submission = $this->getSubmission(); if ($hasSubscriptions) { do_action('fluentform/log_data', [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Payment', 'status' => 'info', 'title' => __('Skip Subscription Item', 'fluentformpro'), 'description' => __('Razorpay does not support subscriptions right now!', 'fluentformpro') ]); } $uniqueHash = md5($submission->id . '-' . $form->id . '-' . time() . '-' . mt_rand(100, 999)); $transactionId = $this->insertTransaction([ 'transaction_type' => 'onetime', 'transaction_hash' => $uniqueHash, 'payment_total' => $this->getAmountTotal(), 'status' => 'pending', 'currency' => PaymentHelper::getFormCurrency($form->id), 'payment_mode' => $this->getPaymentMode() ]); $transaction = $this->getTransaction($transactionId); $this->maybeShowModal($transaction, $submission, $form, $methodSettings); $this->handleRedirect($transaction, $submission, $form, $methodSettings); } public function handleRedirect($transaction, $submission, $form, $methodSettings) { $globalSettings = RazorPaySettings::getSettings(); $successUrl = add_query_arg(array( 'fluentform_payment' => $submission->id, 'payment_method' => $this->method, 'transaction_hash' => $transaction->transaction_hash, 'type' => 'success' ), site_url('/')); $paymentArgs = array( 'amount' => intval($transaction->payment_total), 'currency' => strtoupper($transaction->currency), 'description' => $form->title, 'reference_id' => $transaction->transaction_hash, 'customer' => [ 'email' => PaymentHelper::getCustomerEmail($submission, $form), 'name' => PaymentHelper::getCustomerName($submission, $form), 'contact' => PaymentHelper::getCustomerPhoneNumber($submission, $form), ], "options" => [ "checkout" => [ 'name' => PaymentHelper::getCustomerName($submission, $form), ] ], 'callback_url' => $successUrl, 'notes' => [ 'form_id' => $form->id, 'submission_id' => $submission->id ], 'callback_method' => 'get', 'notify' => [ 'email' => in_array('email', $globalSettings['notifications']), 'sms' => in_array('sms', $globalSettings['notifications']), ] ); $paymentArgs = apply_filters_deprecated( 'fluentform_razorpay_payment_args', [ $paymentArgs, $submission, $transaction, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/razorpay_payment_args', 'Use fluentform/razorpay_payment_args instead of fluentform_razorpay_payment_args.' ); $paymentArgs = apply_filters('fluentform/razorpay_payment_args', $paymentArgs, $submission, $transaction, $form); $paymentIntent = (new API())->makeApiCall('payment_links', $paymentArgs, $form->id, 'POST'); if (is_wp_error($paymentIntent)) { $logData = [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Payment', 'status' => 'error', 'title' => __('Mollie Payment Redirect Error', 'fluentformpro'), 'description' => $paymentIntent->get_error_message() ]; do_action('fluentform/log_data', $logData); wp_send_json_success([ 'message' => $paymentIntent->get_error_message() ], 423); } Helper::setSubmissionMeta($submission->id, '_razorpay_payment_id', $paymentIntent['id']); $logData = [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Payment', 'status' => 'info', 'title' => __('Redirect to RazorPay', 'fluentformpro'), 'description' => __('User redirect to RazorPay for completing the payment', 'fluentformpro') ]; do_action('fluentform/log_data', $logData); wp_send_json_success([ 'nextAction' => 'payment', 'actionName' => 'normalRedirect', 'redirect_url' => $paymentIntent['short_url'], 'message' => __('You are redirecting to razorpay.com to complete the purchase. Please wait while you are redirecting....', 'fluentformpro'), 'result' => [ 'insert_id' => $submission->id ] ], 200); } protected function getPaymentMode($formId = false) { $isLive = RazorPaySettings::isLive($formId); if ($isLive) { return 'live'; } return 'test'; } public function handleSessionRedirectBack($data) { $submissionId = intval($data['fluentform_payment']); $this->setSubmissionId($submissionId); $submission = $this->getSubmission(); $transactionHash = sanitize_text_field($data['transaction_hash']); $transaction = $this->getTransaction($transactionHash, 'transaction_hash'); if (!$transaction || !$submission || $transaction->payment_method != $this->method) { return; } $payId = ArrayHelper::get($data, 'razorpay_payment_id'); $payment = (new API())->makeApiCall('payments/' . $payId, [], $submission->form_id); $isSuccess = false; if (is_wp_error($payment)) { $returnData = [ 'insert_id' => $submission->id, 'title' => __('Failed to retrieve payment data', 'fluentformpro'), 'result' => false, 'error' => $payment->get_error_message() ]; } else { $isSuccess = $payment['status'] == 'captured'; if ($isSuccess) { $returnData = $this->handlePaid($submission, $transaction, $payment); } else { $returnData = [ 'insert_id' => $submission->id, 'title' => __('Failed to retrieve payment data', 'fluentformpro'), 'result' => false, 'error' => __('Looks like you have cancelled the payment. Please try again!', 'fluentformpro') ]; } } $returnData['type'] = ($isSuccess) ? 'success' : 'failed'; if (!isset($returnData['is_new'])) { $returnData['is_new'] = false; } $this->showPaymentView($returnData); } public function handlePaid($submission, $transaction, $vendorTransaction) { $this->setSubmissionId($submission->id); // Check if actions are fired if ($this->getMetaData('is_form_action_fired') == 'yes') { return $this->completePaymentSubmission(false); } $status = 'paid'; // Let's make the payment as paid $updateData = [ 'payment_note' => maybe_serialize($vendorTransaction), 'charge_id' => sanitize_text_field($vendorTransaction['id']), 'payer_email' => $vendorTransaction['email'], 'payment_total' => intval($vendorTransaction['amount']) ]; $this->updateTransaction($transaction->id, $updateData); $this->changeSubmissionPaymentStatus($status); $this->changeTransactionStatus($transaction->id, $status); $this->recalculatePaidTotal(); $returnData = $this->getReturnData(); $this->setMetaData('is_form_action_fired', 'yes'); return $returnData; } public function handleRefund($refundAmount, $submission, $vendorTransaction) { $this->setSubmissionId($submission->id); $transaction = $this->getLastTransaction($submission->id); $this->updateRefund($refundAmount, $transaction, $submission, $this->method); } public function validateSubmittedItems($errors, $paymentItems, $subscriptionItems, $form) { $singleItemTotal = 0; foreach ($paymentItems as $paymentItem) { if ($paymentItem['line_total']) { $singleItemTotal += $paymentItem['line_total']; } } if (count($subscriptionItems) && !$singleItemTotal) { $errors[] = __('RazorPay Error: RazorPay does not support subscriptions right now!', 'fluentformpro'); } return $errors; } public function addCheckoutJs($methodElement, $element, $form) { $settings = RazorPaySettings::getSettings(); if ($settings['checkout_type'] != 'modal') { return; } wp_enqueue_script('razorpay', 'https://checkout.razorpay.com/v1/checkout.js', [], FLUENTFORMPRO_VERSION); wp_enqueue_script('ff_razorpay_handler', FLUENTFORMPRO_DIR_URL . 'public/js/razorpay_handler.js', ['jquery'], FLUENTFORMPRO_VERSION); } public function maybeShowModal($transaction, $submission, $form, $methodSettings) { $settings = RazorPaySettings::getSettings(); if($settings['checkout_type'] != 'modal') { return; } // Create an order First $orderArgs = [ 'amount' => intval($transaction->payment_total), 'currency' => strtoupper($transaction->currency), 'receipt' => $transaction->transaction_hash, 'notes' => [ 'form_id' => $form->id, 'submission_id' => $submission->id ] ]; $order = (new API())->makeApiCall('orders', $orderArgs, $form->id, 'POST'); if (is_wp_error($order)) { $message = $order->get_error_message(); $logData = [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Payment', 'status' => 'error', 'title' => __('RazorPay Payment Error', 'fluentformpro'), 'description' => $order->get_error_message() ]; do_action('fluentform/log_data', $logData); wp_send_json([ 'errors' => __('RazorPay Error: ', 'fluentformpro') . $message, 'append_data' => [ '__entry_intermediate_hash' => Helper::getSubmissionMeta($submission->id, '__entry_intermediate_hash') ] ], 423); } $this->updateTransaction($transaction->id, [ 'charge_id' => $order['id'] ]); $keys = RazorPaySettings::getApiKeys($form->id); $paymentSettings = PaymentHelper::getPaymentSettings(); $modalData = [ 'amount' => intval($transaction->payment_total), 'currency' => strtoupper($transaction->currency), 'description' => $form->title, 'reference_id' => $transaction->transaction_hash, 'order_id' => $order['id'], 'name' => $paymentSettings['business_name'], 'key' => $keys['api_key'], 'prefill' => [ 'email' => PaymentHelper::getCustomerEmail($submission, $form), 'name' => PaymentHelper::getCustomerName($submission, $form), 'contact' => PaymentHelper::getCustomerPhoneNumber($submission, $form), ], ]; if ($theme_color = ArrayHelper::get($settings, 'theme_color')) { $modalData['theme'] = [ "color" => $theme_color, ]; } $logData = [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Payment', 'status' => 'info', 'title' => __('Razorpay Modal is initiated', 'fluentformpro'), 'description' => __('RazorPay Modal is initiated to complete the payment', 'fluentformpro') ]; do_action('fluentform/log_data', $logData); # Tell the client to handle the action wp_send_json_success([ 'nextAction' => 'razorpay', 'actionName' => 'initRazorPayModal', 'submission_id' => $submission->id, 'modal_data' => $modalData, 'transaction_hash' => $transaction->transaction_hash, 'message' => __('Payment Modal is opening, Please complete the payment', 'fluentformpro'), 'confirming_text' => __('Confirming Payment, Please wait...', 'fluentformpro'), 'result' => [ 'insert_id' => $submission->id ], 'append_data' => [ '__entry_intermediate_hash' => Helper::getSubmissionMeta($transaction->submission_id, '__entry_intermediate_hash') ] ], 200); } public function confirmModalPayment() { $data = $_REQUEST; $transactionHash = sanitize_text_field(ArrayHelper::get($data, 'transaction_hash')); $transaction = $this->getTransaction($transactionHash, 'transaction_hash'); if(!$transaction || $transaction->status != 'pending') { wp_send_json([ 'errors' => __('Payment Error: Invalid Request', 'fluentformpro'), ], 423); } $paymentId = sanitize_text_field(ArrayHelper::get($data, 'razorpay_payment_id')); $vendorPayment = (new API())->makeApiCall('payments/' . $paymentId, [], $transaction->form_id); if (is_wp_error($vendorPayment)) { $logData = [ 'parent_source_id' => $transaction->form_id, 'source_type' => 'submission_item', 'source_id' => $transaction->submission_id, 'component' => 'Payment', 'status' => 'failed', 'title' => __('RazorPay Payment is failed to verify', 'fluentformpro'), 'description' => $vendorPayment->get_error_message() ]; do_action('fluentform/log_data', $logData); wp_send_json([ 'errors' => __('Payment Error: ', 'fluentformpro') . $vendorPayment->get_error_message(), 'append_data' => [ '__entry_intermediate_hash' => Helper::getSubmissionMeta($transaction->submission_id, '__entry_intermediate_hash') ] ], 423); } if ($vendorPayment['status'] == 'paid' || $vendorPayment['status'] == 'captured') { $logData = [ 'parent_source_id' => $transaction->form_id, 'source_type' => 'submission_item', 'source_id' => $transaction->submission_id, 'component' => 'Payment', 'status' => 'success', 'title' => __('Payment Success', 'fluentformpro'), 'description' => __('Razorpay payment has been marked as paid', 'fluentformpro') ]; do_action('fluentform/log_data', $logData); $this->setSubmissionId($transaction->submission_id); $submission = $this->getSubmission(); $returnData = $this->handlePaid($submission, $transaction, $vendorPayment); $returnData['payment'] = $vendorPayment; wp_send_json_success($returnData, 200); } wp_send_json([ 'errors' => __('Payment could not be verified. Please contact site admin', 'fluentformpro'), 'append_data' => [ '__entry_intermediate_hash' => Helper::getSubmissionMeta($transaction->submission_id, '__entry_intermediate_hash') ] ], 423); } } PK!Ϟ!!8src/Payments/PaymentMethods/RazorPay/RazorPayHandler.phpnu[key, array($this, 'validateSettings'), 10, 2); if(!$this->isEnabled()) { return; } add_filter('fluentform/transaction_data_' . $this->key, array($this, 'modifyTransaction'), 10, 1); add_filter('fluentform/available_payment_methods', [$this, 'pushPaymentMethodToForm']); (new RazorPayProcessor())->init(); } public function pushPaymentMethodToForm($methods) { $methods[$this->key] = [ 'title' => __('RazorPay', 'fluentformpro'), 'enabled' => 'yes', 'method_value' => $this->key, 'settings' => [ 'option_label' => [ 'type' => 'text', 'template' => 'inputText', 'value' => 'Pay with RazorPay', 'label' => __('Method Label', 'fluentformpro') ] ] ]; return $methods; } public function validateSettings($errors, $settings) { if(ArrayHelper::get($settings, 'is_active') == 'no') { return []; } $mode = ArrayHelper::get($settings, 'payment_mode'); if (!$mode) { $errors['payment_mode'] = __('Please select Payment Mode', 'fluentformpro'); } if ($mode == 'test') { if (!ArrayHelper::get($settings, 'test_api_key')) { $errors['test_api_key'] = __('Please provide Test API Key', 'fluentformpro'); } if (!ArrayHelper::get($settings, 'test_api_secret')) { $errors['test_api_secret'] = __('Please provide Test API Secret', 'fluentformpro'); } } elseif ($mode == 'live') { if (!ArrayHelper::get($settings, 'live_api_key')) { $errors['live_api_key'] = __('Please provide Live API Key', 'fluentformpro'); } if (!ArrayHelper::get($settings, 'live_api_secret')) { $errors['live_api_secret'] = __('Please provide Live API Secret', 'fluentformpro'); } } return $errors; } public function modifyTransaction($transaction) { if ($transaction->charge_id) { $transaction->action_url = 'https://dashboard.razorpay.com/app/payments/'.$transaction->charge_id; } return $transaction; } public function isEnabled() { $settings = $this->getGlobalSettings(); return $settings['is_active'] == 'yes'; } public function getGlobalFields() { return [ 'label' => 'RazorPay', 'fields' => [ [ 'settings_key' => 'is_active', 'type' => 'yes-no-checkbox', 'label' => __('Status', 'fluentformpro'), 'checkbox_label' => __('Enable RazorPay Payment Method', 'fluentformpro'), ], [ 'settings_key' => 'payment_mode', 'type' => 'input-radio', 'label' => __('Payment Mode', 'fluentformpro'), 'options' => [ 'test' => __('Test Mode', 'fluentformpro'), 'live' => __('Live Mode', 'fluentformpro') ], 'info_help' => __('Select the payment mode. for testing purposes you should select Test Mode otherwise select Live mode.', 'fluentformpro'), 'check_status' => 'yes' ], [ 'settings_key' => 'test_payment_tips', 'type' => 'html', 'html' => __('

    Your Test API Credentials

    If you use the test mode

    ', 'fluentformpro') ], [ 'settings_key' => 'test_api_key', 'type' => 'input-text', 'data_type' => 'password', 'placeholder' => __('Test API Key', 'fluentformpro'), 'label' => __('Test API Key', 'fluentformpro'), 'inline_help' => __('Provide your test api key for your test payments', 'fluentformpro'), 'check_status' => 'yes' ], [ 'settings_key' => 'test_api_secret', 'type' => 'input-text', 'data_type' => 'password', 'placeholder' => __('Test API Secret', 'fluentformpro'), 'label' => __('Test API Secret', 'fluentformpro'), 'inline_help' => __('Provide your test api secret for your test payments', 'fluentformpro'), 'check_status' => 'yes' ], [ 'settings_key' => 'live_payment_tips', 'type' => 'html', 'html' => __('

    Your Live API Credentials

    If you use the live mode

    ', 'fluentformpro') ], [ 'settings_key' => 'live_api_key', 'type' => 'input-text', 'data_type' => 'password', 'label' => __('Live API Key', 'fluentformpro'), 'placeholder' => __('Live API Key', 'fluentformpro'), 'inline_help' => __('Provide your live api key for your live payments', 'fluentformpro'), 'check_status' => 'yes' ], [ 'settings_key' => 'live_api_secret', 'type' => 'input-text', 'data_type' => 'password', 'placeholder' => __('Live API Secret', 'fluentformpro'), 'label' => __('Live API Secret', 'fluentformpro'), 'inline_help' => __('Provide your live api secret for your live payments', 'fluentformpro'), 'check_status' => 'yes' ], [ 'settings_key' => 'checkout_type', 'type' => 'input-radio', 'label' => __('Checkout Style Type', 'fluentformpro'), 'options' => [ 'modal' => __('Modal Checkout Style', 'fluentformpro'), 'hosted' => __('Hosted to razorpay.com', 'fluentformpro') ], 'info_help' => __('Select which type of checkout style you want.', 'fluentformpro'), 'check_status' => 'yes' ], [ 'settings_key' => 'theme_color', 'type' => 'input-color', 'label' => __('Modal Theme Color', 'fluentformpro'), 'info_help' => __('Choose Razorpay checkout brand theme color. Leave empty for Razorpay default theme.', 'fluentformpro'), ], [ 'settings_key' => 'notifications_tips', 'type' => 'html', 'html' => __('

    RazorPay Notifications

    Select if you want to enable SMS and Email Notification from razorpay

    ', 'fluentformpro') ], [ 'settings_key' => 'notifications', 'type' => 'input-checkboxes', 'label' => __('RazorPay Notifications', 'fluentformpro'), 'options' => [ 'sms' => __('SMS', 'fluentformpro'), 'email' => __('Email', 'fluentformpro') ], 'info_help' => '', 'check_status' => 'yes' ], [ 'type' => 'html', 'html' => __('

    Please read the documentation to learn how to setup RazorPay Payment Gateway.

    ', 'fluentformpro') ] ] ]; } public function getGlobalSettings() { return RazorPaySettings::getSettings(); } } PK!/P#9src/Payments/PaymentMethods/RazorPay/RazorPaySettings.phpnu[ 'no', 'payment_mode' => 'test', 'checkout_type' => 'modal', 'test_api_key' => '', 'test_api_secret' => '', 'live_api_key' => '', 'live_api_secret' => '', 'notifications' => [] ]; return wp_parse_args(get_option('fluentform_payment_settings_razorpay', []), $defaults); } public static function isLive($formId = false) { $settings = self::getSettings(); return $settings['payment_mode'] == 'live'; } public static function getApiKeys($formId = false) { $isLive = self::isLive($formId); $settings = self::getSettings(); if($isLive) { return [ 'api_key' => $settings['live_api_key'], 'api_secret' => $settings['live_api_secret'], ]; } return [ 'api_key' => $settings['test_api_key'], 'api_secret' => $settings['test_api_secret'], ]; } }PK! i,src/Payments/PaymentMethods/RazorPay/API.phpnu[ 0) { // Append the data $encoded_data .= $arg_separator . $post_data; } else { // Check if POST is empty if (empty($_POST)) { // Nothing to do return; } else { // Loop through each POST foreach ($_POST as $key => $value) { // Encode the value and append the data $encoded_data .= $arg_separator . "$key=" . urlencode($value); } } } // Convert collected post data to an array parse_str($encoded_data, $encoded_data_array); foreach ($encoded_data_array as $key => $value) { if (false !== strpos($key, 'amp;')) { $new_key = str_replace('&', '&', $key); $new_key = str_replace('amp;', '&', $new_key); unset($encoded_data_array[$key]); $encoded_data_array[$new_key] = $value; } } $defaults = $_REQUEST; $encoded_data_array = wp_parse_args($encoded_data_array, $defaults); $this->handleIpn($encoded_data_array); exit(200); } protected function handleIpn($data) { $submissionId = intval(ArrayHelper::get($data, 'submission_id')); if (!$submissionId || empty($data['id'])) { return; } $submission = wpFluent()->table('fluentform_submissions')->where('id', $submissionId)->first(); if (!$submission) { return; } $vendorTransaction = $this->makeApiCall('payments/'.$data['id'], [], $submission->form_id, 'GET'); if(is_wp_error($vendorTransaction)) { $logData = [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Payment', 'status' => 'error', 'title' => __('RazorPay Payment Webhook Error', 'fluentformpro'), 'description' => $vendorTransaction->get_error_message() ]; do_action('fluentform/log_data', $logData); } $status = $vendorTransaction['status']; if($status == 'captured') { $status = 'paid'; } do_action_deprecated( 'fluentform_ipn_razorpay_action_' . $status, [ $submission, $vendorTransaction, $data ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/ipn_razorpay_action_' . $status, 'Use fluentform/ipn_razorpay_action_' . $status . ' instead of fluentform_ipn_razorpay_action_' . $status ); do_action('fluentform/ipn_razorpay_action_' . $status, $submission, $vendorTransaction, $data); if($refundAmount = ArrayHelper::get($vendorTransaction, 'amountRefunded.value')) { $refundAmount = intval($refundAmount * 100); // in cents do_action_deprecated( 'fluentform_ipn_razorpay_action_refunded', [ $refundAmount, $submission, $vendorTransaction, $data ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/ipn_razorpay_action_refunded', 'Use fluentform/ipn_razorpay_action_refunded instead of fluentform_ipn_razorpay_action_refunded.' ); do_action('fluentform/ipn_razorpay_action_refunded', $refundAmount, $submission, $vendorTransaction, $data); } } public function makeApiCall($path, $args, $formId, $method = 'GET') { $keys = RazorPaySettings::getApiKeys($formId); $headers = [ 'Authorization' => 'Basic '.base64_encode($keys['api_key'].':'.$keys['api_secret']), 'Content-type' => 'application/json' ]; if($method == 'POST') { $response = wp_remote_post('https://api.razorpay.com/v1/'.$path, [ 'headers' => $headers, 'body' => json_encode($args) ]); } else { $response = wp_remote_get('https://api.razorpay.com/v1/'.$path, [ 'headers' => $headers, 'body' => $args ]); } if(is_wp_error($response)) { return $response; } $body = wp_remote_retrieve_body($response); $responseData = json_decode($body, true); if(!empty($responseData['error'])) { $message = ArrayHelper::get($responseData, 'error.description'); if(!$message) { $message = __('Unknown RazorPay API request error', 'fluentformpro'); } return new \WP_Error(423, $message, $responseData); } return $responseData; } }PK!wȅ334src/Payments/PaymentMethods/Square/SquareHandler.phpnu[key, array($this, 'validateSettings'), 10, 2); if (!$this->isEnabled()) { return; } add_filter('fluentform/transaction_data_' . $this->key, array($this, 'modifyTransaction'), 10, 1); add_filter('fluentform/available_payment_methods', [$this, 'pushPaymentMethodToForm']); (new SquareProcessor())->init(); } public function pushPaymentMethodToForm($methods) { $methods[$this->key] = [ 'title' => __('Square', 'fluentformpro'), 'enabled' => 'yes', 'method_value' => $this->key, 'settings' => [ 'option_label' => [ 'type' => 'text', 'template' => 'inputText', 'value' => 'Pay with Square', 'label' => __('Method Label', 'fluentformpro') ] ] ]; return $methods; } public function validateSettings($errors, $settings) { if(ArrayHelper::get($settings, 'is_active') == 'no') { return []; } $mode = ArrayHelper::get($settings, 'payment_mode'); if (!$mode) { $errors['payment_mode'] = __('Please select Payment Mode', 'fluentformpro'); } if ($mode == 'test') { if (!ArrayHelper::get($settings, 'test_location_id')) { $errors['test_location_id'] = __('Please provide Test Location ID', 'fluentformpro'); } if (!ArrayHelper::get($settings, 'test_access_key')) { $errors['test_access_key'] = __('Please provide Test Access Secret', 'fluentformpro'); } } elseif ($mode == 'live') { if (!ArrayHelper::get($settings, 'live_location_id')) { $errors['live_location_id'] = __('Please Live Location ID', 'fluentformpro'); } if (!ArrayHelper::get($settings, 'live_access_key')) { $errors['live_access_key'] = __('Please provide Live Access Key', 'fluentformpro'); } } return $errors; } public function modifyTransaction($transaction) { $path = $transaction->payment_mode === 'test' ? 'https://squareupsandbox.com/' : 'https://squareup.com/'; if ($transaction->charge_id) { $transaction->action_url = $path . 'dashboard/sales/transactions/' . $transaction->charge_id; } return $transaction; } public function isEnabled() { $settings = $this->getGlobalSettings(); return $settings['is_active'] == 'yes'; } public function getGlobalFields() { return [ 'label' => 'Square', 'fields' => [ [ 'settings_key' => 'is_active', 'type' => 'yes-no-checkbox', 'label' => __('Status', 'fluentformpro'), 'checkbox_label' => __('Enable Square Payment Method', 'fluentformpro'), ], [ 'settings_key' => 'payment_mode', 'type' => 'input-radio', 'label' => __('Payment Mode', 'fluentformpro'), 'options' => [ 'test' => __('Test Mode', 'fluentformpro'), 'live' => __('Live Mode', 'fluentformpro') ], 'info_help' => __('Select the payment mode. for testing purposes you should select Test Mode otherwise select Live mode.', 'fluentformpro'), 'check_status' => 'yes' ], [ 'settings_key' => 'test_payment_tips', 'type' => 'html', 'html' => __('

    Your Test API Credentials

    If you use the test mode

    ', 'fluentformpro') ], [ 'settings_key' => 'test_access_key', 'type' => 'input-text', 'data_type' => 'password', 'placeholder' => __('Test Access Key', 'fluentformpro'), 'label' => __('Test Access Key', 'fluentformpro'), 'inline_help' => __('Provide your test api secret for your test payments', 'fluentformpro'), 'check_status' => 'yes' ], [ 'settings_key' => 'test_location_id', 'type' => 'input-text', 'data_type' => 'password', 'placeholder' => __('Test Location ID', 'fluentformpro'), 'label' => __('Test Location ID', 'fluentformpro'), 'inline_help' => __('Provide your test location id for your test payments', 'fluentformpro'), 'check_status' => 'yes' ], [ 'settings_key' => 'live_payment_tips', 'type' => 'html', 'html' => __('

    Your Live API Credentials

    If you use the live mode

    ', 'fluentformpro') ], [ 'settings_key' => 'live_access_key', 'type' => 'input-text', 'data_type' => 'password', 'placeholder' => __('Live Access Key', 'fluentformpro'), 'label' => __('Live Access Key', 'fluentformpro'), 'inline_help' => __('Provide your live live access key for your live payments', 'fluentformpro'), 'check_status' => 'yes' ], [ 'settings_key' => 'live_location_id', 'type' => 'input-text', 'data_type' => 'password', 'label' => __('Live Location ID', 'fluentformpro'), 'placeholder' => __('Live Location ID', 'fluentformpro'), 'inline_help' => __('Provide your live api key for your live payments', 'fluentformpro'), 'check_status' => 'yes' ], [ 'type' => 'html', 'html' => __('

    Please read the documentation to learn how to setup Square Payment Gateway.

    ', 'fluentformpro') ] ] ]; } public function getGlobalSettings() { return SquareSettings::getSettings(); } } PK!Fq / /6src/Payments/PaymentMethods/Square/SquareProcessor.phpnu[method, array($this, 'handlePaymentAction'), 10, 6); add_action('fluentform/payment_frameless_' . $this->method, array($this, 'handleSessionRedirectBack')); add_filter('fluentform/validate_payment_items_' . $this->method, [$this, 'validateSubmittedItems'], 10, 4); } public function handlePaymentAction($submissionId, $submissionData, $form, $methodSettings, $hasSubscriptions, $totalPayable) { $this->setSubmissionId($submissionId); $this->form = $form; $submission = $this->getSubmission(); if ($hasSubscriptions) { do_action('fluentform/log_data', [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Payment', 'status' => 'info', 'title' => __('Skip Subscription Item', 'fluentformpro'), 'description' => __('Square does not support subscriptions right now!', 'fluentformpro') ]); } $uniqueHash = md5($submission->id . '-' . $form->id . '-' . time() . '-' . mt_rand(100, 999)); $transactionId = $this->insertTransaction([ 'transaction_type' => 'onetime', 'transaction_hash' => $uniqueHash, 'payment_total' => $this->getAmountTotal(), 'status' => 'pending', 'currency' => PaymentHelper::getFormCurrency($form->id), 'payment_mode' => $this->getPaymentMode() ]); $transaction = $this->getTransaction($transactionId); $this->handleRedirect($transaction, $submission, $form, $methodSettings); } protected function getPaymentMode() { $isLive = SquareSettings::isLive(); if ($isLive) { return 'live'; } return 'test'; } protected function handleRedirect($transaction, $submission, $form, $methodSettings) { $keys = SquareSettings::getApiKeys(); $ipnDomain = site_url('index.php'); if(defined('FLUENTFORM_PAY_IPN_DOMAIN') && FLUENTFORM_PAY_IPN_DOMAIN) { $ipnDomain = FLUENTFORM_PAY_IPN_DOMAIN; } $listenerUrl = add_query_arg(array( 'fluentform_payment_api_notify' => 1, 'payment_method' => $this->method, 'fluentform_payment' => $submission->id, 'transaction_hash' => $transaction->transaction_hash, ), $ipnDomain); $paymentArgs = [ "idempotency_key" => $transaction->transaction_hash, "order" => [ "order" => [ "location_id" => ArrayHelper::get($keys, "location_id"), "line_items" => [ [ "quantity" => '1', "item_type" => "ITEM", "metadata" => [ 'form_id' => 'Form Id ' . strval($form->id), 'submission_id' => 'Submission Id ' . strval($submission->id) ], "name" => $this->getProductNames(), "base_price_money" => [ "amount" => intval($transaction->payment_total), "currency" => $transaction->currency ] ] ], ] ], 'pre_populated_data' => [ 'buyer_email' => PaymentHelper::getCustomerEmail($submission, $form), 'buyer_phone_number' => PaymentHelper::getCustomerPhoneNumber($submission, $form), ], "redirect_url" => $listenerUrl ]; $paymentArgs = apply_filters('fluentform/square_payment_args', $paymentArgs, $submission, $transaction, $form); $paymentIntent = (new API())->makeApiCall('checkouts', $paymentArgs, $form->id, 'POST'); if (is_wp_error($paymentIntent)) { do_action('fluentform/log_data', [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Payment', 'status' => 'error', 'title' => __('Square Payment Redirect Error', 'fluentformpro'), 'description' => $paymentIntent->get_error_message() ]); $this->changeSubmissionPaymentStatus('failed'); $this->changeTransactionStatus($transaction->id, 'failed'); wp_send_json_error([ 'message' => $paymentIntent->get_error_message() ], 423); } Helper::setSubmissionMeta($submission->id, '_square_payment_id', ArrayHelper::get($paymentIntent,'checkout.id')); do_action('fluentform/log_data', [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Payment', 'status' => 'info', 'title' => __('Redirect to Square', 'fluentformpro'), 'description' => __('User redirect to Square for completing the payment', 'fluentformpro') ]); $checkoutPageUrl = ArrayHelper::get($paymentIntent,'checkout.checkout_page_url'); if (strpos($checkoutPageUrl, 'https:') === false) { if (SquareSettings::isLive()) { $checkoutHostingUrl = 'https://connect.squareup.com'; } else { $checkoutHostingUrl = 'https://connect.squareupsandbox.com'; } $checkoutPageUrl = $checkoutHostingUrl . $checkoutPageUrl; } wp_send_json_success([ 'nextAction' => 'payment', 'actionName' => 'normalRedirect', 'redirect_url' => $checkoutPageUrl, 'message' => __('You are redirecting to square to complete the purchase. Please wait while you are redirecting....', 'fluentformpro'), 'result' => [ 'insert_id' => $submission->id ] ], 200); } public function getProductNames() { $orderItems = $this->getOrderItems(); $itemsHtml = ''; foreach ($orderItems as $item) { $itemsHtml != "" && $itemsHtml .= ", "; $itemsHtml .= $item->item_name ; } return $itemsHtml; } public function handleSessionRedirectBack($data) { $submissionId = intval($data['fluentform_payment']); $this->setSubmissionId($submissionId); $submission = $this->getSubmission(); $paymentId = ArrayHelper::get($data, 'transactionId'); $transaction = $this->getLastTransaction($submissionId); $payment = (new API())->makeApiCall('orders/'.$paymentId, [], $submission->form_id); if (is_wp_error($payment)) { do_action('fluentform/log_data', [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Payment', 'status' => 'error', 'title' => __('Square Payment Error', 'fluentformpro'), 'description' => $payment->get_error_message() ]); $returnData = $this->handleFailed($submission, $transaction); $returnData['type'] = 'failed'; } else { $returnData = $this->handlePaid($submission, $transaction, $payment); $status = ArrayHelper::get($payment, 'order.state', ''); $returnData['type'] = $status == 'COMPLETED' ? 'success' : 'failed'; } if (!isset($returnData['is_new'])) { $returnData['is_new'] = false; } $redirectUrl = ArrayHelper::get($returnData, 'result.redirectUrl'); if ($redirectUrl) { wp_redirect($redirectUrl); } $this->showPaymentView($returnData); } private function handleFailed($submission, $transaction) { $this->setSubmissionId($submission->id); $this->changeSubmissionPaymentStatus('failed'); $this->changeTransactionStatus($transaction->id, 'failed'); if ($this->getMetaData('is_form_action_fired') == 'yes') { return $this->completePaymentSubmission(false); } $this->setMetaData('is_form_action_fired', 'yes'); return $this->getReturnData(); } private function handlePaid($submission, $transaction, $payment) { $this->setSubmissionId($submission->id); if ($this->getMetaData('is_form_action_fired') == 'yes') { return $this->completePaymentSubmission(false); } $status = 'paid'; // Let's make the payment as paid $updateData = [ 'payment_note' => maybe_serialize($payment), 'charge_id' => sanitize_text_field(ArrayHelper::get($payment, 'order.id')), ]; if ($last4 = ArrayHelper::get($payment, 'order.tenders.card_details.card.last_4')) { $updateData['card_last_4'] = $last4; } $this->updateTransaction($transaction->id, $updateData); $this->changeSubmissionPaymentStatus($status); $this->changeTransactionStatus($transaction->id, $status); $this->recalculatePaidTotal(); $returnData = $this->getReturnData(); $this->setMetaData('is_form_action_fired', 'yes'); if (intval($payment['order']['total_money']['amount']) != $transaction->payment_total || strtoupper($transaction->currency) != strtoupper($payment['order']['total_money']['currency'])) { do_action('fluentform/log_data', [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Payment', 'status' => 'error', 'title' => __('Transaction Amount Mismatch - Square', 'fluentformpro'), 'description' => __('Transaction Amount should be ' . PaymentHelper::formatMoney($transaction->payment_total, $transaction->currency) . ' but received ' . PaymentHelper::formatMoney(intval($payment['order']['total_money']['amount']), strtoupper($payment['order']['total_money']['currency'])), 'fluentformpro') ]); } return $returnData; } public function validateSubmittedItems($errors, $paymentItems, $subscriptionItems, $form) { $singleItemTotal = 0; foreach ($paymentItems as $paymentItem) { if ($paymentItem['line_total']) { $singleItemTotal += $paymentItem['line_total']; } } if (count($subscriptionItems) && !$singleItemTotal) { $errors[] = __('Square Error: Square does not support subscriptions right now!', 'fluentformpro'); } return $errors; } } PK! e5src/Payments/PaymentMethods/Square/SquareSettings.phpnu[ 'no', 'payment_mode' => 'test', 'test_access_key' => '', 'test_location_id' => '', 'live_access_key' => '', 'live_location_id' => '', 'notifications' => [] ]; return wp_parse_args(get_option('fluentform_payment_settings_square', []), $defaults); } public static function isLive() { $settings = self::getSettings(); return $settings['payment_mode'] == 'live'; } public static function getApiKeys() { $isLive = self::isLive(); $settings = self::getSettings(); if($isLive) { return [ 'access_key' => $settings['live_access_key'], 'location_id' => $settings['live_location_id'], 'api_url' => "https://connect.squareup.com/v2/locations/{$settings['live_location_id']}/" ]; } return [ 'access_key' => $settings['test_access_key'], 'location_id' => $settings['test_location_id'], 'api_url' => "https://connect.squareupsandbox.com/v2/locations/{$settings['test_location_id']}/" ]; } } PK!j鰤*src/Payments/PaymentMethods/Square/API.phpnu[ 0) { // Append the data $encoded_data .= $arg_separator . $post_data; } else { // Check if POST is empty if (empty($_POST)) { // Nothing to do return; } else { // Loop through each POST foreach ($_POST as $key => $value) { // Encode the value and append the data $encoded_data .= $arg_separator . "$key=" . urlencode($value); } } } // Convert collected post data to an array parse_str($encoded_data, $encoded_data_array); foreach ($encoded_data_array as $key => $value) { if (false !== strpos($key, 'amp;')) { $new_key = str_replace('&', '&', $key); $new_key = str_replace('amp;', '&', $new_key); unset($encoded_data_array[$key]); $encoded_data_array[$new_key] = $value; } } $defaults = $_REQUEST; $encoded_data_array = wp_parse_args($encoded_data_array, $defaults); $this->handleIpn($encoded_data_array); exit(200); } protected function handleIpn($data) { $submissionId = intval(ArrayHelper::get($data, 'submission_id')); if (!$submissionId || empty($data['id'])) { return; } $submission = wpFluent()->table('fluentform_submissions')->where('id', $submissionId)->first(); if (!$submission) { return; } $vendorTransaction = $this->makeApiCall('checkouts/'.$data['id'], [], $submission->form_id, 'GET'); if(is_wp_error($vendorTransaction)) { do_action('fluentform/log_data', [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Payment', 'status' => 'error', 'title' => __('Square Payment Webhook Error', 'fluentformpro'), 'description' => $vendorTransaction->get_error_message() ]); } $status = $vendorTransaction['status']; if ($status == 'captured') { $status = 'paid'; } do_action('fluentform_ipn_square_action_'.$status, $submission, $vendorTransaction, $data); if ($refundAmount = ArrayHelper::get($vendorTransaction, 'amountRefunded.value')) { $refundAmount = intval($refundAmount * 100); // in cents do_action('fluentform_ipn_square_action_refunded', $refundAmount, $submission, $vendorTransaction, $data); } } public function makeApiCall($path, $args, $formId, $method = 'GET') { $keys = SquareSettings::getApiKeys(); $headers = [ 'Authorization' => 'Bearer ' . $keys['access_key'], 'Accept' => 'application/json', 'Content-type' => 'application/json' ]; $baseUrl = ArrayHelper::get($keys, 'api_url'); if ($method == 'POST') { $response = wp_remote_post($baseUrl . $path, [ 'headers' => $headers, 'body' => json_encode($args) ]); } else { $response = wp_remote_get($baseUrl . $path, [ 'headers' => $headers, 'body' => $args ]); } if (is_wp_error($response)) { return $response; } $body = wp_remote_retrieve_body($response); $responseData = json_decode($body, true); if (!empty($responseData['errors'])) { $message = ArrayHelper::get($responseData, 'errors.0.detail', ''); if (!$message) { $message = __('Unknown Square API request error', 'fluentformpro'); } return new \WP_Error(423, $message, $responseData); } return $responseData; } } PK!(449src/Payments/PaymentMethods/Stripe/API/StripeListener.phpnu[id)) { return; } $eventId = $event->id; if ($eventId) { status_header(200); try { $formId = StripeSettings::guessFormIdFromEvent($event); $event = $this->retrive($eventId, $formId); if ($event && !is_wp_error($event)) { $eventType = $event->type; if ($eventType == 'charge.succeeded' || $eventType == 'charge.captured') { $this->handleChargeSucceeded($event); } else if ($eventType == 'invoice.payment_succeeded') { $this->maybeHandleSubscriptionPayment($event); } else if ($eventType == 'charge.refunded') { $this->handleChargeRefund($event); } else if ($eventType == 'customer.subscription.deleted') { $this->handleSubscriptionCancelled($event); } else if ($eventType == 'checkout.session.completed') { $this->handleCheckoutSessionCompleted($event); } else if($eventType == 'customer.subscription.updated') { // maybe we have to handle the } } } catch (\Exception $e) { return; // No event found for this account } } else { status_header(500); die('-1'); // Failed } die('1'); } // This is an onetime payment success private function handleChargeSucceeded($event) { $charge = $event->data->object; $meta = (array) $charge->metadata; $transactionId = ArrayHelper::get($meta, 'transaction_id'); if(!$transactionId) { $transaction = wpFluent()->table('fluentform_transactions') ->where('charge_id', $charge->payment_intent) ->first(); if(!$transaction) { return; } } else { $submissionId = ArrayHelper::get($meta, 'submission_id'); $transaction = wpFluent()->table('fluentform_transactions') ->where('submission_id', $submissionId) ->where('id', $transactionId) ->where('payment_method', 'stripe') ->first(); } if (!$transaction) { return; } if($transaction->status == 'paid') { return; // Already paid we don't have to do anything here } // We have the transaction so we have to update some fields $updateData = array( 'status' => 'paid' ); if (!$transaction->card_last_4) { if (!empty($charge->source->last4)) { $updateData['card_last_4'] = $charge->source->last4; } else if (!empty($charge->payment_method_details->card->last4)) { $updateData['card_last_4'] = $charge->payment_method_details->card->last4; } } if (!$transaction->card_brand) { if (!empty($charge->source->brand)) { $updateData['card_brand'] = $charge->source->brand; } else if (!empty($charge->payment_method_details->card->network)) { $updateData['card_brand'] = $charge->payment_method_details->card->network; } } if(!$transaction->charge_id) { $updateData['charge_id'] = $charge->payment_intent; } wpFluent()->table('fluentform_transactions') ->where('id', $transaction->id) ->update($updateData); // We have to fire transaction paid hook here } /* * Handle Subscription Payment IPN * Refactored in version 2.0 */ private function maybeHandleSubscriptionPayment($event) { $data = $event->data->object; $subscriptionId = false; if (property_exists($data, 'subscription')) { $subscriptionId = $data->subscription; } if (!$subscriptionId) { return; } $subscription = wpFluent()->table('fluentform_subscriptions') ->where('vendor_subscription_id', $subscriptionId) ->where('vendor_customer_id', $data->customer) ->first(); if (!$subscription) { return; } $submission = wpFluent()->table('fluentform_submissions') ->where('id', $subscription->submission_id) ->first(); if (!$submission) { return; } $transactionData = $this->createSubsTransactionDataFromInvoice($data, $subscription, $submission); // We may have an already exist session charge that we have to update $pendingTransaction = wpFluent()->table('fluentform_transactions') ->whereNull('charge_id') ->where('submission_id', $submission->id) ->where('status', 'pending') ->first(); if($pendingTransaction) { unset($transactionData['transaction_hash']); unset($transactionData['created_at']); wpFluent()->table('fluentform_transactions') ->where('id', $pendingTransaction->id) ->update($transactionData); } else { (new StripeProcessor())->recordSubscriptionCharge($subscription, $transactionData); } } /* * Refactored at version 2.0 * We are logging refunds now for both subscription and * One time payments */ private function handleChargeRefund($event) { (new StripeProcessor())->handleRefund($event); } /* * Handle Subscription Canceled */ private function handleSubscriptionCancelled($event) { $data = $event->data->object; $subscriptionId = $data->id; $subscription = wpFluent()->table('fluentform_subscriptions') ->where('vendor_subscription_id', $subscriptionId) ->where('status', '!=', 'completed') ->first(); if (!$subscription || $subscription->status == 'cancelled') { return; } do_action_deprecated( 'fluentform_form_submission_activity_start', [ $subscription->form_id ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/form_submission_activity_start', 'Use fluentform/form_submission_activity_start instead of fluentform_form_submission_activity_start.' ); do_action('fluentform/form_submission_activity_start', $subscription->form_id); PaymentHelper::recordSubscriptionCancelled($subscription, $data); } private function handleCheckoutSessionCompleted($event) { $data = $event->data->object; $metaData = (array)$data->metadata; $formId = ArrayHelper::get($metaData, 'form_id'); $session = CheckoutSession::retrieve($data->id, [ 'expand' => [ 'subscription.latest_invoice.payment_intent', 'payment_intent' ] ], $formId); if (!$session || is_wp_error($session)) { return; } $submissionId = intval($session->client_reference_id); if (!$session || !$submissionId) { return; } if (Helper::getSubmissionMeta($submissionId, 'is_form_action_fired') == 'yes') { return; } // let's get the pending submission $submission = wpFluent()->table('fluentform_submissions') ->where('id', $submissionId) ->first(); if (!$submission) { return; } $transactionId = ArrayHelper::get($metaData, 'transaction_id'); if(!$transactionId) { return; } $transaction = wpFluent()->table('fluentform_transactions') ->where('form_id', $submission->form_id) ->where('id', $transactionId) ->where('submission_id', $submission->id) ->first(); if(!$transaction) { return; // not our transaction or transaction_status already paid } $returnData = (new StripeProcessor())->processStripeSession($session, $submission, $transaction); } /* * */ public function retrive($eventId, $formId = false) { $api = new ApiRequest(); $api::set_secret_key(StripeSettings::getSecretKey($formId)); return $api::request([], 'events/' . $eventId, 'GET'); } public function verifySignature($payload, $signature) { // Extract timestamp and signatures from header $timestamp = self::getTimestamp($signature); $signatures = self::getSignatures($signature); if (-1 === $timestamp) { return false; } if (empty($signatures)) { return false; } $signedPayload = "{$timestamp}.{$payload}"; if (!function_exists('hash_hmac')) { return false; } $secret = 'whsec_NsNZNMSnWVPLt8GErz3SVZ97pWu8eb6D'; $expectedSignature = \hash_hmac('sha256', $payload, $secret); foreach ($signatures as $signature) { if ($this->secureCompare($signature, $expectedSignature)) { return true; } } return false; } protected function getTimeStamp($signature) { $items = \explode(',', $signature); foreach ($items as $item) { $itemParts = \explode('=', $item, 2); if ('t' === $itemParts[0]) { if (!\is_numeric($itemParts[1])) { return -1; } return (int)($itemParts[1]); } } return -1; } private function getSignatures($header, $scheme = 'v1') { $signatures = []; $items = \explode(',', $header); foreach ($items as $item) { $itemParts = \explode('=', $item, 2); if (\trim($itemParts[0]) === $scheme) { $signatures[] = $itemParts[1]; } } return $signatures; } protected function secureCompare($a, $b) { if (function_exists('hash_equals')) { return \hash_equals($a, $b); } if (\strlen($a) !== \strlen($b)) { return false; } $result = 0; for ($i = 0; $i < \strlen($a); ++$i) { $result |= \ord($a[$i]) ^ \ord($b[$i]); } return 0 === $result; } protected function createSubsTransactionDataFromInvoice($invoice, $subscription, $submission) { $paymentIntent = false; if(!is_object($invoice->payment_intent)) { ApiRequest::set_secret_key(StripeSettings::getSecretKey($subscription->form_id)); $paymentIntent = ApiRequest::request([], 'payment_intents/'.$invoice->payment_intent, 'GET'); if(is_wp_error($paymentIntent)) { $paymentIntent = false; } $chargeId = $invoice->payment_intent; } else { $chargeId = $invoice->payment_intent->id; $paymentIntent = $invoice->payment_intent; } $paymentTotal = $invoice->amount_paid; if(PaymentHelper::isZeroDecimal($invoice->currency)) { $paymentTotal = $paymentTotal * 100; } $data = [ 'subscription_id' => $subscription->id, 'form_id' => $subscription->form_id, 'transaction_hash' => md5('subscription_trans_'.wp_generate_uuid4().time()), 'user_id' => $submission->user_id, 'submission_id' => $submission->id, 'transaction_type' => 'subscription', 'payment_method' => 'stripe', 'card_last_4' => '', 'card_brand' => '', 'payer_name' => $invoice->customer_name, 'payer_email' => $invoice->customer_email, 'charge_id' => $chargeId, 'payment_total' => $paymentTotal, 'status' => 'paid', 'currency' => strtoupper($invoice->currency), 'payment_mode' => ($invoice->livemode) ? 'live' : 'test', 'payment_note' => maybe_serialize($invoice), 'created_at' => current_time('mysql'), 'updated_at' => current_time('mysql'), ]; if($paymentIntent && !empty($paymentIntent->charges->data[0]->payment_method_details->card)) { $card = $paymentIntent->charges->data[0]->payment_method_details->card; $data['card_brand'] = $card->brand; $data['card_last_4'] = $card->last4; } return $data; } } PK!j:src/Payments/PaymentMethods/Stripe/API/CheckoutSession.phpnu[ 'auto' ]; $args = wp_parse_args($args, $argsDefault); $formId = ArrayHelper::get($args, 'metadata.form_id'); $secretKey = apply_filters_deprecated( 'fluentform-payment_stripe_secret_key', [ StripeSettings::getSecretKey($formId), $formId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_stripe_secret_key', 'Use fluentform/payment_stripe_secret_key instead of fluentform-payment_stripe_secret_key.' ); $secretKey = apply_filters('fluentform/payment_stripe_secret_key', $secretKey, $formId); ApiRequest::set_secret_key($secretKey); return ApiRequest::request($args, 'checkout/sessions'); } public static function retrieve($sessionId, $args = [], $formId = false) { $secretKey = apply_filters_deprecated( 'fluentform-payment_stripe_secret_key', [ StripeSettings::getSecretKey($formId), $formId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_stripe_secret_key', 'Use fluentform/payment_stripe_secret_key instead of fluentform-payment_stripe_secret_key.' ); $secretKey = apply_filters('fluentform/payment_stripe_secret_key', $secretKey, $formId); ApiRequest::set_secret_key($secretKey); return ApiRequest::request($args, 'checkout/sessions/' . $sessionId, 'GET'); } } PK!,[dd3src/Payments/PaymentMethods/Stripe/API/Customer.phpnu[getMessage()); } } public static function validate($args) { $errors = []; if (empty($args['source']) && empty($args['payment_method'])) { $errors['source'] = __('Stripe token/payment_method is required', 'fluentformpro'); } return $errors; } } PK!.5src/Payments/PaymentMethods/Stripe/API/ApiRequest.phpnu[ 'Fluent Forms', 'version' => FLUENTFORMPRO_VERSION, 'url' => site_url(), 'partner_id' => 'pp_partner_FN62GfRLM2Kx5d' ); return array( 'lang' => 'php', 'lang_version' => phpversion(), 'publisher' => 'wpmanageninja', 'uname' => php_uname(), 'application' => $app_info, ); } /** * Generates the headers to pass to API request. * * @since 4.0.0 * @version 4.0.0 */ public static function get_headers() { $user_agent = self::get_user_agent(); $app_info = $user_agent['application']; $headers = [ 'Authorization' => 'Basic ' . base64_encode(self::get_secret_key() . ':'), 'Stripe-Version' => self::STRIPE_API_VERSION, 'User-Agent' => $app_info['name'] . '/' . $app_info['version'] . ' (' . $app_info['url'] . ')', 'X-Stripe-Client-User-Agent' => json_encode($user_agent), ]; $headers = apply_filters_deprecated( 'fluentform_stripe_request_headers', [ $headers ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/stripe_request_headers', 'Use fluentform/stripe_request_headers instead of fluentform_stripe_request_headers.' ); return apply_filters('fluentform/stripe_request_headers', $headers); } /** * Send the request to Stripe's API * * @param array $request * @param string $api * @param string $method * @return object|\WP_Error * @since 3.1.0 * @version 4.0.6 */ public static function request($request, $api = 'charges', $method = 'POST') { $headers = self::get_headers(); if ('charges' === $api && 'POST' === $method) { $customer = !empty($request['customer']) ? $request['customer'] : ''; $source = !empty($request['source']) ? $request['source'] : $customer; $key = ArrayHelper::get($request, 'metadata.fluentform_tid') . '-' . $source . '-' . $api; $key = apply_filters_deprecated( 'fluentform_stripe_idempotency_key', [ $key, $request ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/stripe_idempotency_key', 'Use fluentform/stripe_idempotency_key instead of fluentform_stripe_idempotency_key.' ); $idempotency_key = apply_filters('fluentform/stripe_idempotency_key', $key, $request); $headers['Idempotency-Key'] = $idempotency_key; } $request = apply_filters_deprecated( 'fluentform_stripe_request_body', [ $request, $api ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/stripe_request_body', 'Use fluentform/stripe_request_body instead of fluentform_stripe_request_body.' ); $response = wp_safe_remote_post( self::$ENDPOINT . $api, array( 'method' => $method, 'headers' => $headers, 'body' => apply_filters('fluentform/stripe_request_body', $request, $api), 'timeout' => 50, ) ); if (is_wp_error($response) || empty($response['body'])) { return new \WP_Error('stripe_error', __('There was a problem connecting to the Stripe API endpoint.', 'fluentformpro')); } $body = json_decode(wp_remote_retrieve_body($response)); // check if it's a stripe error or not $responseCode = wp_remote_retrieve_response_code($response); if($responseCode > 299) { $code = __('general_error', 'fluentformpro'); if(!empty($body->error->code)) { $code = $body->error->code; } $message = __('Stripe General Error', 'fluentformpro'); if(!empty($body->error->message)) { $message = $body->error->message; } return new \WP_Error($code, $message, $body); } return $body; } /** * Retrieve API endpoint. * * @param string $api * @return mixed|\WP_Error|null * @since 4.0.0 * @version 4.0.0 */ public static function retrieve($api) { $response = wp_safe_remote_get( self::$ENDPOINT . $api, array( 'method' => 'GET', 'headers' => self::get_headers(), 'timeout' => 70, ) ); if (is_wp_error($response) || empty($response['body'])) { return new \WP_Error('stripe_error', __('There was a problem connecting to the Stripe API endpoint.', 'fluentformpro')); } return json_decode($response['body']); } }PK!3~ ~ .src/Payments/PaymentMethods/Stripe/API/SCA.phpnu[ 'manual', 'confirm' => 'true' ]; $args = wp_parse_args($args, $argsDefault); $secretKey = apply_filters_deprecated( 'fluentform-payment_stripe_secret_key', [ StripeSettings::getSecretKey($formId), $formId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_stripe_secret_key', 'Use fluentform/payment_stripe_secret_key instead of fluentform-payment_stripe_secret_key.' ); $secretKey = apply_filters('fluentform/payment_stripe_secret_key', $secretKey, $formId); ApiRequest::set_secret_key($secretKey); $response = ApiRequest::request($args, 'payment_intents'); return static::processResponse($response); } public static function retrievePaymentIntent($intentId, $args, $formId) { $secretKey = apply_filters_deprecated( 'fluentform-payment_stripe_secret_key', [ StripeSettings::getSecretKey($formId), $formId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_stripe_secret_key', 'Use fluentform/payment_stripe_secret_key instead of fluentform-payment_stripe_secret_key.' ); $secretKey = apply_filters('fluentform/payment_stripe_secret_key', $secretKey, $formId); ApiRequest::set_secret_key($secretKey); $response = ApiRequest::request($args, 'payment_intents/'.$intentId); return static::processResponse($response); } public static function confirmPayment($intendId, $args, $formId) { $secretKey = apply_filters_deprecated( 'fluentform-payment_stripe_secret_key', [ StripeSettings::getSecretKey($formId), $formId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_stripe_secret_key', 'Use fluentform/payment_stripe_secret_key instead of fluentform-payment_stripe_secret_key.' ); $secretKey = apply_filters('fluentform/payment_stripe_secret_key', $secretKey, $formId); ApiRequest::set_secret_key($secretKey); $argsDefault = [ 'payment_method' => '' ]; $args = wp_parse_args($args, $argsDefault); $response = ApiRequest::request($args, 'payment_intents/' . $intendId . '/confirm'); return static::processResponse($response); } } PK! 2src/Payments/PaymentMethods/Stripe/API/Account.phpnu[error)) { $errorType = 'general'; if (!empty($response->error->type)) { $errorType = $response->error->type; } $errorCode = ''; if (!empty($response->error->code)) { $errorCode = $response->error->code . ' : '; } return static::errorHandler($errorType, $errorCode . $response->error->message); } if (false !== $response) { return $response; } return false; } private static function errorHandler($code, $message, $data = []) { return new \WP_Error($code, $message, $data); } } PK!`(`(/src/Payments/PaymentMethods/Stripe/API/Plan.phpnu[getMessage()); } } public static function create($plan, $formId) { $secretKey = apply_filters_deprecated( 'fluentform-payment_stripe_secret_key', [ StripeSettings::getSecretKey($formId), $formId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_stripe_secret_key', 'Use fluentform/payment_stripe_secret_key instead of fluentform-payment_stripe_secret_key.' ); $secretKey = apply_filters('fluentform/payment_stripe_secret_key', $secretKey, $formId); ApiRequest::set_secret_key($secretKey); $response = ApiRequest::request($plan, 'plans', 'POST'); return static::processResponse($response); } public static function getPriceIdsFromSubscriptionTransaction($subscription, $subscriptionTransaction) { if ($subscriptionTransaction->transaction_type != 'subscription') { return false; } $planItems = []; $subscriptionPlan = self::getSubscriptionPlanBySubscription($subscription, $subscriptionTransaction->currency); if(is_wp_error($subscriptionPlan)) { return $subscriptionPlan; } $planItems[] = [ 'price' => $subscriptionPlan->id, 'quantity' => $subscription->quantity ? $subscription->quantity : 1 ]; // Maybe we have signup fee and other single payment amount $transactionTotal = $subscriptionTransaction->payment_total; $subscriptionFirstTotal = 0; if (!$subscription->trial_days) { $subscriptionFirstTotal += $subscription->recurring_amount; } $signupFee = 0; if ($transactionTotal > $subscriptionFirstTotal) { $signupFee = $transactionTotal - $subscriptionFirstTotal; } return [ 'items' => $planItems, 'signup_fee' => $signupFee ]; } public static function getOrCreate($subscription, $submission) { if (PaymentHelper::isZeroDecimal($submission->currency)) { $subscription->recurring_amount = intval($subscription->recurring_amount / 100); } // Generate The subscription ID Here $subscriptionId = static::getGeneratedSubscriptionId($subscription, $submission->currency); $stripePlan = static::retrieve($subscriptionId, $subscription->form_id); if ($stripePlan && !is_wp_error($stripePlan)) { return $stripePlan; } // We don't have this plan yet. Now we have to create the plan from subscription $plan = array( 'id' => $subscriptionId, 'currency' => $submission->currency, 'interval' => $subscription->billing_interval, 'amount' => $subscription->recurring_amount, 'trial_period_days' => $subscription->trial_days, 'product' => [ 'id' => $subscriptionId, 'name' => $subscription->item_name . ' (' . $subscription->plan_name . ')', 'type' => 'service' ], 'metadata' => [ 'form_id' => $subscription->form_id, 'element_id' => $subscription->element_id, 'wp_plugin' => 'Fluent Forms Pro' ] ); return static::create($plan, $subscription->form_id); } public static function getGeneratedSubscriptionId($subscription, $currency = 'USD') { $subscriptionId = 'fluentform_' . $subscription->element_id . '_' . $subscription->recurring_amount . '_' . $subscription->billing_interval . '_' . $subscription->trial_days . '_' . $currency;; $subscriptionId = apply_filters_deprecated( 'fluentform_stripe_plan_name_generated', [ $subscriptionId, $subscription, $currency ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/stripe_plan_name_generated', 'Use fluentform/stripe_plan_name_generated instead of fluentform_stripe_plan_name_generated.' ); return apply_filters('fluentform/stripe_plan_name_generated', $subscriptionId, $subscription, $currency); } public static function subscribe($subscriptionArgs, $formId) { $secretKey = apply_filters_deprecated( 'fluentform-payment_stripe_secret_key', [ StripeSettings::getSecretKey($formId), $formId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_stripe_secret_key', 'Use fluentform/payment_stripe_secret_key instead of fluentform-payment_stripe_secret_key.' ); $secretKey = apply_filters('fluentform/payment_stripe_secret_key', $secretKey, $formId); ApiRequest::set_secret_key($secretKey); return ApiRequest::request($subscriptionArgs, 'subscriptions', 'POST'); } public static function getCancelledAtTimestamp($subscription) { if(!$subscription->bill_times) { return false; // bill times is unlimited } $billTimes = $subscription->bill_times; $billPeriod = $subscription->billing_interval; $dateString = $billTimes.' '.$billPeriod; if($subscription->expiration_at) { return strtotime($subscription->expiration_at) - time() + strtotime($dateString); // after 6 hours } return strtotime($dateString); } public static function getSubscriptionPlanBySubscription($subscription, $currency) { $recurringAmount = $subscription->recurring_amount; if (PaymentHelper::isZeroDecimal($currency)) { $recurringAmount = intval($subscription->recurring_amount / 100); } $planNameArgs = [ 'fluentform', $subscription->form_id, $recurringAmount, $subscription->billing_interval, $currency ]; $planName = apply_filters_deprecated( 'fluentform_stripe_plan_name', [ implode('_', $planNameArgs), $subscription ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/stripe_plan_name', 'Use fluentform/stripe_plan_name instead of fluentform_stripe_plan_name.' ); $planName = apply_filters('fluentform/stripe_plan_name', $planName, $subscription); $subscriptionPlan = static::retrieve($planName, $subscription->form_id); if (!is_wp_error($subscriptionPlan) && $subscriptionPlan) { return $subscriptionPlan; } $plan = array( 'id' => $planName, 'currency' => $currency, 'interval' => $subscription->billing_interval, 'amount' => $recurringAmount, 'trial_period_days' => $subscription->trial_days, 'product' => [ 'id' => $subscription->id, 'name' => $subscription->plan_name, 'type' => 'service' ], 'metadata' => [ 'form_id' => $subscription->form_id, 'element_id' => $subscription->element_id, 'wp_plugin' => 'Fluent Forms Pro' ], 'nickname' => $subscription->item_name . ' - ' . $subscription->plan_name ); return static::create($plan, $subscription->form_id); } public static function maybeSetCancelAt($subscription, $stripeSub) { if($stripeSub->cancel_at) { return; } if(!$subscription->bill_times) { return; } $trialOffset = 0; $dateStr = '+'.$subscription->bill_times.' '.$subscription->billing_interval; if($subscription->trial_days) { $trialOffset = $subscription->trial_days * 86400; } $startingTimestamp = $stripeSub->created; $cancelAt = $startingTimestamp + $trialOffset + (strtotime($dateStr) - time()); $secretKey = apply_filters_deprecated( 'fluentform-payment_stripe_secret_key', [ StripeSettings::getSecretKey($subscription->form_id), $subscription->form_id ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_stripe_secret_key', 'Use fluentform/payment_stripe_secret_key instead of fluentform-payment_stripe_secret_key.' ); $secretKey = apply_filters('fluentform/payment_stripe_secret_key', $secretKey, $subscription->form_id); ApiRequest::set_secret_key($secretKey); return ApiRequest::request([ 'cancel_at' => $cancelAt ], 'subscriptions/' . $stripeSub->id, 'POST'); } } PK! E|C C >src/Payments/PaymentMethods/Stripe/Components/StripeInline.phpnu[instance_index == $targetForm->instance_index) { $classes .= ' ff_has_stripe_inline'; } return $classes; }, 10, 2); $elementId = $data['attributes']['name'] . '_' . $form->id . '_' . $form->instance_index . '_stripe_inline'; $label = ArrayHelper::get($method, 'settings.option_label.value', __('Pay with Stripe', 'fluentformpro')); $display = $method['is_default'] ? 'block' : 'none'; $markup = '
    '; $markup .= '
    '; $markup .= ''; $markup .= '
    '; $attributes = [ 'name' => 'stripe_card_element', 'class' => 'ff_stripe_card_element ff-el-form-control', 'data-wpf_payment_method' => 'stripe', 'id' => $elementId, 'data-checkout_style' => 'embedded_form', 'data-verify_zip' => ArrayHelper::get($method, 'settings.verify_zip.value') === 'yes' ]; $markup .= '
    buildAttributes($attributes) . '>
    '; $markup .= ''; if (!StripeSettings::isLive($form->id)) { $stripeTestModeMessage = __('Stripe test mode activated', 'fluentformpro'); $markup .= '' . $stripeTestModeMessage . ''; } $markup .= '
    '; return $inlineContents . $markup; } /** * We don't need to return anything from here */ function getComponent() { } /** * We don't need to return anything from here */ function render($element, $form) { } } PK!%E0335src/Payments/PaymentMethods/Stripe/StripeSettings.phpnu[ '', 'test_secret_key' => '', 'live_publishable_key' => '', 'live_secret_key' => '', 'payment_mode' => 'test', 'is_active' => 'no', 'provider' => 'api_keys', 'test_account_id' => '', 'live_account_id' => '', 'is_encrypted' => 'no' ]; $settings = get_option('fluentform_payment_settings_stripe', []); if (!$settings) { $defaults['provider'] = 'connect'; } $settings = wp_parse_args($settings, $defaults); if ($settings['provider'] == 'connect' && apply_filters('fluentform/disable_stripe_connect', false)) { $settings['provider'] = 'api_keys'; } if ($decrypted) { $settings = self::maybeDecryptKeys($settings); } return $settings; } public static function updateSettings($data) { $settings = self::getSettings(); $settings = wp_parse_args($data, $settings); $settings = self::encryptKeys($settings); update_option('fluentform_payment_settings_stripe', $settings); return self::getSettings(); } public static function encryptKeys($settings) { $settings['live_secret_key'] = PaymentHelper::encryptKey($settings['live_secret_key']); $settings['test_secret_key'] = PaymentHelper::encryptKey($settings['test_secret_key']); $settings['is_encrypted'] = 'yes'; return $settings; } public static function maybeDecryptKeys($settings) { if (ArrayHelper::get($settings, 'is_encrypted') == 'yes') { if (!empty($settings['live_secret_key'])) { $settings['live_secret_key'] = PaymentHelper::decryptKey($settings['live_secret_key']); } if (!empty($settings['test_secret_key'])) { $settings['test_secret_key'] = PaymentHelper::decryptKey($settings['test_secret_key']); } } else { $encrypted = self::encryptKeys($settings); update_option('fluentform_payment_settings_stripe', $encrypted); } $settings['is_encrypted'] = 'yes'; return $settings; } public static function getSecretKey($formId = false) { if ($formId) { $formPaymentSettings = PaymentHelper::getFormSettings($formId, 'admin'); if (ArrayHelper::get($formPaymentSettings, 'stripe_account_type') == 'custom') { return ArrayHelper::get($formPaymentSettings, 'stripe_custom_config.secret_key'); } } $settings = self::getSettings(); if ($settings['payment_mode'] == 'live') { return $settings['live_secret_key']; } return $settings['test_secret_key']; } public static function getPublishableKey($formId = false) { if ($formId) { $formPaymentSettings = PaymentHelper::getFormSettings($formId, 'admin'); if (ArrayHelper::get($formPaymentSettings, 'stripe_account_type') == 'custom') { return ArrayHelper::get($formPaymentSettings, 'stripe_custom_config.publishable_key'); } } $settings = self::getSettings(); if ($settings['payment_mode'] == 'live') { return $settings['live_publishable_key']; } return $settings['test_publishable_key']; } public static function isLive($formId = false) { if ($formId) { $formPaymentSettings = PaymentHelper::getFormSettings($formId, 'admin'); if (ArrayHelper::get($formPaymentSettings, 'stripe_account_type') == 'custom') { return ArrayHelper::get($formPaymentSettings, 'stripe_custom_config.payment_mode') == 'live'; } } $settings = self::getSettings(); return $settings['payment_mode'] == 'live'; } public static function getMode($formId = false) { return static::isLive($formId) ? 'live' : 'test'; } public static function supportedShippingCountries() { $countries = [ 'AC', 'AD', 'AE', 'AF', 'AG', 'AI', 'AL', 'AM', 'AO', 'AQ', 'AR', 'AT', 'AU', 'AW', 'AX', 'AZ', 'BA', 'BB', 'BD', 'BE', 'BF', 'BG', 'BH', 'BI', 'BJ', 'BL', 'BM', 'BN', 'BO', 'BQ', 'BR', 'BS', 'BT', 'BV', 'BW', 'BY', 'BZ', 'CA', 'CD', 'CF', 'CG', 'CH', 'CI', 'CK', 'CL', 'CM', 'CN', 'CO', 'CR', 'CV', 'CW', 'CY', 'CZ', 'DE', 'DJ', 'DK', 'DM', 'DO', 'DZ', 'EC', 'EE', 'EG', 'EH', 'ER', 'ES', 'ET', 'FI', 'FJ', 'FK', 'FO', 'FR', 'GA', 'GB', 'GD', 'GE', 'GF', 'GG', 'GH', 'GI', 'GL', 'GM', 'GN', 'GP', 'GQ', 'GR', 'GS', 'GT', 'GU', 'GW', 'GY', 'HK', 'HN', 'HR', 'HT', 'HU', 'ID', 'IE', 'IL', 'IM', 'IN', 'IO', 'IQ', 'IS', 'IT', 'JE', 'JM', 'JO', 'JP', 'KE', 'KG', 'KH', 'KI', 'KM', 'KN', 'KR', 'KW', 'KY', 'KZ', 'LA', 'LB', 'LC', 'LI', 'LK', 'LR', 'LS', 'LT', 'LU', 'LV', 'LY', 'MA', 'MC', 'MD', 'ME', 'MF', 'MG', 'MK', 'ML', 'MM', 'MN', 'MO', 'MQ', 'MR', 'MS', 'MT', 'MU', 'MV', 'MW', 'MX', 'MY', 'MZ', 'NA', 'NC', 'NE', 'NG', 'NI', 'NL', 'NO', 'NP', 'NR', 'NU', 'NZ', 'OM', 'PA', 'PE', 'PF', 'PG', 'PH', 'PK', 'PL', 'PM', 'PN', 'PR', 'PS', 'PT', 'PY', 'QA', 'RE', 'RO', 'RS', 'RU', 'RW', 'SA', 'SB', 'SC', 'SE', 'SG', 'SH', 'SI', 'SJ', 'SK', 'SL', 'SM', 'SN', 'SO', 'SR', 'SS', 'ST', 'SV', 'SX', 'SZ', 'TA', 'TC', 'TD', 'TF', 'TG', 'TH', 'TJ', 'TK', 'TL', 'TM', 'TN', 'TO', 'TR', 'TT', 'TV', 'TW', 'TZ', 'UA', 'UG', 'US', 'UY', 'UZ', 'VA', 'VC', 'VE', 'VG', 'VN', 'VU', 'WF', 'WS', 'XK', 'YE', 'YT', 'ZA', 'ZM', 'ZW', 'ZZ' ]; return apply_filters('fluentform/stripe_supported_shipping_countries', $countries); } public static function getClientId($paymentMode = 'live') { if ($paymentMode == 'live') { return 'ca_GwAPNUlKAW6EgeTqERQieU3DXLAX3k7N'; } else { return 'ca_GwAPhxHwszjhsFRdC4j5DqKHud7JLQ8C'; } } public static function guessFormIdFromEvent($event) { $eventType = $event->type; $metaDataEvents = [ 'checkout.session.completed', 'charge.refunded', 'charge.succeeded' ]; if (in_array($eventType, $metaDataEvents)) { $data = $event->data->object; $metaData = (array)$data->metadata; return ArrayHelper::get($metaData, 'form_id'); } return false; } public static function getPaymentDescriptor($form) { $title = $form->title; $paymentSettings = PaymentHelper::getFormSettings($form->id, 'admin'); if ($providedDescriptor = ArrayHelper::get($paymentSettings, 'stripe_descriptor')) { $title = $providedDescriptor; } else { $globalSettings = PaymentHelper::getPaymentSettings(); if (!empty($globalSettings['business_name'])) { $title = $globalSettings['business_name']; } } $illegal = array('<', '>', '"', "'"); // Remove slashes $descriptor = stripslashes($title); // Remove illegal characters $descriptor = str_replace($illegal, '', $descriptor); // Trim to 22 characters max $descriptor = substr($descriptor, 0, 22); if (!$descriptor || strlen($descriptor) < 5) { $descriptor = 'FluentForm'; } return $descriptor; } } PK!bk  5src/Payments/PaymentMethods/Stripe/PaymentManager.phpnu[find($subscription->submission_id); } if(!$submission || $submission->payment_method != 'stripe') { return new \WP_Error('method_mismatch', __('Failed to cancel this subscription', 'fluentformpro')); } // Get the first transaction to determine the payment mode $lastTransaction = wpFluent()->table('fluentform_transactions') ->orderBy('id', 'DESC') ->where('subscription_id', $subscription->id) ->where('payment_method', 'stripe') ->first(); if(!$lastTransaction) { return new \WP_Error('transaction_mismatch', __('Failed to cancel this subscription', 'fluentformpro')); } $vendorSubscriptionId = $subscription->vendor_subscription_id; if(!$vendorSubscriptionId) { return new \WP_Error('no_vendor_subscription_found', __('Failed to cancel this subscription', 'fluentformpro')); } $secretKey = StripeSettings::getSecretKey($submission->form_id); ApiRequest::set_secret_key($secretKey); $response = ApiRequest::request([], 'subscriptions/'.$vendorSubscriptionId, 'DELETE'); if(is_wp_error($response)) { return $response; } PaymentHelper::recordSubscriptionCancelled($subscription, $response, [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'General', 'status' => 'info', 'title' => __('Subscription has been cancelled by ', 'fluentformpro') . $scope, 'description' => __('Subscription has been cancelled from ', 'fluentformpro') . $submission->payment_method ]); // It's a success so let's send a valid response return $response; } public function refundTransaction($transaction, $scope = 'admin') { } private function retrieveVendorSubscription($subscription) { } private function retrieveVendorTransaction($transaction) { } }PK!8Tbb6src/Payments/PaymentMethods/Stripe/StripeProcessor.phpnu[method, array($this, 'handleSessionRedirectBack')); } public function handlePaymentAction($submissionId, $submissionData, $form, $methodSettings, $hasSubscriptions, $totalPayable) { $this->setSubmissionId($submissionId); $this->form = $form; $submission = $this->getSubmission(); $paymentTotal = $this->getAmountTotal(); if (!$paymentTotal && !$hasSubscriptions) { return false; } // Create the initial transaction here $transaction = $this->createInitialPendingTransaction($submission, $hasSubscriptions); $this->handleCheckoutSession($transaction, $submission, $form, $methodSettings); } public function handleCheckoutSession($transaction, $submission, $form, $methodSettings) { $formSettings = PaymentHelper::getFormSettings($form->id); $args = [ 'fluentform_payment' => $submission->id, 'payment_method' => $this->method, 'transaction_hash' => $transaction->transaction_hash, 'type' => 'success' ]; $successUrl = add_query_arg($args, site_url('index.php')); $cancelUrl = $submission->source_url; if (!wp_http_validate_url($cancelUrl)) { $cancelUrl = site_url($cancelUrl); } $checkoutArgs = [ 'cancel_url' => wp_sanitize_redirect($cancelUrl), 'success_url' => wp_sanitize_redirect($successUrl), 'locale' => 'auto', 'billing_address_collection' => 'auto', 'client_reference_id' => $submission->id, 'customer_email' => $transaction->payer_email, 'metadata' => [ 'submission_id' => $submission->id, 'form_id' => $form->id, 'transaction_id' => ($transaction) ? $transaction->id : '' ] ]; if (ArrayHelper::get($methodSettings, 'settings.require_billing_info.value') == 'yes') { $checkoutArgs['billing_address_collection'] = 'required'; } if (ArrayHelper::get($methodSettings, 'settings.require_shipping_info.value') == 'yes') { $checkoutArgs['shipping_address_collection'] = [ 'allowed_countries' => StripeSettings::supportedShippingCountries() ]; } if ($lineItems = $this->getFormattedItems($submission->currency)) { $checkoutArgs['line_items'] = $lineItems; } $receiptEmail = PaymentHelper::getCustomerEmail($submission, $form); if ($receiptEmail) { $checkoutArgs['customer_email'] = $receiptEmail; } if ($transaction->transaction_type == 'subscription') { unset($checkoutArgs['submit_type']); $subscriptions = $this->getSubscriptions(); $subscription = $subscriptions[0]; if ($subscription->initial_amount) { if (!isset($checkoutArgs['line_items'])) { $checkoutArgs['line_items'] = []; } $price = $subscription->initial_amount; if (PaymentHelper::isZeroDecimal($transaction->currency)) { $price = intval($price / 100); } $checkoutArgs['line_items'][] = [ 'amount' => $price, 'currency' => $transaction->currency, 'name' => __('Signup fee for ', 'fluentformpro') . $subscription->plan_name, 'quantity' => 1 ]; } $stripePlan = Plan::getSubscriptionPlanBySubscription($subscription, $transaction->currency); if(is_wp_error($stripePlan)) { $this->handlePaymentChargeError($stripePlan->get_error_message(), $submission, $transaction); } $this->updateSubscription($subscription->id, [ 'vendor_plan_id' => $stripePlan->id ]); $subsArgs = [ 'items' => [ [ 'plan' => $stripePlan->id, 'quantity' => $subscription->quantity ? $subscription->quantity : 1 ] ] ]; if ($subscription->trial_days) { $subsArgs['trial_period_days'] = $subscription->trial_days; } $subsArgs['metadata'] = $this->getIntentMetaData($submission, $form, $transaction); $checkoutArgs['subscription_data'] = $subsArgs; } else { $checkoutArgs['submit_type'] = 'auto'; $checkoutArgs['payment_intent_data'] = $this->getPaymentIntentData($transaction, $submission, $form); if ($receiptEmail && ArrayHelper::get($formSettings, 'disable_stripe_payment_receipt') != 'yes') { $checkoutArgs['payment_intent_data']['receipt_email'] = $receiptEmail; } } if ($formSettings['transaction_type'] == 'donation' && $transaction->transaction_type != 'subscription') { $checkoutArgs['submit_type'] = 'donate'; } $checkoutArgs = apply_filters_deprecated( 'fluentform_stripe_checkout_args', [ $checkoutArgs, $submission, $transaction, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/stripe_checkout_args', 'Use fluentform/stripe_checkout_args instead of fluentform_stripe_checkout_args.' ); $checkoutArgs = apply_filters('fluentform/stripe_checkout_args', $checkoutArgs, $submission, $transaction, $form); $session = CheckoutSession::create($checkoutArgs); if (!empty($session->error) || is_wp_error($session)) { $error = __('Something is wrong', 'fluentformpro'); if (is_wp_error($session)) { $error = $session->get_error_message(); } else if (!empty($session->error->message)) { $error = $session->error->message; } wp_send_json([ 'errors' => __('Stripe Error: ', 'fluentformpro') . $error ], 423); } $this->setMetaData('stripe_session_id', $session->id); $logData = [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Payment', 'status' => 'info', 'title' => __('Redirect to Stripe', 'fluentformpro'), 'description' => __('User redirect to Stripe for completing the payment', 'fluentformpro') ]; do_action('fluentform/log_data', $logData); wp_send_json_success([ 'nextAction' => 'payment', 'actionName' => 'stripeRedirectToCheckout', 'sessionId' => $session->id, 'message' => __('You are redirecting to stripe.com to complete the purchase. Please wait while you are redirecting....', 'fluentformpro'), 'result' => [ 'insert_id' => $submission->id ] ], 200); } protected function getPaymentIntentData($transaction, $submission, $form) { $data = [ 'capture_method' => 'automatic', 'description' => $form->title, 'statement_descriptor_suffix' => StripeSettings::getPaymentDescriptor($form), ]; $paymentSettings = PaymentHelper::getFormSettings($form->id, 'admin'); $intentMeta = $this->getIntentMetaData($submission, $form, $transaction, $paymentSettings); $data['metadata'] = $intentMeta; return $data; } public function getFormattedItems($currency) { $orderItems = $this->getOrderItems(); $discountItems = $this->getDiscountItems(); $discountTotal = 0; foreach ($discountItems as $item) { $discountTotal += $item->line_total; } $orderTotal = 0; foreach ($orderItems as $orderItem) { $orderTotal += $orderItem->line_total; } $formattedItems = []; foreach ($orderItems as $item) { $price = $item->item_price; if($discountTotal) { $price = intval($price - ($discountTotal / $orderTotal) * $price); } if (PaymentHelper::isZeroDecimal($currency)) { $price = intval($price / 100); } $quantity = $item->quantity ?: 1; $stripeLine = [ 'amount' => $price, 'currency' => $currency, 'name' => $item->item_name, 'quantity' => $quantity ]; $formattedItems[] = $stripeLine; } return $formattedItems; } public function handleSessionRedirectBack($data) { $type = sanitize_text_field($data['type']); $submissionId = intval($data['fluentform_payment']); $this->setSubmissionId($submissionId); $submission = $this->getSubmission(); if (!$submission) { return; } if ($type == 'success') { if ($this->getMetaData('is_form_action_fired') == 'yes') { $returnData = $this->getReturnData(); } else { $sessionId = $this->getMetaData('stripe_session_id'); $session = CheckoutSession::retrieve($sessionId, [ 'expand' => [ 'subscription.latest_invoice.payment_intent', 'payment_intent' ] ], $submission->form_id); if ($session && !is_wp_error($session) && $session->customer) { $transactionHash = sanitize_text_field($data['transaction_hash']); $transaction = $this->getTransaction($transactionHash, 'transaction_hash'); $returnData = $this->processStripeSession($session, $submission, $transaction); } else { $error = __('Sorry! No Valid payment session found. Please try again'); if (is_wp_error($session)) { $error = $session->get_error_message(); } $returnData = [ 'insert_id' => $submission->id, 'title' => __('Failed to retrieve session data', 'fluentformpro'), 'result' => false, 'error' => $error ]; } } } else { $returnData = [ 'insert_id' => $submission->id, 'result' => false, 'error' => __('Looks like you have cancelled the payment. Please try again!', 'fluentformpro') ]; } $returnData['type'] = $type; if (!isset($returnData['is_new'])) { $returnData['is_new'] = false; } $this->showPaymentView($returnData); } public function processStripeSession($session, $submission, $transaction) { $this->setSubmissionId($submission->id); if ($transaction->status == 'paid' && $submission->payment_status == 'paid') { return $this->getReturnData(); } $invoice = empty($session->subscription->latest_invoice) ? $session : $session->subscription->latest_invoice; $paymentStatus = $this->getIntentSuccessName($invoice->payment_intent); $this->changeSubmissionPaymentStatus($paymentStatus); if($transaction->transaction_type == 'subscription') { $subscriptions = $this->getSubscriptions(); if($subscriptions) { $this->processSubscriptionSuccess($subscriptions, $invoice, $submission); $vendorSubscription = $session->subscription; if($vendorSubscription) { Plan::maybeSetCancelAt($subscriptions[0], $vendorSubscription); } } } $this->processOneTimeSuccess($invoice, $transaction, $paymentStatus); $returnData = $this->completePaymentSubmission(false); $this->recalculatePaidTotal(); $returnData['is_new'] = $this->getMetaData('is_form_action_fired') === 'yes'; return $returnData; } protected function getIntentSuccessName($intent) { if (!$intent || !$intent->status) { return false; } $successStatuses = [ 'succeeded' => 'paid', 'requires_capture' => 'requires_capture' ]; if (isset($successStatuses[$intent->status])) { return $successStatuses[$intent->status]; } return false; } protected function getDescriptor($title) { $illegal = array('<', '>', '"', "'"); // Remove slashes $descriptor = stripslashes($title); // Remove illegal characters $descriptor = str_replace($illegal, '', $descriptor); // Trim to 22 characters max return substr($descriptor, 0, 22); } protected function formatAddress($address) { $addressArray = [ 'line1' => $address->line1, 'line2' => $address->line2, 'city' => $address->city, 'state' => $address->state, 'postal_code' => $address->postal_code, 'country' => $address->country, ]; return implode(', ', array_filter($addressArray)); } public function handleRefund($event) { $data = $event->data->object; $chargeId = $data->payment_intent; // Get the Transaction from database $transaction = wpFluent()->table('fluentform_transactions') ->where('charge_id', $chargeId) ->where('payment_method', 'stripe') ->first(); if (!$transaction) { // Not our transaction return; } $submission = wpFluent()->table('fluentform_submissions') ->find($transaction->submission_id); if (!$submission) { return; } $this->setSubmissionId($submission->id); $amountRefunded = $data->amount_refunded; if (PaymentHelper::isZeroDecimal($data->currency)) { $amountRefunded = $amountRefunded * 100; } // Remove All Existing Refunds wpFluent()->table('fluentform_transactions') ->where('submission_id', $submission->id) ->where('transaction_type', 'refund') ->delete(); $this->refund($amountRefunded, $transaction, $submission, 'stripe', $chargeId, 'Refund from Stripe'); } public function getPaymentMode() { $stripeSettings = StripeSettings::getSettings(); return $stripeSettings['payment_mode']; } public function processSubscriptionSuccess($subscriptions, $invoice, $submission) { foreach ($subscriptions as $subscription) { $subscriptionStatus = 'active'; if ($subscription->trial_days) { $subscriptionStatus = 'trialling'; } $updateData = [ 'vendor_customer_id' => $invoice->customer, 'vendor_response' => maybe_serialize($invoice), ]; if(!$subscription->bill_count && $subscriptionStatus == 'active') { $updateData['bill_count'] = 1; } if (!$subscription->vendor_subscription_id) { $updateData['vendor_subscription_id'] = $invoice->subscription; } $this->updateSubscription($subscription->id, $updateData); $subscription = fluentFormApi('submissions')->getSubscription($subscription->id); $this->updateSubscriptionStatus($subscription, $subscriptionStatus); } $logData = [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Payment', 'status' => 'success', 'title' => __('Stripe Subscription Charged', 'fluentformpro'), 'description' => __('Stripe recurring subscription successfully initiated', 'fluentformpro') ]; do_action('fluentform/log_data', $logData); if (!empty($invoice->payment_intent->charges->data[0])) { $charge = $invoice->payment_intent->charges->data[0]; $this->recordStripeBillingAddress($charge, $submission); } } protected function recordStripeBillingAddress($charge, $submission) { if(!is_array($submission->response)) { $submission->response = json_decode($submission->response, true); } if (isset($submission->response['__checkout_billing_address_details'])) { return; } if (empty($charge->billing_details)) { return; } $billingDetails = $charge->billing_details; if (!empty($billingDetails->address)) { $submission->response['__checkout_billing_address_details'] = $billingDetails->address; } if (!empty($billingDetails->phone)) { $submission->response['__stripe_phone'] = $billingDetails->phone; } if (!empty($billingDetails->name)) { $submission->response['__stripe_name'] = $billingDetails->name; } if (!empty($billingDetails->email)) { $submission->response['__stripe_email'] = $billingDetails->email; } $this->updateSubmission($submission->id, [ 'response' => json_encode($submission->response) ]); $logData = [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Payment', 'status' => 'info', 'title' => __('Stripe Billing Address Logged', 'fluentformpro'), 'description' => __('Billing address from stripe has been logged in the submission data', 'fluentformpro') ]; do_action('fluentform/log_data', $logData); } protected function processOneTimeSuccess($invoice, $transaction, $paymentStatus) { if ($transaction) { $updateData = [ 'charge_id' => $invoice->payment_intent ? $invoice->payment_intent->id : null, 'status' => 'paid', 'payment_note' => maybe_serialize($invoice->payment_intent) ]; $updateData = array_merge($updateData, $this->retrieveCustomerDetailsFromInvoice($invoice)); $this->updateTransaction($transaction->id, $updateData); $this->changeTransactionStatus($transaction->id, $paymentStatus); } } protected function getIntentMetaData($submission, $form, $transaction, $paymentSettings = false) { if (!$paymentSettings) { $paymentSettings = PaymentHelper::getFormSettings($form->id, 'admin'); } $intentMeta = [ 'submission_id' => $submission->id, 'form_id' => $form->id, 'transaction_id' => $transaction->id, 'wp_plugin' => 'Fluent Forms Pro', 'form_title' => $form->title ]; $metaItems = ArrayHelper::get($paymentSettings, 'stripe_meta_data', []); if ((ArrayHelper::get($paymentSettings, 'push_meta_to_stripe') == 'yes') && !empty($metaItems)) { foreach ($metaItems as $metaItem) { if ($itemValue = ArrayHelper::get($metaItem, 'item_value')) { $metaData[ArrayHelper::get($metaItem, 'label', 'item')] = $itemValue; } } $metaData = ShortCodeParser::parse($metaData, $submission->id, $submission->response); $metaData = array_filter($metaData); foreach ($metaData as $itemKey => $value) { if (is_string($value) || is_numeric($value)) { $metaData[$itemKey] = strip_tags($value); } } $intentMeta = array_merge($intentMeta, $metaData); } return $intentMeta; } protected function retrieveCustomerDetailsFromInvoice($invoice) { $customer = []; if (!empty($invoice->payment_intent->charges->data[0])) { $charge = $invoice->payment_intent->charges->data[0]; $customer = $this->retrieveCustomerDetailsFromCharge($charge); $customer = array_merge($customer, [ 'payer_email' => $invoice->customer_email, 'payer_name' => $invoice->customer_name, ]); } return $customer; } protected function retrieveCustomerDetailsFromCharge($charge) { $customer = []; if (!empty($charge->billing_details)) { $customer['billing_address'] = $this->formatAddress($charge->billing_details->address); } if (!empty($charge->shipping) && !empty($charge->shipping->address)) { $customer['shipping_address'] = $this->formatAddress($charge->shipping->address); } if (!empty($charge->payment_method_details->card)) { $card = $charge->payment_method_details->card; $customer['card_brand'] = $card->brand; $customer['card_last_4'] = $card->last4; } return $customer; } protected function handlePaymentChargeError($message, $submission, $transaction, $charge = false, $type = 'general') { do_action_deprecated( 'fluentform_payment_stripe_failed', [ $submission, $transaction, $this->form->id, $charge, $type ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_stripe_failed', 'Use fluentform/payment_stripe_failed instead of fluentform_payment_stripe_failed.' ); do_action('fluentform/payment_stripe_failed', $submission, $transaction, $this->form->id, $charge, $type); do_action_deprecated( 'fluentform_payment_failed', [ $submission, $transaction, $this->form->id, $charge, $type ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_failed', 'Use fluentform/payment_failed instead of fluentform_payment_failed.' ); do_action('fluentform/payment_failed', $submission, $transaction, $this->form->id, $charge, $type); if ($transaction) { $this->changeTransactionStatus($transaction->id, 'failed'); } $this->changeSubmissionPaymentStatus('failed'); if ($message) { $logData = [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Payment', 'status' => 'error', 'title' => __('Stripe Payment Error', 'fluentformpro'), 'description' => __($message, 'fluentformpro') ]; do_action('fluentform/log_data', $logData); } wp_send_json([ 'errors' => __('Stripe Error: ', 'fluentformpro') . $message, 'append_data' => [ '__entry_intermediate_hash' => Helper::getSubmissionMeta($submission->id, '__entry_intermediate_hash') ] ], 423); } public function recordSubscriptionCharge($subscription, $transactionData) { $this->setSubmissionId($subscription->submission_id); return $this->maybeInsertSubscriptionCharge($transactionData); } } PK!%%г4src/Payments/PaymentMethods/Stripe/StripeHandler.phpnu[key, function () { $settings = StripeSettings::getSettings(); if ($settings['test_secret_key']) { $settings['test_secret_key'] = 'ENCRYPTED_KEY'; } if ($settings['live_secret_key']) { $settings['live_secret_key'] = 'ENCRYPTED_KEY'; } return $settings; }); add_filter('fluentform/payment_method_settings_validation_' . $this->key, array($this, 'validateSettings'), 10, 2); add_filter('fluentform/payment_method_settings_save_' . $this->key, array($this, 'sanitizeGlobalSettings'), 10, 1); if (!$this->isEnabled()) { return; } add_filter('fluentform/available_payment_methods', array($this, 'pushPaymentMethodToForm'), 10, 1); add_action('fluentform/rendering_payment_method_' . $this->key, array($this, 'enqueueAssets')); add_filter('fluentform/transaction_data_' . $this->key, array($this, 'modifyTransaction'), 10, 1); add_action('fluentform/ipn_endpoint_' . $this->key, function () { (new StripeListener())->verifyIPN(); }); add_action('fluentform/process_payment_stripe', [$this, 'routeStripeProcessor'], 10, 6); add_filter('fluentform/payment_manager_class_' . $this->key, function ($class) { return new PaymentManager(); }); (new StripeProcessor())->init(); (new StripeInlineProcessor())->init(); } public function routeStripeProcessor($submissionId, $submissionData, $form, $methodSettings, $hasSubscriptions, $totalPayable = 0) { $processor = ArrayHelper::get($methodSettings, 'settings.embedded_checkout.value') === 'yes' ? 'inline' : 'hosted'; do_action_deprecated( 'fluentform_process_payment_stripe_' . $processor, [ $submissionId, $submissionData, $form, $methodSettings, $hasSubscriptions, $totalPayable ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/process_payment_stripe_' . $processor, 'Use fluentform/process_payment_stripe_' . $processor . ' instead of fluentform_process_payment_stripe_' . $processor ); do_action('fluentform/process_payment_stripe_' . $processor, $submissionId, $submissionData, $form, $methodSettings, $hasSubscriptions, $totalPayable); } public function pushPaymentMethodToForm($methods) { if (!$this->isEnabled()) { return $methods; } $methods[$this->key] = [ 'title' => __('Credit/Debit Card (Stripe)', 'fluentformpro'), 'enabled' => 'yes', 'method_value' => $this->key, 'settings' => [ 'option_label' => [ 'type' => 'text', 'template' => 'inputText', 'value' => 'Pay with Card (Stripe)', 'label' => __('Method Label', 'fluentformpro') ], 'embedded_checkout' => [ 'type' => 'checkbox', 'template' => 'inputYesNoCheckbox', 'value' => 'yes', 'label' => __('Embedded Checkout', 'fluentformpro') ], 'require_billing_info' => [ 'type' => 'checkbox', 'template' => 'inputYesNoCheckbox', 'value' => 'no', 'label' => __('Require Billing info', 'fluentformpro'), 'dependency' => array( 'depends_on' => 'embedded_checkout/value', 'value' => 'yes', 'operator' => '!=' ) ], 'require_shipping_info' => [ 'type' => 'checkbox', 'template' => 'inputYesNoCheckbox', 'value' => 'no', 'label' => __('Collect Shipping Info', 'fluentformpro'), 'dependency' => array( 'depends_on' => 'embedded_checkout/value', 'value' => 'yes', 'operator' => '!=' ) ], 'verify_zip_code' => [ 'type' => 'checkbox', 'template' => 'inputYesNoCheckbox', 'value' => 'no', 'label' => __('Verify Zip/Postal Code', 'fluentformpro') ], ] ]; return $methods; } public function enqueueAssets() { wp_enqueue_script('stripe_elements', 'https://js.stripe.com/v3/', array('jquery'), '3.0', true); } public function validateSettings($errors, $settings) { if (ArrayHelper::get($settings, 'is_active') != 'yes') { return []; } $mode = $settings['payment_mode']; if (empty($settings[$mode . '_publishable_key'])) { $errors[$mode . '_publishable_key'] = __(ucfirst($mode) . ' Publishable Key is required', 'fluentformpro'); } if (empty($settings[$mode . '_secret_key'])) { $errors[$mode . '_secret_key'] = __(ucfirst($mode) . ' Secret Key is required', 'fluentformpro'); } if (ArrayHelper::get($settings, 'provider') === 'connect' && count($errors)) { $errors = [ 'connect' => __('Connect with Stripe was not successful. Please try again!', 'fluentformpro') ]; } return $errors; } public function modifyTransaction($transaction) { if ($transaction->charge_id) { $urlBase = 'https://dashboard.stripe.com/'; if ($transaction->payment_mode != 'live') { $urlBase .= 'test/'; } $transaction->action_url = $urlBase . 'payments/' . $transaction->charge_id; } if ($transaction->status == 'requires_capture') { $transaction->additional_note = __('Action Required: The payment has been authorized but not captured yet. Please Click here to capture this payment in stripe.com', 'fluentformpro'); } return $transaction; } public function isEnabled() { $settings = StripeSettings::getSettings(false); return $settings['is_active'] == 'yes'; } public function sanitizeGlobalSettings($settings) { if ($settings['is_active'] != 'yes') { return [ 'test_publishable_key' => '', 'test_secret_key' => '', 'live_publishable_key' => '', 'live_secret_key' => '', 'payment_mode' => 'test', 'is_active' => 'no', 'provider' => 'connect' // api_keys ]; } $prevSettings = StripeSettings::getSettings(true); if ($settings['test_secret_key'] == 'ENCRYPTED_KEY') { $settings['test_secret_key'] = $prevSettings['test_secret_key']; } if ($settings['live_secret_key'] == 'ENCRYPTED_KEY') { $settings['live_secret_key'] = $prevSettings['live_secret_key']; } return StripeSettings::encryptKeys($settings); } } PK!G G G<src/Payments/PaymentMethods/Stripe/StripeInlineProcessor.phpnu[setSubmissionId($submissionId); $this->form = $form; $submission = $this->getSubmission(); $paymentTotal = $this->getAmountTotal(); if (!$paymentTotal && !$hasSubscriptions) { return false; } // Create the initial transaction here $transaction = $this->createInitialPendingTransaction($submission, $hasSubscriptions); $paymentMethodId = ArrayHelper::get($submissionData['response'], '__stripe_payment_method_id'); $customerArgs = $this->customerArguments($paymentMethodId, $submission); $customer = Customer::createCustomer($customerArgs, $this->form->id); if (is_wp_error($customer)) { // We have errors $this->handlePaymentChargeError($customer->get_error_message(), $submission, $transaction); } if ($transaction->transaction_type == 'subscription') { $this->handleSetupIntent($submission, $paymentMethodId, $customer, $transaction, $totalPayable); } else { // Let's create the one time payment first // We will handle One-Time Payment Here only $paymentSettings = PaymentHelper::getFormSettings($form->id, 'admin'); $intentArgs = [ 'payment_method' => $paymentMethodId, 'amount' => $transaction->payment_total, 'currency' => $transaction->currency, 'confirmation_method' => 'manual', 'confirm' => 'true', 'description' => $this->getProductNames(), 'statement_descriptor_suffix' => StripeSettings::getPaymentDescriptor($form), 'metadata' => $this->getIntentMetaData($submission, $form, $transaction, $paymentSettings), 'customer' => $customer->id ]; $this->handlePaymentIntent($transaction, $submission, $intentArgs); } } // This is only for Subscription Payment protected function handleSetupIntent($submission, $paymentMethodId, $customer, $transaction, $totalPayable) { if (is_wp_error($customer)) { $this->handlePaymentChargeError($customer->get_error_message(), $submission, $transaction, false, 'customer'); } $subscriptions = $this->getSubscriptions(); $subscription = $subscriptions[0]; $subscriptionTransactionArgs = Plan::getPriceIdsFromSubscriptionTransaction($subscription, $transaction); if(is_wp_error($subscriptionTransactionArgs)) { $this->handlePaymentChargeError($customer->get_error_message(), $submission, $transaction, false, 'customer'); } $subscriptionArgs = [ 'customer' => $customer->id, 'metadata' => $this->getIntentMetaData($submission, $this->getForm(), $transaction), 'payment_behavior' => 'allow_incomplete', ]; $subscriptionArgs['items'] = $subscriptionTransactionArgs['items']; if ($signupFee = $subscriptionTransactionArgs['signup_fee']) { Invoice::createItem([ 'amount' => $signupFee, 'currency' => $submission->currency, 'customer' => $customer->id, 'description' => __('Signup fee for ', 'fluentformpro') . $subscription->plan_name ], $submission->form_id); } // Maybe we have to set a cancel_at parameter to subscription args if ($cancelledAt = Plan::getCancelledAtTimestamp($subscription)) { $subscriptionArgs['cancel_at'] = $cancelledAt; } if ($subscription->trial_days) { $dateTime = current_datetime(); $localtime = $dateTime->getTimestamp() + $dateTime->getOffset(); $subscriptionArgs['trial_end'] = $localtime + $subscription->trial_days * 86400; } $subscriptionPayment = Plan::subscribe($subscriptionArgs, $submission->form_id); if (is_wp_error($subscriptionPayment)) { $this->handlePaymentChargeError($subscriptionPayment->get_error_message(), $submission, $transaction, false, 'subscription'); } $invoice = Invoice::retrieve( $subscriptionPayment->latest_invoice, $this->form->id, [ 'expand' => ['payment_intent.charges'] ] ); if (is_wp_error($invoice)) { $this->handlePaymentChargeError($invoice->get_error_message(), $submission, $transaction, false, 'invoice'); } if ( $invoice->payment_intent && $invoice->payment_intent->status == 'requires_action' && $invoice->payment_intent->next_action->type == 'use_stripe_sdk' ) { $transactionId = false; if ($transaction) { $transactionId = $transaction->id; } $this->processScaBeforeVerification($submission->form_id, $submission->id, $transactionId, $invoice->payment_intent->id); wp_send_json_success([ 'nextAction' => 'payment', 'actionName' => 'stripeSetupIntent', 'stripe_subscription_id' => $subscriptionPayment->id, 'payment_method_id' => $paymentMethodId, 'intent' => $invoice->payment_intent, 'submission_id' => $submission->id, 'customer_name' => ($transaction) ? $transaction->payer_name : '', 'customer_email' => ($transaction) ? $transaction->payer_email : '', 'client_secret' => $invoice->payment_intent->client_secret, 'message' => __('Verifying your card details. Please wait...', 'fluentformpro'), 'result' => [ 'insert_id' => $submission->id ] ], 200); } // now this payment is successful. We don't need anything else $this->handlePaidSubscriptionInvoice($invoice, $submission); } protected function customerArguments($paymentMethodId, $submission) { $customerArgs = [ 'payment_method' => $paymentMethodId, 'invoice_settings' => [ 'default_payment_method' => $paymentMethodId ], 'metadata' => [ 'submission_id' => $submission->id, 'form_id' => $submission->form_id, 'form_name' => strip_tags($this->form->title) ] ]; $receiptEmail = PaymentHelper::getCustomerEmail($submission, $this->form); if ($receiptEmail) { $customerArgs['email'] = $receiptEmail; } $receiptName = PaymentHelper::getCustomerName($submission, $this->form); if ($receiptName) { $customerArgs['name'] = $receiptName; $customerArgs['description'] = $receiptName; } $address = PaymentHelper::getCustomerAddress($submission); if ($address) { $customerArgs['address'] = [ 'city' => ArrayHelper::get($address, 'city'), 'country' => ArrayHelper::get($address, 'country'), 'line1' => ArrayHelper::get($address, 'address_line_1'), 'line2' => ArrayHelper::get($address, 'address_line_2'), 'postal_code' => ArrayHelper::get($address, 'zip'), 'state' => ArrayHelper::get($address, 'state'), ]; } return $customerArgs; } protected function handlePaidSubscriptionInvoice($invoice, $submission) { if ($invoice->status !== 'paid') { wp_send_json([ 'errors' => __('Stripe Error: Payment Failed! Please try again.', 'fluentformpro') ], 423); } // Submission status as paid $this->changeSubmissionPaymentStatus('paid'); $subscriptions = $this->getSubscriptions(); $this->processSubscriptionSuccess($subscriptions, $invoice, $submission); $transaction = $this->getLastTransaction($submission->id); $paymentStatus = $this->getIntentSuccessName($invoice->payment_intent); $this->processOnetimeSuccess($invoice, $transaction, $paymentStatus); $this->recalculatePaidTotal(); $this->sendSuccess($submission); } protected function handlePaymentIntent($transaction, $submission, $intentArgs) { $formSettings = PaymentHelper::getFormSettings($submission->form_id); if (PaymentHelper::isZeroDecimal($transaction->currency)) { $intentArgs['amount'] = intval($transaction->payment_total / 100); } $receiptEmail = PaymentHelper::getCustomerEmail($submission, $this->form); if ($receiptEmail && ArrayHelper::get($formSettings, 'disable_stripe_payment_receipt') != 'yes') { $intentArgs['receipt_email'] = $receiptEmail; } $intent = SCA::createPaymentIntent($intentArgs, $this->form->id); if (is_wp_error($intent)) { $this->handlePaymentChargeError($intent->get_error_message(), $submission, $transaction, false, 'payment_intent'); } if ( $intent->status == 'requires_action' && $intent->next_action && $intent->next_action->type == 'use_stripe_sdk' ) { $this->processScaBeforeVerification($submission->form_id, $submission->id, $transaction->id, $intent->id); # Tell the client to handle the action wp_send_json_success([ 'nextAction' => 'payment', 'actionName' => 'initStripeSCAModal', 'submission_id' => $submission->id, 'client_secret' => $intent->client_secret, 'message' => apply_filters('fluentform/stripe_strong_customer_verify_waiting_message', __('Verifying strong customer authentication. Please wait...', 'fluentformpro')), 'result' => [ 'insert_id' => $submission->id ] ], 200); } else if ($intent->status == 'succeeded') { // Payment is succeeded here $charge = $intent->charges->data[0]; $this->handlePaymentSuccess($charge, $transaction, $submission); } else { $message = __('Payment Failed! Your card may have been declined.', 'fluentformpro'); if (!empty($intent->error->message)) { $message = $intent->error->message; } $this->handlePaymentChargeError($message, $submission, $transaction, false, 'payment_intent'); } } protected function handlePaymentSuccess($charge, $transaction, $submission) { $transactionData = [ 'charge_id' => $charge->payment_intent, 'payment_method' => 'stripe', 'payment_mode' => $this->getPaymentMode(), 'payment_note' => maybe_serialize($charge) ]; $methodDetails = $charge->payment_method_details; if ($methodDetails && !empty($methodDetails->card)) { $transactionData['card_brand'] = $methodDetails->card->brand; $transactionData['card_last_4'] = $methodDetails->card->last4; } $this->updateTransaction($transaction->id, $transactionData); $this->changeTransactionStatus($transaction->id, 'paid'); $logData = [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Payment', 'status' => 'info', 'title' => __('Payment Status changed', 'fluentformpro'), 'description' => __('Payment status changed to paid', 'fluentformpro') ]; do_action('fluentform/log_data', $logData); $this->updateSubmission($submission->id, [ 'payment_status' => 'paid', 'payment_method' => 'stripe', ]); $logData = [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Payment', 'status' => 'success', 'title' => __('Payment Complete', 'fluentformpro'), 'description' => __('One time Payment Successfully made via Stripe. Charge ID: ', 'fluentformpro') . $charge->id ]; do_action('fluentform/log_data', $logData); $this->recalculatePaidTotal(); $this->sendSuccess($submission); } public function confirmScaPayment() { $formId = intval($_REQUEST['form_id']); $submissionId = intval($_REQUEST['submission_id']); $paymentMethod = sanitize_text_field($_REQUEST['payment_method']); $paymentIntentId = sanitize_text_field($_REQUEST['payment_intent_id']); $this->setSubmissionId($submissionId); $submission = $this->getSubmission(); $this->form = $this->getForm(); $transaction = $this->getLastTransaction($submissionId); $confirmation = SCA::confirmPayment($paymentIntentId, [ 'payment_method' => $paymentMethod ], $formId); if (is_wp_error($confirmation)) { $message = 'Payment has been failed. ' . $confirmation->get_error_message(); $this->handlePaymentChargeError($message, $submission, $transaction, $confirmation, 'payment_error'); } if ($confirmation->status == 'succeeded') { $charge = $confirmation->charges->data[0];; $this->handlePaymentSuccess($charge, $transaction, $submission); } else { $this->handlePaymentChargeError('We could not verify your payment. Please try again', $submission, $transaction, $confirmation, 'payment_error'); } } public function confirmScaSetupIntentsPayment() { $formId = intval($_REQUEST['form_id']); $submissionId = intval($_REQUEST['submission_id']); $intentId = sanitize_text_field($_REQUEST['payment_intent_id']); $this->setSubmissionId($submissionId); $this->form = $this->getForm(); $submission = $this->getSubmission(); // Let's retrieve the intent $intent = SCA::retrievePaymentIntent($intentId, [ 'expand' => [ 'invoice.payment_intent' ] ], $formId); if (is_wp_error($intent)) { $this->handlePaymentChargeError($intent->get_error_message(), $submission, false, false, 'payment_intent'); } $invoice = $intent->invoice; $this->handlePaidSubscriptionInvoice($invoice, $submission); } protected function sendSuccess($submission) { try { $returnData = $this->getReturnData(); wp_send_json_success($returnData, 200); } catch (\Exception $e) { wp_send_json([ 'errors' => $e->getMessage() ], 423); } } protected function processScaBeforeVerification($formId, $submissionId, $transactionId, $chargeId) { if ($transactionId) { $this->updateTransaction($transactionId, [ 'charge_id' => $chargeId, 'payment_mode' => $this->getPaymentMode() ]); $this->changeTransactionStatus($transactionId, 'intended'); } $logData = [ 'parent_source_id' => $formId, 'source_type' => 'submission_item', 'source_id' => $submissionId, 'component' => 'Payment', 'status' => 'info', 'title' => __('Stripe SCA Required', 'fluentformpro'), 'description' => __('SCA is required for this payment. Requested SCA info from customer', 'fluentformpro') ]; do_action('fluentform/log_data', $logData); } /** * Products name comma separated * @return string */ public function getProductNames() { $orderItems = $this->getOrderItems(); $itemsHtml = ''; foreach ($orderItems as $item) { $itemsHtml != "" && $itemsHtml .= ", "; $itemsHtml .= $item->item_name ; } return $itemsHtml; } } PK!7w4src/Payments/PaymentMethods/Stripe/ConnectConfig.phpnu[ rawurlencode(admin_url('admin.php?page=fluent_forms_settings&component=payment_settings')), 'mode' => 'live', 'hash' => $hash ]; $testArgs = [ 'url_base' => rawurlencode(admin_url('admin.php?page=fluent_forms_settings&component=payment_settings')), 'mode' => 'test', 'hash' => $hash ]; $settings = StripeSettings::getSettings(); $data = [ 'connect_config' => [ 'live_redirect' => add_query_arg($liveArgs, $configBase), 'test_redirect' => add_query_arg($testArgs, $configBase), 'image_url' => FLUENTFORMPRO_DIR_URL . 'public/images/stripe-connect.png', ], 'test_account' => self::getAccountInfo($settings, 'test'), 'live_account' => self::getAccountInfo($settings, 'live') ]; if ($settings['test_secret_key']) { $settings['test_secret_key'] = 'ENCRYPTED_KEY'; } if ($settings['live_secret_key']) { $settings['live_secret_key'] = 'ENCRYPTED_KEY'; } $data['settings'] = $settings; return $data; } public static function verifyAuthorizeSuccess($data) { $response = wp_remote_post(self::$connectBase . 'stripe-verify-code', [ 'method' => 'POST', 'timeout' => 45, 'redirection' => 5, 'httpversion' => '1.0', 'sslverify' => false, 'blocking' => true, 'headers' => array(), 'body' => $data, 'cookies' => array() ]); if (is_wp_error($response)) { $message = $response->get_error_message(); echo '
    ' . $message . '
    '; return; } $response = json_decode(wp_remote_retrieve_body($response), true); if (empty($response['stripe_user_id'])) { $message = ArrayHelper::get($response, 'message'); if (!$message) { $message = __('Invalid Stripe Request. Please configure stripe payment gateway again', 'fluentformpro'); } echo '
    ' . $message . '
    '; return; } $settings = StripeSettings::getSettings(); $settings['provider'] = 'connect'; $settings['is_active'] = 'yes'; if (!empty($response['livemode'])) { $settings['payment_mode'] = 'live'; $settings['live_account_id'] = $response['stripe_user_id']; $settings['live_publishable_key'] = $response['stripe_publishable_key']; $settings['live_secret_key'] = $response['access_token']; } else { $settings['payment_mode'] = 'test'; $settings['test_account_id'] = $response['stripe_user_id']; $settings['test_publishable_key'] = $response['stripe_publishable_key']; $settings['test_secret_key'] = $response['access_token']; } StripeSettings::updateSettings($settings); ?> $account->get_error_message() ]; } // Find the email. $email = isset($account->email) ? esc_html($account->email) : ''; // Find a Display Name. $display_name = isset($account->display_name) ? esc_html($account->display_name) : ''; if ( empty($display_name) && isset($account->settings) && isset($account->settings->dashboard) && isset($account->settings->dashboard->display_name) ) { $display_name = esc_html($account->settings->dashboard->display_name); } if (empty($display_name)) { return [ 'error' => __('Unable to find connected display name', 'fluentformpro') ]; } return [ 'account_id' => $accountId, 'display_name' => $display_name, 'email' => $email ]; } public static function disconnect($data, $sendResponse = false) { $mode = ArrayHelper::get($data, 'mode'); $stripeSettings = StripeSettings::getSettings(); if($stripeSettings['is_active'] != 'yes') { if($sendResponse) { wp_send_json_error([ 'message' => __('Stripe mode is not active', 'fluentformpro') ], 423); } return false; } if(empty($stripeSettings[$mode.'_account_id'])) { if($sendResponse) { wp_send_json_error([ 'message' => __('Selected Account does not exist', 'fluentformpro') ], 423); } return false; } $stripeSettings[$mode.'_account_id'] = ''; $stripeSettings[$mode.'_publishable_key'] = ''; $stripeSettings[$mode.'_secret_key'] = ''; if($mode == 'live') { $alternateMode = 'test'; } else { $alternateMode = 'live'; } if(empty($stripeSettings[$alternateMode.'_account_id'])) { $stripeSettings['is_active'] = 'no'; $stripeSettings['payment_mode'] = 'test'; } else { $stripeSettings['payment_mode'] = $alternateMode; } StripeSettings::updateSettings($stripeSettings); if($sendResponse) { wp_send_json_success([ 'message' => __('Stripe settings has been disconnected', 'fluentformpro'), 'settings' => $stripeSettings ], 200); } return true; } } PK!-src/Payments/PaymentMethods/BaseProcessor.phpnu[method, array($this, 'handlePaymentAction'), 10, 6); } public abstract function handlePaymentAction($submissionId, $submissionData, $form, $methodSettings, $hasSubscriptions, $totalPayable); public function setSubmissionId($submissionId) { $this->submissionId = $submissionId; } public function getSubmissionId() { return $this->submissionId; } public function insertTransaction($data) { if (empty($data['transaction_type'])) { $data['transaction_type'] = 'onetime'; } $data = wp_parse_args($data, $this->getTransactionDefaults()); if (empty($data['transaction_hash'])) { $data['transaction_hash'] = md5($data['transaction_type'] . '_payment_' . $data['submission_id'] . '-' . $data['form_id'] . '_' . $data['created_at'] . '-' . time() . '-' . mt_rand(100, 999)); } return wpFluent()->table('fluentform_transactions')->insertGetId($data); } public function insertRefund($data) { $submission = $this->getSubmission(); $data['created_at'] = current_time('mysql'); $data['updated_at'] = current_time('mysql'); $data['form_id'] = $submission->form_id; $data['submission_id'] = $submission->id; $data['payment_method'] = $this->method; if (empty($data['transaction_type'])) { $data['transaction_type'] = 'refund'; } if ($userId = get_current_user_id()) { $data['user_id'] = $userId; } if (empty($data['transaction_hash'])) { $data['transaction_hash'] = md5($data['transaction_type'] . '_payment_' . $data['submission_id'] . '-' . $data['form_id'] . '_' . $data['created_at'] . '-' . time() . '-' . mt_rand(100, 999)); } return wpFluent()->table('fluentform_transactions')->insertGetId($data); } public function getTransaction($transactionId, $column = 'id') { return wpFluent()->table('fluentform_transactions') ->where($column, $transactionId) ->first(); } public function getRefund($refundId, $column = 'id') { return wpFluent()->table('fluentform_transactions') ->where($column, $refundId) ->where('transaction_type', 'refund') ->first(); } public function getTransactionByChargeId($chargeId) { return wpFluent()->table('fluentform_transactions') ->where('submission_id', $this->submissionId) ->where('charge_id', $chargeId) ->first(); } public function getLastTransaction($submissionId) { return wpFluent()->table('fluentform_transactions') ->where('submission_id', $submissionId) ->orderBy('id', 'DESC') ->first(); } public function changeSubmissionPaymentStatus($newStatus) { do_action_deprecated( 'fluentform_before_payment_status_change', [ $newStatus, $this->getSubmission() ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/before_payment_status_change', 'Use fluentform/before_payment_status_change instead of fluentform_before_payment_status_change.' ); do_action('fluentform/before_payment_status_change', $newStatus, $this->getSubmission()); wpFluent()->table('fluentform_submissions') ->where('id', $this->submissionId) ->update([ 'payment_status' => $newStatus, 'updated_at' => current_time('mysql') ]); $this->submission = null; $logData = [ 'parent_source_id' => $this->getForm()->id, 'source_type' => 'submission_item', 'source_id' => $this->submissionId, 'component' => 'Payment', 'status' => 'paid' === $newStatus ? 'success' : $newStatus, 'title' => __('Payment Status changed', 'fluentformpro'), 'description' => __('Payment status changed to ', 'fluentformpro') . $newStatus ]; do_action('fluentform/log_data', $logData); do_action_deprecated( 'fluentform_after_payment_status_change', [ $newStatus, $this->getSubmission() ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/after_payment_status_change', 'Use fluentform/after_payment_status_change instead of fluentform_after_payment_status_change.' ); do_action('fluentform/after_payment_status_change', $newStatus, $this->getSubmission()); return true; } public function recalculatePaidTotal() { $transactions = wpFluent()->table('fluentform_transactions') ->where('submission_id', $this->submissionId) ->whereIn('status', ['paid', 'requires_capture', 'processing', 'partially-refunded', 'refunded']) ->get(); $total = 0; $subscriptionId = false; $subBillCount = 0; foreach ($transactions as $transaction) { $total += $transaction->payment_total; if($transaction->subscription_id) { $subscriptionId = $transaction->subscription_id; $subBillCount += 1; } } $refunds = $this->getRefundTotal(); if ($refunds) { $total = $total - $refunds; } wpFluent()->table('fluentform_submissions') ->where('id', $this->submissionId) ->update([ 'total_paid' => $total, 'updated_at' => current_time('mysql') ]); if($subscriptionId && $subBillCount) { $this->updateSubscription($subscriptionId, [ 'bill_count' => $subBillCount ]); } } public function getRefundTotal() { $refunds = wpFluent()->table('fluentform_transactions') ->where('submission_id', $this->submissionId) ->where('transaction_type', 'refund') ->get(); $total = 0; if ($refunds) { foreach ($refunds as $refund) { $total += $refund->payment_total; } } return $total; } public function changeTransactionStatus($transactionId, $newStatus) { do_action_deprecated( 'fluentform_before_transaction_status_change', [ $newStatus, $this->getSubmission(), $transactionId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/before_transaction_status_change', 'Use fluentform/before_transaction_status_change instead of fluentform_before_transaction_status_change.' ); do_action( 'fluentform/before_transaction_status_change', $newStatus, $this->getSubmission(), $transactionId ); wpFluent()->table('fluentform_transactions') ->where('id', $transactionId) ->update([ 'status' => $newStatus, 'updated_at' => current_time('mysql') ]); do_action_deprecated( 'fluentform_after_transaction_status_change', [ $newStatus, $this->getSubmission(), $transactionId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/after_transaction_status_change', 'Use fluentform/after_transaction_status_change instead of fluentform_after_transaction_status_change.' ); do_action( 'fluentform/after_transaction_status_change', $newStatus, $this->getSubmission(), $transactionId ); return true; } public function updateTransaction($transactionId, $data) { $data['updated_at'] = current_time('mysql'); return wpFluent()->table('fluentform_transactions') ->where('id', $transactionId) ->update($data); } public function completePaymentSubmission($isAjax = true) { $returnData = $this->getReturnData(); if ($isAjax) { wp_send_json_success($returnData, 200); } return $returnData; } public function getReturnData() { $submission = $this->getSubmission(); try { $submissionService = new SubmissionHandlerService(); if ($this->getMetaData('is_form_action_fired') == 'yes') { $data = $submissionService->getReturnData($submission->id, $this->getForm(), $submission->response); $returnData = [ 'insert_id' => $submission->id, 'result' => $data, 'error' => '' ]; if (!isset($_REQUEST['fluentform_payment_api_notify'])) { // now we have to check if we need this user as auto login if ($loginId = $this->getMetaData('_make_auto_login')) { $this->maybeAutoLogin($loginId, $submission); } } } else { $returnData = $submissionService->processSubmissionData( $this->submissionId, $submission->response, $this->getForm() ); $this->setMetaData('is_form_action_fired', 'yes'); } return $returnData; } catch (\Exception $e) { return [ 'insert_id' => $submission->id, 'result' => '', 'error' => $e->getMessage(), ]; } } public function getSubmission() { if (!is_null($this->submission)) { return $this->submission; } $submission = wpFluent()->table('fluentform_submissions') ->where('id', $this->submissionId) ->first(); if (!$submission) { return false; } $submission->response = json_decode($submission->response, true); $this->submission = $submission; return $this->submission; } public function getForm() { if (!is_null($this->form)) { return $this->form; } $submission = $this->getSubmission(); $this->form = wpFluent()->table('fluentform_forms') ->where('id', $submission->form_id) ->first(); return $this->form; } public function getOrderItems() { return wpFluent()->table('fluentform_order_items') ->where('submission_id', $this->submissionId) ->where('type', '!=', 'discount') // type = single, signup_fee ->get(); } public function getDiscountItems() { return wpFluent()->table('fluentform_order_items') ->where('submission_id', $this->submissionId) ->where('type', 'discount') ->get(); } public function setMetaData($name, $value) { $value = maybe_serialize($value); return wpFluent()->table('fluentform_submission_meta') ->insertGetId([ 'response_id' => $this->getSubmissionId(), 'form_id' => $this->getForm()->id, 'meta_key' => $name, 'value' => $value, 'created_at' => current_time('mysql'), 'updated_at' => current_time('mysql') ]); } public function deleteMetaData($name) { return wpFluent()->table('fluentform_submission_meta') ->where('meta_key', $name) ->where('response_id', $this->getSubmissionId()) ->delete(); } public function getMetaData($metaKey) { $meta = wpFluent()->table('fluentform_submission_meta') ->where('response_id', $this->getSubmissionId()) ->where('meta_key', $metaKey) ->first(); if ($meta && $meta->value) { return maybe_unserialize($meta->value); } return false; } public function showPaymentView($returnData) { $redirectUrl = ArrayHelper::get($returnData, 'result.redirectUrl'); if ($redirectUrl) { wp_redirect($redirectUrl); exit(); } $form = $this->getForm(); if (!empty($returnData['title'])) { $title = $returnData['title']; } else if ($returnData['type'] == 'success') { $title = __('Payment Success', 'fluentformpro'); } else { $title = __('Payment Failed', 'fluentformpro'); } $message = $returnData['error']; if (!$message) { $message = $returnData['result']['message']; } $data = [ 'status' => $returnData['type'], 'form' => $form, 'title' => $title, 'submission' => $this->getSubmission(), 'message' => $message, 'is_new' => $returnData['is_new'], 'data' => $returnData ]; $data = apply_filters_deprecated( 'fluentform_frameless_page_data', [ $data ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/frameless_page_data', 'Use fluentform/frameless_page_data instead of fluentform_frameless_page_data.' ); $data = apply_filters('fluentform/frameless_page_data', $data); add_filter('pre_get_document_title', function ($title) use ($data) { return $data['title'] . ' ' . apply_filters('document_title_separator', '-') . ' ' . $data['form']->title; }); add_action('wp_enqueue_scripts', function () { wp_enqueue_style('fluent-form-landing', FLUENTFORMPRO_DIR_URL . 'public/css/frameless.css', [], FLUENTFORMPRO_VERSION); }); status_header(200); echo $this->loadView('frameless_view', $data); exit(200); } public function loadView($view, $data = []) { $file = FLUENTFORMPRO_DIR_PATH . 'src/views/' . $view . '.php'; extract($data); ob_start(); include($file); return ob_get_clean(); } public function refund($refund_amount, $transaction, $submission, $method = '', $refundId = '', $refundNote = 'Refunded') { $this->setSubmissionId($submission->id); $status = 'refunded'; $alreadyRefunded = $this->getRefundTotal(); $totalRefund = intval($refund_amount + $alreadyRefunded); if ($totalRefund < $transaction->payment_total) { $status = 'partially-refunded'; } $this->changeTransactionStatus($transaction->id, $status); $this->changeSubmissionPaymentStatus($status); $uniqueHash = md5('refund_' . $submission->id . '-' . $submission->form_id . '-' . time() . '-' . mt_rand(100, 999)); $refundData = [ 'form_id' => $submission->form_id, 'submission_id' => $submission->id, 'transaction_hash' => $uniqueHash, 'payment_method' => $transaction->payment_method, 'charge_id' => $refundId, 'payment_note' => $refundNote, 'payment_total' => $refund_amount, 'currency' => $transaction->currency, 'payment_mode' => $transaction->payment_mode, 'created_at' => current_time('mysql'), 'updated_at' => current_time('mysql'), 'status' => 'refunded', 'transaction_type' => 'refund' ]; $refundId = $this->insertRefund($refundData); $logData = [ 'parent_source_id' => $submission->form_id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'Payment', 'status' => 'info', 'title' => __('Refund issued', 'fluentformpro'), 'description' => __('Refund issued and refund amount: ', 'fluentformpro') . number_format($refund_amount / 100, 2) ]; do_action('fluentform/log_data', $logData); $this->recalculatePaidTotal(); $refund = $this->getRefund($refundId); do_action_deprecated( 'fluentform_payment_' . $status . '_' . $method, [ $refund, $transaction, $submission ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_' . $status . '_' . $method, 'Use fluentform/payment_' . $status . '_' . $method . ' instead of fluentform_payment_' . $status . '_' . $method ); do_action('fluentform/payment_' . $status . '_' . $method, $refund, $transaction, $submission); do_action_deprecated( 'fluentform_payment_' . $status, [ $refund, $transaction, $submission ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_' . $status, 'Use fluentform/payment_' . $status . ' instead of fluentform_payment_' . $status ); do_action('fluentform/payment_' . $status, $refund, $transaction, $submission); } public function updateRefund($totalRefund, $transaction, $submission, $method = '', $refundId = '', $refundNote = 'Refunded') { if(!$totalRefund) { return; } $this->setSubmissionId($submission->id); $existingRefund = wpFluent()->table('fluentform_transactions') ->where('submission_id', $submission->id) ->where('transaction_type', 'refund') ->first(); if ($existingRefund) { if ($existingRefund->payment_total == $totalRefund) { return; } $status = 'refunded'; if ($totalRefund < $transaction->payment_total) { $status = 'partially-refunded'; } $updateData = [ 'form_id' => $submission->form_id, 'submission_id' => $submission->id, 'payment_method' => $transaction->payment_method, 'charge_id' => $refundId, 'payment_note' => $refundNote, 'payment_total' => $totalRefund, 'payment_mode' => $transaction->payment_mode, 'created_at' => current_time('mysql'), 'updated_at' => current_time('mysql'), 'status' => 'refunded', 'transaction_type' => 'refund' ]; wpFluent()->table('fluentform_transactions')->where('id', $existingRefund->id) ->update($updateData); $existingRefund = wpFluent()->table('fluentform_transactions') ->where('submission_id', $submission->id) ->where('transaction_type', 'refund') ->first(); if ($transaction->status != $status) { $this->changeTransactionStatus($transaction->id, $status); } do_action_deprecated( 'fluentform_payment_refund_updated_' . $method, [ $existingRefund, $existingRefund->form_id ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_refund_updated_' . $method, 'Use fluentform/payment_refund_updated_' . $method . ' instead of fluentform_payment_refund_updated_' . $method ); do_action('fluentform/payment_refund_updated_' . $method, $existingRefund, $existingRefund->form_id); do_action_deprecated( 'fluentform_payment_refund_updated', [ $existingRefund, $existingRefund->form_id ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_refund_updated', 'Use fluentform/payment_refund_updated instead of fluentform_payment_refund_updated.' ); do_action('fluentform/payment_refund_updated', $existingRefund, $existingRefund->form_id); } else { $this->refund($totalRefund, $transaction, $submission, $method, $refundId, $refundNote); } } private function maybeAutoLogin($loginId, $submission) { if (is_user_logged_in() || !$loginId) { return; } if ($loginId != $submission->user_id) { return; } wp_clear_auth_cookie(); wp_set_current_user($loginId); wp_set_auth_cookie($loginId); $this->deleteMetaData('_make_auto_login'); } public function getAmountTotal() { $orderItems = $this->getOrderItems(); $amountTotal = 0; foreach ($orderItems as $item) { $amountTotal += $item->line_total; } $discountItems = $this->getDiscountItems(); foreach ($discountItems as $discountItem) { $amountTotal -= $discountItem->line_total; } return $amountTotal; } public function handleSessionRedirectBack($data) { $submissionId = intval($data['fluentform_payment']); $this->setSubmissionId($submissionId); $submission = $this->getSubmission(); $transactionHash = sanitize_text_field($data['transaction_hash']); $transaction = $this->getTransaction($transactionHash, 'transaction_hash'); if (!$transaction || !$submission) { return; } $type = $transaction->status; $form = $this->getForm(); if ($type == 'paid') { $returnData = $this->getReturnData(); } else { $returnData = [ 'insert_id' => $submission->id, 'title' => __('Payment was not marked as paid', 'fluentformpro'), 'result' => false, 'error' => __('Looks like you have is still on pending status', 'fluentformpro') ]; } $returnData['type'] = 'success'; $returnData['is_new'] = false; $this->showPaymentView($returnData); } public function getSubscriptions($status = false) { $subscriptions = wpFluent()->table('fluentform_subscriptions') ->where('submission_id', $this->submissionId) ->when($status, function ($q) use ($status) { $q->where('status', $status); }) ->get(); foreach ($subscriptions as $subscription) { $subscription->original_plan = maybe_unserialize($subscription->original_plan); $subscription->vendor_response = maybe_unserialize($subscription->vendor_response); } return $subscriptions; } public function updateSubscription($id, $data) { $data['updated_at'] = current_time('mysql'); return wpFluent()->table('fluentform_subscriptions') ->where('id', $id) ->update($data); } public function maybeInsertSubscriptionCharge($item) { $exists = wpFluent()->table('fluentform_transactions') ->where('transaction_type', 'subscription') ->where('submission_id', $item['submission_id']) ->where('subscription_id', $item['subscription_id']) ->where('charge_id', $item['charge_id']) ->where('payment_method', $item['payment_method']) ->first(); $isNew = false; if ($exists) { // We don't want to update the address and payer email that we already have here if ($exists->billing_address) { unset($item['billing_address']); } if ($exists->payer_email) { unset($item['payer_email']); } unset($item['transaction_hash']); unset($item['created_at']); wpFluent()->table('fluentform_transactions') ->where('id', $exists->id) ->update($item); $id = $exists->id; } else { if (empty($item['created_at'])) { $item['created_at'] = current_time('mysql'); $item['updated_at'] = current_time('mysql'); } if (empty($item['transaction_hash'])) { $uniqueHash = md5('subscription_payment_' . $item['submission_id'] . '-' . $item['charge_id'] . '-' . time() . '-' . mt_rand(100, 999)); $item['transaction_hash'] = $uniqueHash; } $id = wpFluent()->table('fluentform_transactions')->insertGetId($item); $isNew = true; } $transaction = fluentFormApi('submissions')->transaction($id); // We want to update the total amount here $parentSubscription = wpFluent()->table('fluentform_subscriptions') ->where('id', $transaction->subscription_id) ->first(); // Let's count the total subscription payment if ($parentSubscription) { list($billCount, $paymentTotal) = $this->getPaymentCountsAndTotal($parentSubscription->id); wpFluent()->table('fluentform_subscriptions') ->where('id', $parentSubscription->id) ->update([ 'bill_count' => $billCount, 'payment_total' => $paymentTotal, 'updated_at' => current_time('mysql') ]); wpFluent()->table('fluentform_submissions')->where('id', $parentSubscription->submission_id) ->update([ 'payment_total' => $paymentTotal, 'total_paid' => $paymentTotal, ]); $subscription = wpFluent()->table('fluentform_subscriptions') ->where('id', $parentSubscription->id) ->first(); if($isNew) { $submission = $this->getSubmission(); do_action_deprecated( 'fluentform_subscription_received_payment', [ $subscription, $submission ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/subscription_received_payment', 'Use fluentform/subscription_received_payment instead of fluentform_subscription_received_payment.' ); do_action('fluentform/subscription_received_payment', $subscription, $submission); do_action_deprecated( 'fluentform_subscription_received_payment_' . $submission->payment_method, [ $subscription, $submission ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/subscription_received_payment_' . $submission->payment_method, 'Use fluentform/subscription_received_payment_' . $submission->payment_method . ' instead of fluentform_subscription_received_payment_' . $submission->payment_method ); do_action('fluentform/subscription_received_payment_' . $submission->payment_method, $subscription, $submission); } if($subscription->bill_times >= $subscription->bill_count) { // We have to mark the subscription as completed $this->updateSubscriptionStatus($subscription, 'completed'); } } return $id; } public function getPaymentCountsAndTotal($subscriptionId, $paymentMethod = false) { $payments = wpFluent() ->table('fluentform_transactions') ->select(['id', 'payment_total']) ->where('transaction_type', 'subscription') ->where('subscription_id', $subscriptionId) ->when($paymentMethod, function ($q) use ($paymentMethod) { $q->where('payment_method', $paymentMethod); }) ->get(); $paymentTotal = 0; foreach ($payments as $payment) { $paymentTotal += $payment->payment_total; } return [count($payments), $paymentTotal]; } protected function getCancelAtTimeStamp($subscription) { if (!$subscription->bill_times) { return false; } $dateTime = current_datetime(); $localtime = $dateTime->getTimestamp() + $dateTime->getOffset(); $billingStartDate = $localtime; if ($subscription->expiration_at) { $billingStartDate = strtotime($subscription->expiration_at); } $billTimes = $subscription->bill_times; $interval = $subscription->billing_interval; $interValMaps = [ 'day' => 'days', 'week' => 'weeks', 'month' => 'months', 'year' => 'years' ]; if (isset($interValMaps[$interval]) && $billTimes > 1) { $interval = $interValMaps[$interval]; } return strtotime('+ ' . $billTimes . ' ' . $interval, $billingStartDate); } public function updateSubmission($id, $data) { $data['updated_at'] = current_time('mysql'); return wpFluent()->table('fluentform_submissions') ->where('id', $id) ->update($data); } public function limitLength($string, $limit = 127) { $str_limit = $limit - 3; if (function_exists('mb_strimwidth')) { if (mb_strlen($string) > $limit) { $string = mb_strimwidth($string, 0, $str_limit) . '...'; } } else { if (strlen($string) > $limit) { $string = substr($string, 0, $str_limit) . '...'; } } return $string; } public function getTransactionDefaults() { $submission = $this->getSubmission(); if (!$submission) { return []; } $data = []; if ($customerEmail = PaymentHelper::getCustomerEmail($submission, $this->getForm())) { $data['payer_email'] = $customerEmail; } if ($customerName = PaymentHelper::getCustomerName($submission, $this->getForm())) { $data['payer_name'] = $customerName; } if ($submission->user_id) { $data['user_id'] = $submission->user_id; } else if ($user = get_user_by('ID', get_current_user_id())) { $data['user_id'] = $user->ID; } if (!$submission->user_id && !empty($data['payer_email'])) { $email = $data['payer_email']; $maybeUser = get_user_by('email', $email); if ($maybeUser) { $this->updateSubmission($submission->id, [ 'user_id' => $maybeUser->ID ]); if (empty($data['user_id'])) { $data['user_id'] = $maybeUser->ID; } } } $address = PaymentHelper::getCustomerAddress($submission); if (!$address) { $address = ArrayHelper::get($submission->response, 'address_1'); } if ($address) { $address = array_filter($address); if ($address) { $data['billing_address'] = implode(', ', $address); } } $data['created_at'] = current_time('mysql'); $data['updated_at'] = current_time('mysql'); $data['form_id'] = $submission->form_id; $data['submission_id'] = $submission->id; $data['payment_method'] = $this->method; return $data; } public function createInitialPendingTransaction($submission = false, $hasSubscriptions = false) { if (!$submission) { $submission = $this->getSubmission(); } $form = $this->getForm(); $uniqueHash = md5($submission->id . '-' . $form->id . '-' . time() . '-' . mt_rand(100, 999)); $transactionData = [ 'transaction_type' => 'onetime', 'transaction_hash' => $uniqueHash, 'payment_total' => $this->getAmountTotal(), 'status' => 'pending', 'currency' => strtoupper($submission->currency), 'payment_mode' => $this->getPaymentMode() ]; if ($hasSubscriptions) { $subscriptions = $this->getSubscriptions(); if ($subscriptions) { $subscriptionInitialTotal = 0; foreach ($subscriptions as $subscription) { if (!$subscription->trial_days) { $subscriptionInitialTotal += $subscription->recurring_amount; } if ($subscription->initial_amount) { $subscriptionInitialTotal += $subscription->initial_amount; } $transactionData['subscription_id'] = $subscription->id; } $transactionData['payment_total'] += $subscriptionInitialTotal; $transactionData['transaction_type'] = 'subscription'; } } $transactionId = $this->insertTransaction($transactionData); $this->updateSubmission($submission->id, [ 'payment_total' => $transactionData['payment_total'] ]); return $this->getTransaction($transactionId); } /** * @param object $subscription * @param string $newStatus * @param string $note * @return object */ public function updateSubscriptionStatus($subscription, $newStatus, $note = '') { if(!$note) { $note = __('Subscription status has been changed to '.$newStatus.' from '.$subscription->status, 'fluentformpro'); } $oldStatus = $subscription->status; if($oldStatus == $newStatus) { return $subscription; } wpFluent()->table('fluentform_subscriptions') ->where('id', $subscription->id) ->update([ 'status' => $newStatus, 'updated_at' => current_time('mysql') ]); $logData = [ 'parent_source_id' => $this->getForm()->id, 'source_type' => 'submission_item', 'source_id' => $this->submissionId, 'component' => 'Payment', 'status' => 'info', 'title' => __('Subscription Status changed to ', 'fluentformpro') . $newStatus, 'description' => $note ]; do_action('fluentform/log_data', $logData); $subscription->status = $newStatus; $submission = $this->getSubmission(); do_action_deprecated( 'fluentform_subscription_payment_' . $newStatus, [ $subscription, $submission, false ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/subscription_payment_' . $newStatus, 'Use fluentform/subscription_payment_' . $newStatus . ' instead of fluentform_subscription_payment_' . $newStatus ); do_action('fluentform/subscription_payment_' . $newStatus, $subscription, $submission, false); do_action_deprecated( 'fluentform_subscription_payment_' . $newStatus . '_' . $submission->payment_method, [ $subscription, $submission, false ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/subscription_payment_' . $newStatus . '_' . $submission->payment_method, 'Use fluentform/subscription_payment_' . $newStatus . '_' . $submission->payment_method . ' instead of fluentform_subscription_payment_' . $newStatus . '_' . $submission->payment_method ); do_action('fluentform/subscription_payment_' . $newStatus . '_' . $submission->payment_method, $subscription, $submission, false); return $subscription; } } PK!FGX@@1src/Payments/PaymentMethods/BasePaymentMethod.phpnu[key = $key; $this->settingsKey = 'fluentform_payment_settings_'.$key; add_filter('fluentform/payment_methods_global_settings', function ($methods) { $fields = $this->getGlobalFields(); if($fields) { $methods[$this->key] = $fields; } return $methods; }); add_filter('fluentform/payment_settings_' . $this->key, array($this, 'getGlobalSettings')); } abstract public function getGlobalFields(); abstract public function getGlobalSettings(); }PK!=īīsrc/Payments/PaymentHelper.phpnu[ '', 'push_meta_to_stripe' => 'no', 'receipt_email' => self::getFormInput($formId,'input_email'), 'customer_name' => self::getFormInput($formId,'input_name'), 'customer_address' => self::getFormInput($formId,'address'), 'transaction_type' => 'product', 'stripe_checkout_methods' => ['card'], 'stripe_meta_data' => [ [ 'item_value' => '', 'label' => '' ] ], 'stripe_account_type' => 'global', 'disable_stripe_payment_receipt' => 'no', 'stripe_custom_config' => [ 'payment_mode' => 'live', 'publishable_key' => '', 'secret_key' => '' ], 'custom_paypal_id' => '', 'custom_paypal_mode' => 'live', 'paypal_account_type' => 'global' ]; $settings = Helper::getFormMeta($formId, '_payment_settings', []); $settings = wp_parse_args($settings, $defaults); if (empty($settings['receipt_email'])) { $settings['receipt_email'] = self::getFormInput($formId, 'input_email'); } if (empty($settings['customer_name'])) { $name = self::getFormInput($formId, 'input_name'); if (!empty($name)) { $settings['customer_name'] = sprintf('{inputs.%s}', $name); } } if (empty($settings['customer_address'])) { $settings['customer_address'] = self::getFormInput($formId, 'address'); } $globalSettings = self::getPaymentSettings(); if (!$settings['currency']) { $settings['currency'] = $globalSettings['currency']; } if ($scope == 'public') { $settings = wp_parse_args($settings, $globalSettings); } $cachedSettings[$scope . '_' . $formId] = $settings; return $settings; } public static function getCurrencyConfig($formId = false, $currency = false) { if ($formId) { $settings = self::getFormSettings($formId, 'public'); } else { $settings = self::getPaymentSettings(); } if ($currency) { $settings['currency'] = $currency; } $settings = ArrayHelper::only($settings, ['currency', 'currency_sign_position', 'currency_separator', 'decimal_points']); $settings['currency_sign'] = self::getCurrencySymbol($settings['currency']); return $settings; } public static function getPaymentSettings() { static $paymentSettings; if ($paymentSettings) { return $paymentSettings; } $paymentSettings = get_option('__fluentform_payment_module_settings'); $defaults = [ 'status' => 'no', 'currency' => 'USD', 'currency_sign_position' => 'left', 'currency_separator' => 'dot_comma', 'decimal_points' => "2", 'business_name' => '', 'business_logo' => '', 'business_address' => '', 'debug_log' => 'no', 'all_payments_page_id' => '', 'receipt_page_id' => '', 'user_can_manage_subscription' => 'yes' ]; $paymentSettings = wp_parse_args($paymentSettings, $defaults); return $paymentSettings; } public static function updatePaymentSettings($data) { $existingSettings = self::getPaymentSettings(); $settings = wp_parse_args($data, $existingSettings); update_option('__fluentform_payment_module_settings', $settings, 'yes'); return self::getPaymentSettings(); } /** * https://support.stripe.com/questions/which-currencies-does-stripe-support */ public static function getCurrencies() { $currencies = [ 'AED' => __('United Arab Emirates Dirham', 'fluentformpro'), 'AFN' => __('Afghan Afghani', 'fluentformpro'), 'ALL' => __('Albanian Lek', 'fluentformpro'), 'AMD' => __('Armenian Dram', 'fluentformpro'), 'ANG' => __('Netherlands Antillean Gulden', 'fluentformpro'), 'AOA' => __('Angolan Kwanza', 'fluentformpro'), 'ARS' => __('Argentine Peso','fluentformpro'), // non amex 'AUD' => __('Australian Dollar', 'fluentformpro'), 'AWG' => __('Aruban Florin', 'fluentformpro'), 'AZN' => __('Azerbaijani Manat', 'fluentformpro'), 'BAM' => __('Bosnia & Herzegovina Convertible Mark', 'fluentformpro'), 'BBD' => __('Barbadian Dollar', 'fluentformpro'), 'BDT' => __('Bangladeshi Taka', 'fluentformpro'), 'BIF' => __('Burundian Franc', 'fluentformpro'), 'BGN' => __('Bulgarian Lev', 'fluentformpro'), 'BMD' => __('Bermudian Dollar', 'fluentformpro'), 'BND' => __('Brunei Dollar', 'fluentformpro'), 'BOB' => __('Bolivian Boliviano', 'fluentformpro'), 'BRL' => __('Brazilian Real', 'fluentformpro'), 'BSD' => __('Bahamian Dollar', 'fluentformpro'), 'BWP' => __('Botswana Pula', 'fluentformpro'), 'BZD' => __('Belize Dollar', 'fluentformpro'), 'CAD' => __('Canadian Dollar', 'fluentformpro'), 'CDF' => __('Congolese Franc', 'fluentformpro'), 'CHF' => __('Swiss Franc', 'fluentformpro'), 'CLP' => __('Chilean Peso', 'fluentformpro'), 'CNY' => __('Chinese Renminbi Yuan', 'fluentformpro'), 'COP' => __('Colombian Peso', 'fluentformpro'), 'CRC' => __('Costa Rican Colón', 'fluentformpro'), 'CVE' => __('Cape Verdean Escudo', 'fluentformpro'), 'CZK' => __('Czech Koruna', 'fluentformpro'), 'DJF' => __('Djiboutian Franc', 'fluentformpro'), 'DKK' => __('Danish Krone', 'fluentformpro'), 'DOP' => __('Dominican Peso', 'fluentformpro'), 'DZD' => __('Algerian Dinar', 'fluentformpro'), 'EGP' => __('Egyptian Pound', 'fluentformpro'), 'ETB' => __('Ethiopian Birr', 'fluentformpro'), 'EUR' => __('Euro', 'fluentformpro'), 'FJD' => __('Fijian Dollar', 'fluentformpro'), 'FKP' => __('Falkland Islands Pound', 'fluentformpro'), 'GBP' => __('British Pound', 'fluentformpro'), 'GEL' => __('Georgian Lari', 'fluentformpro'), 'GHS' => __('Ghanaian Cedi', 'fluentformpro'), 'GIP' => __('Gibraltar Pound', 'fluentformpro'), 'GMD' => __('Gambian Dalasi', 'fluentformpro'), 'GNF' => __('Guinean Franc', 'fluentformpro'), 'GTQ' => __('Guatemalan Quetzal', 'fluentformpro'), 'GYD' => __('Guyanese Dollar', 'fluentformpro'), 'HKD' => __('Hong Kong Dollar', 'fluentformpro'), 'HNL' => __('Honduran Lempira', 'fluentformpro'), 'HRK' => __('Croatian Kuna', 'fluentformpro'), 'HTG' => __('Haitian Gourde', 'fluentformpro'), 'HUF' => __('Hungarian Forint', 'fluentformpro'), 'IDR' => __('Indonesian Rupiah', 'fluentformpro'), 'ILS' => __('Israeli New Sheqel', 'fluentformpro'), 'INR' => __('Indian Rupee', 'fluentformpro'), 'ISK' => __('Icelandic Króna', 'fluentformpro'), 'JMD' => __('Jamaican Dollar', 'fluentformpro'), 'JPY' => __('Japanese Yen', 'fluentformpro'), 'KES' => __('Kenyan Shilling', 'fluentformpro'), 'KGS' => __('Kyrgyzstani Som', 'fluentformpro'), 'KHR' => __('Cambodian Riel', 'fluentformpro'), 'KMF' => __('Comorian Franc', 'fluentformpro'), 'KRW' => __('South Korean Won', 'fluentformpro'), 'KYD' => __('Cayman Islands Dollar', 'fluentformpro'), 'KZT' => __('Kazakhstani Tenge', 'fluentformpro'), 'LAK' => __('Lao Kip', 'fluentformpro'), 'LBP' => __('Lebanese Pound', 'fluentformpro'), 'LKR' => __('Sri Lankan Rupee', 'fluentformpro'), 'LRD' => __('Liberian Dollar', 'fluentformpro'), 'LSL' => __('Lesotho Loti', 'fluentformpro'), 'MAD' => __('Moroccan Dirham', 'fluentformpro'), 'MDL' => __('Moldovan Leu', 'fluentformpro'), 'MGA' => __('Malagasy Ariary', 'fluentformpro'), 'MKD' => __('Macedonian Denar', 'fluentformpro'), 'MNT' => __('Mongolian Tögrög', 'fluentformpro'), 'MOP' => __('Macanese Pataca', 'fluentformpro'), 'MRO' => __('Mauritanian Ouguiya', 'fluentformpro'), 'MUR' => __('Mauritian Rupee', 'fluentformpro'), 'MVR' => __('Maldivian Rufiyaa', 'fluentformpro'), 'MWK' => __('Malawian Kwacha', 'fluentformpro'), 'MXN' => __('Mexican Peso', 'fluentformpro'), 'MYR' => __('Malaysian Ringgit', 'fluentformpro'), 'MZN' => __('Mozambican Metical', 'fluentformpro'), 'NAD' => __('Namibian Dollar', 'fluentformpro'), 'NGN' => __('Nigerian Naira', 'fluentformpro'), 'NIO' => __('Nicaraguan Córdoba', 'fluentformpro'), 'NOK' => __('Norwegian Krone', 'fluentformpro'), 'NPR' => __('Nepalese Rupee', 'fluentformpro'), 'NZD' => __('New Zealand Dollar', 'fluentformpro'), 'PAB' => __('Panamanian Balboa', 'fluentformpro'), 'PEN' => __('Peruvian Nuevo Sol', 'fluentformpro'), 'PGK' => __('Papua New Guinean Kina', 'fluentformpro'), 'PHP' => __('Philippine Peso', 'fluentformpro'), 'PKR' => __('Pakistani Rupee', 'fluentformpro'), 'PLN' => __('Polish Złoty', 'fluentformpro'), 'PYG' => __('Paraguayan Guaraní', 'fluentformpro'), 'QAR' => __('Qatari Riyal', 'fluentformpro'), 'RON' => __('Romanian Leu', 'fluentformpro'), 'RSD' => __('Serbian Dinar', 'fluentformpro'), 'RUB' => __('Russian Ruble', 'fluentformpro'), 'RWF' => __('Rwandan Franc', 'fluentformpro'), 'SAR' => __('Saudi Riyal', 'fluentformpro'), 'SBD' => __('Solomon Islands Dollar', 'fluentformpro'), 'SCR' => __('Seychellois Rupee', 'fluentformpro'), 'SEK' => __('Swedish Krona', 'fluentformpro'), 'SGD' => __('Singapore Dollar', 'fluentformpro'), 'SHP' => __('Saint Helenian Pound', 'fluentformpro'), 'SLL' => __('Sierra Leonean Leone', 'fluentformpro'), 'SOS' => __('Somali Shilling', 'fluentformpro'), 'SRD' => __('Surinamese Dollar', 'fluentformpro'), 'STD' => __('São Tomé and Príncipe Dobra', 'fluentformpro'), 'SVC' => __('Salvadoran Colón', 'fluentformpro'), 'SZL' => __('Swazi Lilangeni', 'fluentformpro'), 'THB' => __('Thai Baht', 'fluentformpro'), 'TJS' => __('Tajikistani Somoni', 'fluentformpro'), 'TOP' => __('Tongan Paʻanga', 'fluentformpro'), 'TRY' => __('Turkish Lira', 'fluentformpro'), 'TTD' => __('Trinidad and Tobago Dollar', 'fluentformpro'), 'TWD' => __('New Taiwan Dollar', 'fluentformpro'), 'TZS' => __('Tanzanian Shilling', 'fluentformpro'), 'UAH' => __('Ukrainian Hryvnia', 'fluentformpro'), 'UGX' => __('Ugandan Shilling', 'fluentformpro'), 'USD' => __('United States Dollar', 'fluentformpro'), 'UYU' => __('Uruguayan Peso', 'fluentformpro'), 'UZS' => __('Uzbekistani Som', 'fluentformpro'), 'VND' => __('Vietnamese Đồng', 'fluentformpro'), 'VUV' => __('Vanuatu Vatu', 'fluentformpro'), 'WST' => __('Samoan Tala', 'fluentformpro'), 'XAF' => __('Central African Cfa Franc', 'fluentformpro'), 'XCD' => __('East Caribbean Dollar', 'fluentformpro'), 'XOF' => __('West African Cfa Franc', 'fluentformpro'), 'XPF' => __('Cfp Franc', 'fluentformpro'), 'YER' => __('Yemeni Rial', 'fluentformpro'), 'ZAR' => __('South African Rand', 'fluentformpro'), 'ZMW' => __('Zambian Kwacha', 'fluentformpro') ]; $currencies = apply_filters_deprecated( 'fluentform_accepted_currencies', [ $currencies ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/accepted_currencies', 'Use fluentform/accepted_currencies instead of fluentform_accepted_currencies.' ); return apply_filters('fluentform/accepted_currencies', $currencies); } /** * Get a specific currency symbol * * https://support.stripe.com/questions/which-currencies-does-stripe-support */ public static function getCurrencySymbol($currency = '') { if (!$currency) { // If no currency is passed then default it to USD $currency = 'USD'; } $currency = strtoupper($currency); $symbols = self::getCurrencySymbols(); $currency_symbol = isset($symbols[$currency]) ? $symbols[$currency] : ''; $currency_symbol = apply_filters_deprecated( 'fluentform_currency_symbol', [ $currency_symbol, $currency ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/currency_symbol', 'Use fluentform/currency_symbol instead of fluentform_currency_symbol.' ); return apply_filters('fluentform/currency_symbol', $currency_symbol, $currency); } public static function getCurrencySymbols() { $symbols = [ 'AED' => 'د.إ', 'AFN' => '؋', 'ALL' => 'L', 'AMD' => 'AMD', 'ANG' => 'ƒ', 'AOA' => 'Kz', 'ARS' => '$', 'AUD' => '$', 'AWG' => 'ƒ', 'AZN' => 'AZN', 'BAM' => 'KM', 'BBD' => '$', 'BDT' => '৳ ', 'BGN' => 'лв.', 'BHD' => '.د.ب', 'BIF' => 'Fr', 'BMD' => '$', 'BND' => '$', 'BOB' => 'Bs.', 'BRL' => 'R$', 'BSD' => '$', 'BTC' => '฿', 'BTN' => 'Nu.', 'BWP' => 'P', 'BYR' => 'Br', 'BZD' => '$', 'CAD' => '$', 'CDF' => 'Fr', 'CHF' => 'CHF', 'CLP' => '$', 'CNY' => '¥', 'COP' => '$', 'CRC' => '₡', 'CUC' => '$', 'CUP' => '$', 'CVE' => '$', 'CZK' => 'Kč', 'DJF' => 'Fr', 'DKK' => 'DKK', 'DOP' => 'RD$', 'DZD' => 'د.ج', 'EGP' => 'EGP', 'ERN' => 'Nfk', 'ETB' => 'Br', 'EUR' => '€', 'FJD' => '$', 'FKP' => '£', 'GBP' => '£', 'GEL' => 'ლ', 'GGP' => '£', 'GHS' => '₵', 'GIP' => '£', 'GMD' => 'D', 'GNF' => 'Fr', 'GTQ' => 'Q', 'GYD' => '$', 'HKD' => '$', 'HNL' => 'L', 'HRK' => 'Kn', 'HTG' => 'G', 'HUF' => 'Ft', 'IDR' => 'Rp', 'ILS' => '₪', 'IMP' => '£', 'INR' => '₹', 'IQD' => 'ع.د', 'IRR' => '﷼', 'ISK' => 'Kr.', 'JEP' => '£', 'JMD' => '$', 'JOD' => 'د.ا', 'JPY' => '¥', 'KES' => 'KSh', 'KGS' => 'лв', 'KHR' => '៛', 'KMF' => 'Fr', 'KPW' => '₩', 'KRW' => '₩', 'KWD' => 'د.ك', 'KYD' => '$', 'KZT' => 'KZT', 'LAK' => '₭', 'LBP' => 'ل.ل', 'LKR' => 'රු', 'LRD' => '$', 'LSL' => 'L', 'LYD' => 'ل.د', 'MAD' => 'د. م.', 'MDL' => 'L', 'MGA' => 'Ar', 'MKD' => 'ден', 'MMK' => 'Ks', 'MNT' => '₮', 'MOP' => 'P', 'MRO' => 'UM', 'MUR' => '₨', 'MVR' => '.ރ', 'MWK' => 'MK', 'MXN' => '$', 'MYR' => 'RM', 'MZN' => 'MT', 'NAD' => '$', 'NGN' => '₦', 'NIO' => 'C$', 'NOK' => 'kr', 'NPR' => '₨', 'NZD' => '$', 'OMR' => 'ر.ع.', 'PAB' => 'B/.', 'PEN' => 'S/.', 'PGK' => 'K', 'PHP' => '₱', 'PKR' => '₨', 'PLN' => 'zł', 'PRB' => 'р.', 'PYG' => '₲', 'QAR' => 'ر.ق', 'RMB' => '¥', 'RON' => 'lei', 'RSD' => 'дин.', 'RUB' => '₽', 'RWF' => 'Fr', 'SAR' => 'ر.س', 'SBD' => '$', 'SCR' => '₨', 'SDG' => 'ج.س.', 'SEK' => 'kr', 'SGD' => '$', 'SHP' => '£', 'SLL' => 'Le', 'SOS' => 'Sh', 'SRD' => '$', 'SSP' => '£', 'STD' => 'Db', 'SYP' => 'ل.س', 'SZL' => 'L', 'THB' => '฿', 'TJS' => 'ЅМ', 'TMT' => 'm', 'TND' => 'د.ت', 'TOP' => 'T$', 'TRY' => '₺', 'TTD' => '$', 'TWD' => 'NT$', 'TZS' => 'Sh', 'UAH' => '₴', 'UGX' => 'UGX', 'USD' => '$', 'UYU' => '$', 'UZS' => 'UZS', 'VEF' => 'Bs F', 'VND' => '₫', 'VUV' => 'Vt', 'WST' => 'T', 'XAF' => 'Fr', 'XCD' => '$', 'XOF' => 'Fr', 'XPF' => 'Fr', 'YER' => '﷼', 'ZAR' => 'R', 'ZMW' => 'ZK', ]; $symbols = apply_filters_deprecated( 'fluentform_currency_symbols', [ $symbols ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/currencies_symbols', 'Use fluentform/currencies_symbols instead of fluentform_currency_symbols.' ); return apply_filters('fluentform/currencies_symbols', $symbols); } public static function zeroDecimalCurrencies() { $zeroDecimalCurrencies = [ 'BIF' => esc_html__('Burundian Franc', 'fluentformpro'), 'CLP' => esc_html__('Chilean Peso', 'fluentformpro'), 'DJF' => esc_html__('Djiboutian Franc', 'fluentformpro'), 'GNF' => esc_html__('Guinean Franc', 'fluentformpro'), 'JPY' => esc_html__('Japanese Yen', 'fluentformpro'), 'KMF' => esc_html__('Comorian Franc', 'fluentformpro'), 'KRW' => esc_html__('South Korean Won', 'fluentformpro'), 'MGA' => esc_html__('Malagasy Ariary', 'fluentformpro'), 'PYG' => esc_html__('Paraguayan Guaraní', 'fluentformpro'), 'RWF' => esc_html__('Rwandan Franc', 'fluentformpro'), 'VND' => esc_html__('Vietnamese Dong', 'fluentformpro'), 'VUV' => esc_html__('Vanuatu Vatu', 'fluentformpro'), 'XAF' => esc_html__('Central African Cfa Franc', 'fluentformpro'), 'XOF' => esc_html__('West African Cfa Franc', 'fluentformpro'), 'XPF' => esc_html__('Cfp Franc', 'fluentformpro'), ]; $zeroDecimalCurrencies = apply_filters_deprecated( 'fluentform_zero_decimal_currencies', [ $zeroDecimalCurrencies ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/zero_decimal_currencies', 'Use fluentform/zero_decimal_currencies instead of fluentform_zero_decimal_currencies.' ); return apply_filters('fluentform/zero_decimal_currencies', $zeroDecimalCurrencies); } public static function isZeroDecimal($currencyCode) { $currencyCode = strtoupper($currencyCode); $zeroDecimals = self::zeroDecimalCurrencies(); return isset($zeroDecimals[$currencyCode]); } public static function getPaymentStatuses() { $paymentStatuses = [ 'paid' => __('Paid', 'fluentformpro'), 'processing' => __('Processing', 'fluentformpro'), 'pending' => __('Pending', 'fluentformpro'), 'failed' => __('Failed', 'fluentformpro'), 'refunded' => __('Refunded', 'fluentformpro'), 'partially-refunded' => __('Partial Refunded', 'fluentformpro'), 'cancelled' => __('Cancelled', 'fluentformpro') ]; $paymentStatuses = apply_filters_deprecated( 'fluentform_available_payment_statuses', [ $paymentStatuses ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/available_payment_statuses', 'Use fluentform/available_payment_statuses instead of fluentform_available_payment_statuses.' ); return apply_filters('fluentform/available_payment_statuses', $paymentStatuses); } public static function getFormPaymentMethods($formId) { $inputs = FormFieldsParser::getInputs($formId, ['element', 'settings']); foreach ($inputs as $field) { if ($field['element'] == 'payment_method') { $methods = ArrayHelper::get($field, 'settings.payment_methods'); if (is_array($methods)) { return array_filter($methods, function ($method) { return $method['enabled'] == 'yes'; }); } } } return []; } public static function getCustomerEmail($submission, $form = false) { $formSettings = PaymentHelper::getFormSettings($submission->form_id, 'admin'); $customerEmailField = ArrayHelper::get($formSettings, 'receipt_email'); if ($customerEmailField) { $email = ArrayHelper::get($submission->response, $customerEmailField); if ($email) { return $email; } } $user = get_user_by('ID', get_current_user_id()); if ($user) { return $user->user_email; } if (!$form) { return ''; } $emailFields = FormFieldsParser::getInputsByElementTypes($form, ['input_email'], ['attributes']); foreach ($emailFields as $field) { $fieldName = $field['attributes']['name']; if (!empty($submission->response[$fieldName])) { return $submission->response[$fieldName]; } } return ''; } static function getCustomerPhoneNumber($submission, $form) { $phoneFields = FormFieldsParser::getInputsByElementTypes($form, ['phone'], ['attributes']); foreach ($phoneFields as $field) { $fieldName = $field['attributes']['name']; if (!empty($submission->response[$fieldName])) { return $submission->response[$fieldName]; } } return ''; } /** * Trim a string and append a suffix. * * @param string $string String to trim. * @param integer $chars Amount of characters. * Defaults to 200. * @param string $suffix Suffix. * Defaults to '...'. * @return string */ public static function formatPaymentItemString($string, $chars = 200, $suffix = '...') { $string = wp_strip_all_tags($string); if (strlen($string) > $chars) { if (function_exists('mb_substr')) { $string = mb_substr($string, 0, ($chars - mb_strlen($suffix))) . $suffix; } else { $string = substr($string, 0, ($chars - strlen($suffix))) . $suffix; } } return html_entity_decode($string, ENT_NOQUOTES, 'UTF-8'); } /** * Limit length of an arg. * * @param string $string Argument to limit. * @param integer $limit Limit size in characters. * @return string */ public static function limitLength($string, $limit = 127) { $str_limit = $limit - 3; if (function_exists('mb_strimwidth')) { if (mb_strlen($string) > $limit) { $string = mb_strimwidth($string, 0, $str_limit) . '...'; } } else { if (strlen($string) > $limit) { $string = substr($string, 0, $str_limit) . '...'; } } return $string; } public static function floatToString($float) { if (!is_float($float)) { return $float; } $locale = localeconv(); $string = strval($float); $string = str_replace($locale['decimal_point'], '.', $string); return $string; } public static function convertToCents($amount) { if (!$amount) { return 0; } $amount = floatval($amount); return intval(round($amount * 100)); } public static function getCustomerName($submission, $form = false) { $formSettings = PaymentHelper::getFormSettings($submission->form_id, 'admin'); $customerNameCode = ArrayHelper::get($formSettings, 'customer_name'); if ($customerNameCode) { $customerName = ShortCodeParser::parse($customerNameCode, $submission->id, $submission->response); if ($customerName) { return $customerName; } } $user = get_user_by('ID', get_current_user_id()); if ($user) { $customerName = trim($user->first_name . ' ' . $user->last_name); if (!$customerName) { $customerName = $user->display_name; } if ($customerName) { return $customerName; } } if (!$form) { return ''; } $nameFields = FormFieldsParser::getInputsByElementTypes($form, ['input_name'], ['attributes']); $fieldName = false; foreach ($nameFields as $field) { if ($field['element'] === 'input_name') { $fieldName = $field['attributes']['name']; break; } } $name = ''; if ($fieldName) { if (!empty($submission->response[$fieldName])) { $names = array_filter($submission->response[$fieldName]); return trim(implode(' ', $names)); } } return $name; } public static function getStripeInlineConfig($formId) { $methods = static::getFormPaymentMethods($formId); $stripe = ArrayHelper::get($methods, 'stripe'); $stripeInlineStyles = ArrayHelper::get(Helper::getFormMeta($formId, '_ff_form_styles', []), 'stripe_inline_element_style', false); if ($stripe) { return [ 'is_inline' => ArrayHelper::get($stripe, 'settings.embedded_checkout.value') == 'yes', 'inline_styles' => $stripeInlineStyles, 'verifyZip' => ArrayHelper::get($methods['stripe'], 'settings.verify_zip_code.value') === 'yes', ]; } return []; } public static function log($data, $submission = false, $forceInsert = false) { if (!$forceInsert) { static $paymentSettings; if (!$paymentSettings) { $paymentSettings = self::getPaymentSettings(); } if (!isset($paymentSettings['debug_log']) || $paymentSettings['debug_log'] != 'yes') { return false; } } $defaults = [ 'component' => 'Payment', 'status' => 'info', 'created_at' => current_time('mysql') ]; if ($submission) { $defaults['parent_source_id'] = $submission->form_id; $defaults['source_type'] = 'submission_item'; $defaults['source_id'] = $submission->id; } else { $defaults['source_type'] = 'system_log'; } $data = wp_parse_args($data, $defaults); return wpFluent()->table('fluentform_logs') ->insertGetId($data); } public static function maybeFireSubmissionActionHok($submission) { if (Helper::getSubmissionMeta($submission->id, 'is_form_action_fired') == 'yes') { return false; } $form = wpFluent()->table('fluentform_forms')->where('id', $submission->form_id)->first(); $formData = $submission->response; if (!is_array($formData)) { $formData = json_decode($formData, true); } (new SubmissionHandlerService())->processSubmissionData( $submission->id, $formData, $form ); Helper::setSubmissionMeta($submission->id, 'is_form_action_fired', 'yes'); return true; } public static function loadView($fileName, $data) { // normalize the filename $fileName = str_replace(array('../', './'), '', $fileName); $basePath = FLUENTFORMPRO_DIR_PATH . 'src/views/receipt/'; $basePath = apply_filters_deprecated( 'fluentform_payment_receipt_template_base_path', [ $basePath, $fileName, $data ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_receipt_template_base_path', 'Use fluentform/payment_receipt_template_base_path instead of fluentform_payment_receipt_template_base_path.' ); $basePath = apply_filters('fluentform/payment_receipt_template_base_path', $basePath, $fileName, $data); $filePath = $basePath . $fileName . '.php'; extract($data); ob_start(); include $filePath; return ob_get_clean(); } public static function recordSubscriptionCancelled($subscription, $vendorData, $logData = []) { wpFluent()->table('fluentform_subscriptions') ->where('id', $subscription->id) ->update([ 'status' => 'cancelled', 'updated_at' => current_time('mysql') ]); $subscription = wpFluent()->table('fluentform_subscriptions') ->where('id', $subscription->id) ->first(); $submission = wpFluent()->table('fluentform_submissions') ->where('id', $subscription->submission_id) ->first(); $logDefaults = [ 'parent_source_id' => $subscription->form_id, 'source_type' => 'submission_item', 'source_id' => $subscription->submission_id, 'component' => 'Payment', 'status' => 'info', 'title' => __('Subscription has been cancelled', 'fluentformpro'), 'description' => __('Subscription has been cancelled from ', 'fluentformpro') . $submission->payment_method ]; $logs = wp_parse_args($logData, $logDefaults); do_action('fluentform/log_data', $logs); do_action_deprecated( 'fluentform_subscription_payment_canceled', [ $subscription, $submission, $vendorData ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/subscription_payment_canceled', 'Use fluentform/subscription_payment_canceled instead of fluentform_subscription_payment_canceled.' ); // New Payment Made so we have to fire some events here do_action('fluentform/subscription_payment_canceled', $subscription, $submission, $vendorData); do_action_deprecated( 'fluentform_subscription_payment_canceled_' . $submission->payment_method, [ $subscription, $submission, $vendorData ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/subscription_payment_canceled_' . $submission->payment_method, 'Use fluentform/subscription_payment_canceled_' . $submission->payment_method . ' instead of fluentform_subscription_payment_canceled_' . $submission->payment_method ); do_action('fluentform/subscription_payment_canceled_' . $submission->payment_method, $subscription, $submission, $vendorData); } public static function getPaymentSummaryText($plan, $formId, $currency, $withMarkup = true) { $paymentSummaryText = [ 'has_signup_fee' => __('{first_interval_total} for first {billing_interval} then {subscription_amount} for each {billing_interval}', 'fluentformpro'), 'has_trial' => __('Free for {trial_days} days then {subscription_amount} for each {billing_interval}', 'fluentformpro'), 'onetime_only' => __('One time payment of {first_interval_total}', 'fluentformpro'), 'normal' => __('{subscription_amount} for each {billing_interval}', 'fluentformpro'), 'bill_times' => __(', for {bill_times} installments', 'fluentformpro'), 'single_trial' => __('Free for {trial_days} days then {subscription_amount} one time') ]; $paymentSummaryText = apply_filters_deprecated( 'fluentform_recurring_payment_summary_texts', [ $paymentSummaryText, $plan, $formId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/recurring_payment_summary_texts', 'Use fluentform/recurring_payment_summary_texts instead of fluentform_recurring_payment_summary_texts.' ); $cases = apply_filters('fluentform/recurring_payment_summary_texts', $paymentSummaryText, $plan, $formId); // if is trial $hasTrial = ArrayHelper::get($plan, 'has_trial_days') == 'yes' && ArrayHelper::get($plan, 'trial_days'); if ($hasTrial) { $plan['signup_fee'] = 0; } $signupFee = 0; $hasSignupFee = ArrayHelper::get($plan, 'has_signup_fee') == 'yes' && ArrayHelper::get($plan, 'signup_fee'); if ($hasSignupFee) { $plan['trial_days'] = 0; $signupFee = ArrayHelper::get($plan, 'signup_fee'); } $firstIntervalTotal = PaymentHelper::formatMoney( PaymentHelper::convertToCents($signupFee + ArrayHelper::get($plan, 'subscription_amount')), $currency ); if ($signupFee) { $signupFee = PaymentHelper::formatMoney( PaymentHelper::convertToCents($signupFee), $currency ); } $subscriptionAmount = PaymentHelper::formatMoney( PaymentHelper::convertToCents(ArrayHelper::get($plan, 'subscription_amount')), $currency ); $billingInterval = $plan['billing_interval']; $billingInterval = ArrayHelper::get(self::getBillingIntervals(), $billingInterval, $billingInterval); $replaces = array( '{signup_fee}' => '', '{first_interval_total}' => '' . $firstIntervalTotal . '', '{subscription_amount}' => '' . $subscriptionAmount . '', '{billing_interval}' => '' . $billingInterval . '', '{trial_days}' => '' . $plan['trial_days'] . '', '{bill_times}' => '' . ArrayHelper::get($plan, 'bill_times') . '' ); if (ArrayHelper::get($plan, 'user_input') == 'yes') { $cases['{subscription_amount}'] = '' . $subscriptionAmount . ''; } foreach ($cases as $textKey => $text) { $cases[$textKey] = str_replace(array_keys($replaces), array_values($replaces), $text); } $customText = ''; if ($hasSignupFee) { $customText = $cases['has_signup_fee']; } else if ($hasTrial) { if (ArrayHelper::get($plan, 'bill_times') == 1) { $customText = $cases['single_trial']; } else { $customText = $cases['has_trial']; } } else if (isset($plan['bill_times']) && $plan['bill_times'] == 1) { $customText = $cases['onetime_only']; } else { $customText = $cases['normal']; } if (isset($plan['bill_times']) && $plan['bill_times'] > 1) { $customText .= $cases['bill_times']; } if($withMarkup) { $class = $plan['is_default'] === 'yes' ? '' : 'hidden_field'; return '
    ' . $customText . '
    '; } return $customText; } public static function getCustomerAddress($submission) { $formSettings = PaymentHelper::getFormSettings($submission->form_id, 'admin'); $customerAddressField = ArrayHelper::get($formSettings, 'customer_address'); if ($customerAddressField) { return ArrayHelper::get($submission->response, $customerAddressField); } return null; } public static function getBillingIntervals() { return [ 'day' => __('day', 'fluentformpro'), 'week' => __('week', 'fluentformpro'), 'month' => __('month', 'fluentformpro'), 'year' => __('year', 'fluentformpro') ]; } public static function getSubscriptionStatuses() { return [ 'active' => __('active', 'fluentformpro'), 'trialling' => __('trialling', 'fluentformpro'), 'failing' => __('failing', 'fluentformpro'), 'cancelled' => __('cancelled', 'fluentformpro') ]; } public static function getFormInput($formId,$inputType) { $form = fluentFormApi()->form($formId); $fields = FormFieldsParser::getInputsByElementTypes($form, [$inputType], ['attributes']); if (!empty($fields)) { $field = array_shift($fields); return ArrayHelper::get($field, 'attributes.name'); } return ''; } public static function encryptKey($value) { if(!$value) { return $value; } if ( ! extension_loaded( 'openssl' ) ) { return $value; } $salt = (defined( 'LOGGED_IN_SALT' ) && '' !== LOGGED_IN_SALT) ? LOGGED_IN_SALT : 'this-is-a-fallback-salt-but-not-secure'; $key = ( defined( 'LOGGED_IN_KEY' ) && '' !== LOGGED_IN_KEY ) ? LOGGED_IN_KEY : 'this-is-a-fallback-key-but-not-secure'; $method = 'aes-256-ctr'; $ivlen = openssl_cipher_iv_length( $method ); $iv = openssl_random_pseudo_bytes( $ivlen ); $raw_value = openssl_encrypt( $value . $salt, $method, $key, 0, $iv ); if ( ! $raw_value ) { return false; } return base64_encode( $iv . $raw_value ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode } public static function decryptKey( $raw_value ) { if(!$raw_value) { return $raw_value; } if ( ! extension_loaded( 'openssl' ) ) { return $raw_value; } $raw_value = base64_decode( $raw_value, true ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode $method = 'aes-256-ctr'; $ivlen = openssl_cipher_iv_length( $method ); $iv = substr( $raw_value, 0, $ivlen ); $raw_value = substr( $raw_value, $ivlen ); $salt = (defined( 'LOGGED_IN_SALT' ) && '' !== LOGGED_IN_SALT) ? LOGGED_IN_SALT : 'this-is-a-fallback-salt-but-not-secure'; $key = ( defined( 'LOGGED_IN_KEY' ) && '' !== LOGGED_IN_KEY ) ? LOGGED_IN_KEY : 'this-is-a-fallback-key-but-not-secure'; $value = openssl_decrypt( $raw_value, $method, $key, 0, $iv ); if ( ! $value || substr( $value, - strlen( $salt ) ) !== $salt ) { return false; } return substr( $value, 0, - strlen( $salt ) ); } } PK!5^66src/Payments/AjaxEndpoints.phpnu[ 'enablePaymentModule', 'update_global_settings' => 'updateGlobalSettings', 'get_payment_method_settings' => 'getPaymentMethodSettings', 'save_payment_method_settings' => 'savePaymentMethodSettings', 'get_form_settings' => 'getFormSettings', 'save_form_settings' => 'saveFormSettings', 'update_transaction' => 'updateTransaction', 'get_coupons' => 'getCoupons', 'enable_coupons' => 'enableCoupons', 'save_coupon' => 'saveCoupon', 'delete_coupon' => 'deleteCoupon', 'get_stripe_connect_config' => 'getStripeConnectConfig', 'disconnect_stripe_connection' => 'disconnectStripeConnect', 'get_pages' => 'getWpPages', 'cancel_subscription' => 'cancelSubscription' ]; if (isset($validRoutes[$route])) { $this->{$validRoutes[$route]}(); } die(); } public function enablePaymentModule() { $this->upgradeDb(); // Update settings $settings = PaymentHelper::updatePaymentSettings([ 'status' => 'yes' ]); // send response to reload the page wp_send_json_success([ 'message' => __('Payment Module successfully enabled!', 'fluentformpro'), 'settings' => $settings, 'reload' => 'yes' ]); } private function upgradeDB() { global $wpdb; $table = $wpdb->prefix . 'fluentform_transactions'; $cols = $wpdb->get_col("DESC {$table}", 0); if ($cols && in_array('subscription_id', $cols) && in_array('transaction_hash', $cols)) { // We are good } else { $wpdb->query("DROP TABLE IF EXISTS {$table}"); Migration::migrate(); // Migrate the database FormSubmissions::migrate(true); // Add payment_total } } public function updateGlobalSettings() { $settings = wp_unslash($_REQUEST['settings']); // Update settings $settings = PaymentHelper::updatePaymentSettings($settings); // send response to reload the page wp_send_json_success([ 'message' => __('Settings successfully updated!', 'fluentformpro'), 'settings' => $settings, 'reload' => 'yes' ]); } public function getPaymentMethodSettings() { $method = sanitize_text_field($_REQUEST['method']); $paymentSettings = apply_filters_deprecated( 'fluentform_payment_settings_' . $method, [ [] ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_settings_' . $method, 'Use fluentform/payment_settings_' . $method . ' instead of fluentform_payment_settings_' . $method ); $settings = apply_filters('fluentform/payment_settings_' . $method, $paymentSettings); wp_send_json_success([ 'settings' => ($settings) ? $settings : false ]); } public function savePaymentMethodSettings() { $method = sanitize_text_field($_REQUEST['method']); $settings = wp_unslash($_REQUEST['settings']); $settingsValidation = apply_filters_deprecated( 'fluentform_payment_method_settings_validation_' . $method, [ [], $settings ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_method_settings_validation_' . $method, 'Use fluentform/payment_method_settings_validation_' . $method . ' instead of fluentform_payment_method_settings_validation_' . $method ); $validationErrors = apply_filters('fluentform/payment_method_settings_validation_' . $method, $settingsValidation, $settings); if ($validationErrors) { wp_send_json_error([ 'message' => __('Failed to save settings', 'fluentformpro'), 'errors' => $validationErrors ], 423); } $settings = apply_filters_deprecated( 'fluentform_payment_method_settings_save_' . $method, [ $settings ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_method_settings_save_' . $method, 'Use fluentform/payment_method_settings_save_' . $method . ' instead of fluentform_payment_method_settings_save_' . $method ); $settings = apply_filters('fluentform/payment_method_settings_save_' . $method, $settings); update_option('fluentform_payment_settings_' . $method, $settings, 'yes'); wp_send_json_success([ 'message' => __('Settings successfully updated', 'fluentformpro') ]); } public function getFormSettings() { $formId = intval($_REQUEST['form_id']); $settings = PaymentHelper::getFormSettings($formId, 'admin'); $form = wpFluent()->table('fluentform_forms')->find($formId); $addressFields = array_values(FormFieldsParser::getAddressFields($form)); wp_send_json_success([ 'settings' => $settings, 'currencies' => PaymentHelper::getCurrencies(), 'payment_methods' => PaymentHelper::getFormPaymentMethods($formId), 'addressFields' => array_filter($addressFields) ], 200); } public function saveFormSettings() { $formId = intval($_REQUEST['form_id']); $settings = wp_unslash($_REQUEST['settings']); Helper::setFormMeta($formId, '_payment_settings', $settings); wp_send_json_success([ 'message' => __('Settings successfully saved', 'fluentformpro') ], 200); } public function updateTransaction() { $transactionData = $_REQUEST['transaction']; $transactionId = intval($transactionData['id']); $oldTransaction = wpFluent()->table('fluentform_transactions') ->find($transactionId); $changingStatus = $oldTransaction->status != $transactionData['status']; $updateData = ArrayHelper::only($transactionData, [ 'payer_name', 'payer_email', 'billing_address', 'shipping_address', 'charge_id', 'status' ]); $updateData['updated_at'] = current_time('mysql'); wpFluent()->table('fluentform_transactions') ->where('id', $transactionId) ->update($updateData); $newStatus = $transactionData['status']; if ( ($changingStatus && ($newStatus == 'refunded' || $newStatus == 'partial-refunded')) || ($newStatus == 'partial-refunded' && ArrayHelper::get($transactionData, 'refund_amount')) ) { $refundAmount = 0; $refundNote = 'Refunded by Admin'; if ($newStatus == 'refunded') { // Handle refund here $refundAmount = $oldTransaction->payment_total; } else if ($newStatus == 'partially-refunded') { $refundAmount = ArrayHelper::get($transactionData, 'refund_amount') * 100; $refundNote = ArrayHelper::get($transactionData, 'refund_note'); } if ($refundAmount) { $offlineProcessor = new OfflineProcessor(); $offlineProcessor->setSubmissionId($oldTransaction->submission_id); $submission = $offlineProcessor->getSubmission(); $offlineProcessor->refund($refundAmount, $oldTransaction, $submission, $oldTransaction->payment_method, 'refund_' . time(), $refundNote); } } if ($changingStatus) { if ($newStatus == 'paid' || $newStatus == 'pending' || $newStatus == 'processing') { // Delete All Refunds wpFluent()->table('fluentform_transactions') ->where('submission_id', $oldTransaction->submission_id) ->where('transaction_type', 'refund') ->delete(); } $offlineProcessor = new OfflineProcessor(); $offlineProcessor->setSubmissionId($oldTransaction->submission_id); $offlineProcessor->changeSubmissionPaymentStatus($newStatus); $offlineProcessor->changeTransactionStatus($transactionId, $newStatus); $offlineProcessor->recalculatePaidTotal(); } wp_send_json_success([ 'message' => __('Successfully updated data', 'fluentformpro') ], 200); } public function getCoupons() { $status = get_option('fluentform_coupon_status'); if ($status != 'yes') { wp_send_json([ 'coupon_status' => false ], 200); } $couponModel = new CouponModel(); ob_start(); $coupons = $couponModel->getCoupons(true); $errors = ob_get_clean(); if ($errors) { (new CouponModel())->migrate(); $coupons = $couponModel->getCoupons(true); } $data = [ 'coupon_status' => 'yes', 'coupons' => $coupons ]; if (isset($_REQUEST['page']) && $_REQUEST['page'] == 1) { $forms = wpFluent()->table('fluentform_forms') ->select(['id', 'title']) ->where('has_payment', 1) ->get(); $formattedForms = []; foreach ($forms as $form) { $formattedForms[$form->id] = $form->title; } $data['available_forms'] = $formattedForms; } wp_send_json($data, 200); } public function enableCoupons() { (new CouponModel())->migrate(); update_option('fluentform_coupon_status', 'yes', 'no'); wp_send_json([ 'coupon_status' => 'yes' ], 200); } public function saveCoupon() { $coupon = wp_unslash($_REQUEST['coupon']); $validator = fluentValidator($coupon, [ 'title' => 'required', 'code' => 'required', 'amount' => 'required', 'coupon_type' => 'required', 'status' => 'required' ]); if ($validator->validate()->fails()) { $errors = $validator->errors(); wp_send_json([ 'errors' => $errors, 'message' => __('Please fill up all the required fields', 'fluentformpro') ], 423); } $couponId = false; if (isset($coupon['id'])) { $couponId = $coupon['id']; unset($coupon['id']); } if ($exist = (new CouponModel())->isCouponCodeAvailable($coupon['code'], $couponId)) { wp_send_json([ 'errors' => [ 'code' => [ 'exist' => __('Same coupon code already exists', 'fluentformpro') ] ], 'message' => __('Same coupon code already exists', 'fluentformpro') ], 423); } if ($couponId) { (new CouponModel())->update($couponId, $coupon); } else { $couponId = (new CouponModel())->insert($coupon); } wp_send_json([ 'message' => __('Coupon has been saved successfully', 'fluentformpro'), 'coupon_id' => $couponId ], 200); } public function deleteCoupon() { $couponId = intval($_REQUEST['coupon_id']); (new CouponModel())->delete($couponId); wp_send_json([ 'message' => __('Coupon has been successfully deleted', 'fluentformpro'), 'coupon_id' => $couponId ], 200); } public function getStripeConnectConfig() { wp_send_json_success(ConnectConfig::getConnectConfig()); } public function disconnectStripeConnect() { return ConnectConfig::disconnect($_REQUEST, true); } public function getWpPages() { $pages = wpFluent()->table('posts') ->select(['ID', 'post_title']) ->where('post_status', 'publish') ->where('post_type', 'page') ->orderBy('ID', 'ASC') ->get(); wp_send_json_success([ 'pages' => $pages ]); } public function cancelSubscription() { $subscriptionId = intval(ArrayHelper::get($_REQUEST, 'subscription_id')); $subscription = fluentFormApi('submissions')->getSubscription($subscriptionId); if (!$subscription) { wp_send_json_error([ 'message' => __('Subscription could not be found', 'fluentformpro') ], 423); } $response = (new PaymentManagement())->cancelSubscription($subscription); if(is_wp_error($response)) { wp_send_json_error([ 'message' => $response->get_error_code().' - '.$response->get_error_message() ], 423); } wp_send_json_success([ 'message' => $response ]); } } PK!sˌhhsrc/Payments/PaymentHandler.phpnu[isEnabled()) { return; } add_filter('fluentform/show_payment_entries', '__return_true'); add_filter('fluentform/form_settings_menu', array($this, 'maybeAddPaymentSettings'), 10, 2); // Let's load Payment Methods here (new StripeHandler())->init(); (new PayPalHandler())->init(); (new OfflineHandler())->init(); (new MollieHandler())->init(); (new RazorPayHandler())->init(); (new PaystackHandler())->init(); (new SquareHandler())->init(); // Let's load the payment method component here new MultiPaymentComponent(); new Subscription(); new CustomPaymentComponent(); new ItemQuantity(); new PaymentMethods(); new PaymentSummaryComponent(); new Coupon(); new StripeInline(); add_action('fluentform/before_insert_payment_form', array($this, 'maybeHandlePayment'), 10, 3); add_filter('fluentform/submission_order_data', function ($data, $submission) { return OrderData::getSummary($submission, $submission->form); }, 10, 2); add_filter('fluentform/entries_vars', function ($vars, $form) { if ($form->has_payment) { $vars['has_payment'] = $form->has_payment; $vars['currency_config'] = PaymentHelper::getCurrencyConfig($form->id); $vars['currency_symbols'] = PaymentHelper::getCurrencySymbols(); $vars['payment_statuses'] = PaymentHelper::getPaymentStatuses(); } return $vars; }, 10, 2); add_filter( 'fluentform/submission_labels', [$this, 'modifySingleEntryLabels'], 10, 3 ); add_filter('fluentform/all_entry_labels_with_payment', array($this, 'modifySingleEntryLabels'), 10, 3); add_action('fluentform/rendering_payment_form', function ($form) { wp_enqueue_script('fluentform-payment-handler', FLUENTFORMPRO_DIR_URL . 'public/js/payment_handler.js', array('jquery'), FLUENTFORM_VERSION, true); wp_enqueue_style( 'fluentform-payment-skin', FLUENTFORMPRO_DIR_URL . 'public/css/payment_skin.css', array(), FLUENTFORM_VERSION ); wp_localize_script('fluentform-payment-handler', 'fluentform_payment_config', [ 'i18n' => [ 'item' => __('Item', 'fluentformpro'), 'price' => __('Price', 'fluentformpro'), 'qty' => __('Qty', 'fluentformpro'), 'line_total' => __('Line Total', 'fluentformpro'), 'total' => __('Total', 'fluentformpro'), 'not_found' => __('No payment item selected yet', 'fluentformpro'), 'discount:' => __('Discount:', 'fluentformpro'), 'processing_text' => __('Processing payment. Please wait...', 'fluentformpro'), 'confirming_text' => __('Confirming payment. Please wait...', 'fluentformpro'), 'Signup Fee for' => __('Signup Fee for', 'fluentformpro') ] ]); $secretKey = apply_filters_deprecated( 'fluentform-payment_stripe_publishable_key', [ StripeSettings::getPublishableKey($form->id), $form->id ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_stripe_publishable_key', 'Use fluentform/payment_stripe_publishable_key instead of fluentform-payment_stripe_publishable_key.' ); $publishableKey = apply_filters('fluentform/payment_stripe_publishable_key', $secretKey, $form->id); $stripeCustomCss = [ 'styles' => [ 'base' => [ 'backgroundColor' => 'white', 'color' => '#32325d', 'fontFamily' => "-apple-system, \"system-ui\", \"Segoe UI\", Roboto, Oxygen-Sans, Ubuntu, Cantarell, \"Helvetica Neue\", sans-serif", 'fontSize' => '14px', 'fontSmoothing' => 'antialiased', 'iconColor' => '#32325d', 'textDecoration' => 'none', '::placeholder' => [ 'color'=> "#aab7c4" ], ":focus" => [ 'backgroundColor' => 'white', 'color' => '#32325d', 'fontFamily' => "-apple-system, \"system-ui\", \"Segoe UI\", Roboto, Oxygen-Sans, Ubuntu, Cantarell, \"Helvetica Neue\", sans-serif", 'fontSize' => '14px', 'fontSmoothing' => 'antialiased', 'iconColor' => '#32325d', 'textDecoration' => 'none', ], ], 'invalid' => [ 'color' => "#fa755a", 'iconColor' => "#fa755a" ] ] ]; wp_localize_script('fluentform-payment-handler', 'fluentform_payment_config_' . $form->id, [ 'currency_settings' => PaymentHelper::getCurrencyConfig($form->id), 'stripe' => [ 'publishable_key' => $publishableKey, 'inlineConfig' => PaymentHelper::getStripeInlineConfig($form->id), 'custom_style' => apply_filters('fluentform/stripe_inline_custom_css', $stripeCustomCss, $form->id) ], 'stripe_app_info' => array( 'name' => 'Fluent Forms', 'version' => FLUENTFORMPRO_VERSION, 'url' => site_url(), 'partner_id' => 'pp_partner_FN62GfRLM2Kx5d' ) ]); }); if (isset($_GET['fluentform_payment']) && isset($_GET['payment_method'])) { add_action('wp', function () { $data = $_GET; $type = sanitize_text_field($_GET['fluentform_payment']); if ($type == 'view' && $route = ArrayHelper::get($data, 'route')) { do_action_deprecated( 'fluent_payment_view_' . $route, [ $data ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_view_' . $route, 'Use fluentform/payment_view_' . $route . ' instead of fluent_payment_view_' . $route ); do_action('fluentform/payment_view_' . $route, $data); } $this->validateFrameLessPage($data); $paymentMethod = sanitize_text_field($_GET['payment_method']); do_action_deprecated( 'fluent_payment_frameless_' . $paymentMethod, [ $data ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_frameless_' . $paymentMethod, 'Use fluentform/payment_frameless_' . $paymentMethod . ' instead of fluent_payment_frameless_' . $paymentMethod ); do_action('fluentform/payment_frameless_' . $paymentMethod, $data); }); } if (isset($_REQUEST['fluentform_payment_api_notify'])) { add_action('wp', function () { $paymentMethod = sanitize_text_field($_REQUEST['payment_method']); do_action_deprecated( 'fluentform_ipn_endpoint_' . $paymentMethod, [ ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/ipn_endpoint_' . $paymentMethod, 'Use fluentform/ipn_endpoint_' . $paymentMethod . ' instead of fluentform_ipn_endpoint_' . $paymentMethod ); do_action('fluentform/ipn_endpoint_' . $paymentMethod); }); } add_filter('fluentform/editor_vars', function ($vars) { $settings = PaymentHelper::getCurrencyConfig($vars['form_id']); $vars['payment_settings'] = $settings; $vars['has_payment_features'] = !!$settings; return $vars; }); add_filter('fluentform/admin_i18n', array($this, 'paymentTranslations'), 10, 1); add_filter('fluentform/payment_smartcode', array($this, 'paymentReceiptView'), 10, 3); add_action('user_register', array($this, 'maybeAssignTransactions'), 99, 1); (new PaymentEntries())->init(); /* * Transactions and subscriptions Shortcode */ (new TransactionShortcodes())->init(); add_filter( 'fluentform/validate_input_item_subscription_payment_component', [$this, 'validateSubscriptionInputs'], 10, 3 ); add_filter( 'fluentform/validate_input_item_multi_payment_component', [$this, 'validatePaymentInputs'], 10, 3 ); add_filter( 'fluentform/validate_input_item_payment_method', [$this, 'validatePaymentMethod'], 10, 5 ); } public function pushGlobalSettings($components) { $components['payment_settings'] = [ 'hash' => '', 'title' => __('Payment Settings', 'fluentformpro'), 'query' => [ 'component' => 'payment_settings' ], 'sub_menu'=>[ [ 'name' => __('Settings', 'fluentformpro'), 'path' => '#/', 'query' => [ 'component' => 'payment_settings/' ] ], [ 'name' => __('Payment Methods', 'fluentformpro'), 'path' => '#/payment_methods', 'query' => [ 'component' => 'payment_settings/' ] ], [ 'name' => __('Coupons', 'fluentformpro'), 'path' => '#/coupons', 'query' => [ 'component' => 'payment_settings/' ] ], ] ]; return $components; } public function renderPaymentSettings() { if (isset($_GET['ff_stripe_connect'])) { $data = ArrayHelper::only($_GET, ['ff_stripe_connect', 'mode', 'state', 'code']); ConnectConfig::verifyAuthorizeSuccess($data); } $paymentSettings = PaymentHelper::getPaymentSettings(); $isSettingsAvailable = !!get_option('__fluentform_payment_module_settings'); $nav = 'general'; if (isset($_REQUEST['nav'])) { $nav = sanitize_text_field($_REQUEST['nav']); } $paymentMethods = apply_filters_deprecated( 'fluentformpro_available_payment_methods', [ [] ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/available_payment_methods', 'Use fluentform/available_payment_methods instead of fluentformpro_available_payment_methods.' ); $globalSettings = apply_filters_deprecated( 'fluentformpro_payment_methods_global_settings', [ [] ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_methods_global_settings', 'Use fluentform/payment_methods_global_settings instead of fluentformpro_payment_methods_global_settings.' ); $data = [ 'is_setup' => $isSettingsAvailable, 'general' => $paymentSettings, 'payment_methods' => apply_filters('fluentform/available_payment_methods', $paymentMethods), 'available_payment_methods' => apply_filters('fluentform/payment_methods_global_settings', $globalSettings), 'currencies' => PaymentHelper::getCurrencies(), 'active_nav' => $nav, 'stripe_webhook_url' => add_query_arg([ 'fluentform_payment_api_notify' => '1', 'payment_method' => 'stripe' ], site_url('index.php')), 'paypal_webhook_url' => add_query_arg([ 'fluentform_payment_api_notify' => '1', 'payment_method' => 'paypal' ], site_url('index.php')) ]; wp_enqueue_script('ff-payment-settings', FLUENTFORMPRO_DIR_URL . 'public/js/payment-settings.js', ['jquery'], FLUENTFORMPRO_VERSION, true); wp_enqueue_style('ff-payment-settings', FLUENTFORMPRO_DIR_URL . 'public/css/payment_settings.css', [], FLUENTFORMPRO_VERSION); wp_enqueue_media(); wp_localize_script('ff-payment-settings', 'ff_payment_settings', $data); echo '
    '; } public function handleAjaxEndpoints() { if (isset($_REQUEST['form_id'])) { Acl::verify('fluentform_forms_manager'); } else { Acl::verify('fluentform_settings_manager'); } $route = sanitize_text_field($_REQUEST['route']); (new AjaxEndpoints())->handleEndpoint($route); } public function maybeHandlePayment($insertData, $data, $form) { // Let's get selected Payment Method if (!FormFieldsParser::hasPaymentFields($form)) { return; } $paymentAction = new PaymentAction($form, $insertData, $data); if (!$paymentAction->getSubscriptionItems() && !$paymentAction->getCalculatedAmount()) { return; } /* * We have to check if * 1. has payment method * 2. if user selected payment method * 3. or maybe has a conditional logic on it */ if ($paymentAction->isConditionPass()) { if (FormFieldsParser::hasElement($form, 'payment_method') && !$paymentAction->selectedPaymentMethod ) { wp_send_json([ 'errors' => [__('Sorry! No selected payment method found. Please select a valid payment method', 'fluentformpro')] ], 423); } } /* * Some Payment Gateway like Razorpay, Square not supported $subscriptionItems. * So we are providing filter hook to validate payment fields. */ $errors = apply_filters( 'fluentform/validate_payment_items_' . $paymentAction->selectedPaymentMethod, [], $paymentAction->getOrderItems(), $paymentAction->getSubscriptionItems(), $form ); if ($errors) { wp_send_json([ 'errors' => $errors ], 423); } $paymentAction->draftFormEntry(); } public function isEnabled() { $paymentSettings = PaymentHelper::getPaymentSettings(); return $paymentSettings['status'] == 'yes'; } public function modifySingleEntryLabels($labels, $submission, $form) { $formFields = FormFieldsParser::getPaymentFields($form); if ($formFields && is_array($formFields)) { $labels = ArrayHelper::except($labels, array_keys($formFields)); } return $labels; } public function maybeAddPaymentSettings($menus, $formId) { $form = wpFluent()->table('fluentform_forms')->find($formId); if ($form->has_payment) { $menus = array_merge(array_slice($menus, 0, 1), array( 'payment_settings' => [ 'title' => __('Payment Settings', 'fluentformpro'), 'slug' => 'form_settings', 'hash' => 'payment_settings', 'route' => '/payment-settings', ] ), array_slice($menus, 1)); } return $menus; } /** * @param $html string * @param $property string * @param $instance ShortCodeParser * @return false|string */ public function paymentReceiptView($html, $property, $instance) { $entry = $instance::getEntry(); $receiptClass = new PaymentReceipt($entry); return $receiptClass->getItem($property); } private function validateFrameLessPage($data) { // We should verify the transaction hash from the URL $transactionHash = sanitize_text_field(ArrayHelper::get($data, 'transaction_hash')); $submissionId = intval(ArrayHelper::get($data, 'fluentform_payment')); if (!$submissionId) { die('Validation Failed'); } if ($transactionHash) { $transaction = wpFluent()->table('fluentform_transactions') ->where('submission_id', $submissionId) ->where('transaction_hash', $transactionHash) ->first(); if ($transaction) { return true; } die('Transaction hash is invalid'); } $uid = sanitize_text_field(ArrayHelper::get($data, 'entry_uid')); if (!$uid) { die('Validation Failed'); } $originalUid = Helper::getSubmissionMeta($submissionId, '_entry_uid_hash'); if ($originalUid != $uid) { die(__('Transaction UID is invalid', 'fluentformpro')); } return true; } public function maybeAssignTransactions($userId) { $user = get_user_by('ID', $userId); if (!$user) { return false; } $userEmail = $user->user_email; $transactions = wpFluent()->table('fluentform_transactions') ->where('payer_email', $userEmail) ->where(function ($query) { $query->whereNull('user_id') ->orWhere('user_id', ''); }) ->get(); if (!$transactions) { return false; } $submissionIds = []; $transactionIds = []; foreach ($transactions as $transaction) { $submissionIds[] = $transaction->submission_id; $transactionIds[] = $transaction->id; } $submissionIds = array_unique($submissionIds); $transactionIds = array_unique($transactionIds); wpFluent()->table('fluentform_submissions') ->whereIn('id', $submissionIds) ->update([ 'user_id' => $userId, 'updated_at' => current_time('mysql') ]); wpFluent()->table('fluentform_transactions') ->whereIn('id', $transactionIds) ->update([ 'user_id' => $userId, 'updated_at' => current_time('mysql') ]); return true; } public function paymentTranslations($i18n) { $paymentI18n = array( 'Order Details' => __('Order Details', 'fluentformpro'), 'Product' => __('Product', 'fluentformpro'), 'Qty' => __('Qty', 'fluentformpro'), 'Unit Price' => __('Unit Price', 'fluentformpro'), 'Total' => __('Total', 'fluentformpro'), 'Sub-Total' => __('Sub-Total', 'fluentformpro'), 'Discount' => __('Discount', 'fluentformpro'), 'Price' => __('Price', 'fluentformpro'), 'Payment Details' => __('Payment Details', 'fluentformpro'), 'From Subscriptions' => __('From Subscriptions', 'fluentformpro'), 'Card Last 4' => __('Card Last 4', 'fluentformpro'), 'Payment Total' => __('Payment Total', 'fluentformpro'), 'Payment Status' => __('Payment Status', 'fluentformpro'), 'Transaction ID' => __('Transaction ID', 'fluentformpro'), 'Payment Method' => __('Payment Method', 'fluentformpro'), 'Transaction' => __('Transaction', 'fluentformpro'), 'Refunds' => __('Refunds', 'fluentformpro'), 'Refund' => __('Refund', 'fluentformpro'), 'at' => __('at', 'fluentformpro'), 'View' => __('View', 'fluentformpro'), 'has been refunded via' => __('has been refunded via', 'fluentformpro'), 'Note' => __('Note', 'fluentformpro'), 'Edit Transaction' => __('Edit Transaction', 'fluentformpro'), 'Billing Name' => __('Billing Name', 'fluentformpro'), 'Billing Email' => __('Billing Email', 'fluentformpro'), 'Billing Address' => __('Billing Address', 'fluentformpro'), 'Shipping Address' => __('Shipping Address', 'fluentformpro'), 'Reference ID' => __('Reference ID', 'fluentformpro'), 'refunds-to-be-handled-from-provider-text' => __('Please note that, Actual Refund needs to be handled in your Payment Service Provider.', 'fluentformpro'), 'Please Provide new refund amount only.' => __('Please Provide new refund amount only.', 'fluentformpro'), 'Refund Note' => __('Refund Note', 'fluentformpro'), 'Cancel' => __('Cancel', 'fluentformpro'), 'Confirm' => __('Confirm', 'fluentformpro'), ); return array_merge($i18n,$paymentI18n); } public function validateSubscriptionInputs($error, $field, $formData) { if (isset($formData[$field['name']])) { $subscriptionOptions = ArrayHelper::get($field, 'raw.settings.subscription_options', []); $selectedPlanIndex = $formData[$field['name']]; $acceptedSubscriptionPlan = is_numeric($selectedPlanIndex) && in_array($selectedPlanIndex, array_keys($subscriptionOptions)); if (!$acceptedSubscriptionPlan) { $error = __('This subscription plan is invalid', 'fluentformpro'); } $selectedPlan = ArrayHelper::get($subscriptionOptions, $selectedPlanIndex, []); if ('yes' === ArrayHelper::get($selectedPlan, 'user_input')) { $userGivenValue = ArrayHelper::get($formData, "{$field['name']}_custom_$selectedPlanIndex"); $userGivenValue = $userGivenValue ?: 0; $planMinValue = ArrayHelper::get($selectedPlan, 'user_input_min_value'); if (!is_numeric($userGivenValue) || ($planMinValue && $userGivenValue < $planMinValue)) { $error = __('This subscription plan value is invalid', 'fluentformpro'); } } } return $error; } public function validatePaymentInputs($error, $field, $formData) { if (ArrayHelper::get($formData, $field['name'])) { $fieldType = ArrayHelper::get($field, 'raw.attributes.type'); if (in_array($fieldType, ['radio', 'select', 'checkbox'])) { $pricingOptions = array_column( ArrayHelper::get($field, 'raw.settings.pricing_options', []), 'label' ); $pricingOptions = array_map('sanitize_text_field', $pricingOptions); if (in_array($fieldType, ['radio', 'select'])) { $acceptedPaymentPlan = in_array($formData[$field['name']], $pricingOptions); } else { $acceptedPaymentPlan = array_diff($formData[$field['name']], $pricingOptions); $acceptedPaymentPlan = empty($acceptedPaymentPlan); } if (!$acceptedPaymentPlan) { $error = __('This payment item is invalid', 'fluentformpro'); } } } return $error; } public function validatePaymentMethod($error, $field, $formData, $fields, $form) { if ($selectedMethod = ArrayHelper::get($formData, $field['name'])) { $activeMethods = array_keys(PaymentHelper::getFormPaymentMethods($form->id)); if (!in_array($selectedMethod, $activeMethods)) { $error = __('This payment method is invalid', 'fluentformpro'); } } return $error; } } PK!GMM&src/Payments/TransactionShortcodes.phpnu[' . $content . ''; } $atts = shortcode_atts([ 'type' => 'all', 'payment_statuses' => '', 'subscription_statuses' => '', ], $atts); if ($atts['payment_statuses']) { $pay_statuses_array = array_filter(explode(',', $atts['payment_statuses'])); $atts['payment_statuses'] = $pay_statuses_array; } if ($atts['subscription_statuses']) { $sub_statuses_array = array_filter(explode(',', $atts['subscription_statuses'])); $atts['subscription_statuses'] = $sub_statuses_array; } $viewConfig = $this->getViewConfig(); $html = ''; if ($atts['type'] == 'all' || $atts['type'] == 'subscriptions') { $subscriptionsHtml = $this->getSubscriptionsHtml($userId, $viewConfig, $atts); if ($subscriptionsHtml) { wp_enqueue_script('fluentform_transactions', FLUENTFORMPRO_DIR_URL . 'public/js/fluentform_transactions_ui.js', ['jquery'], FLUENTFORM_VERSION, true); wp_enqueue_style( 'fluentform_transactions', FLUENTFORMPRO_DIR_URL . 'public/css/fluentform_transactions.css', [], FLUENTFORM_VERSION ); wp_localize_script('fluentform_transactions', 'ff_transactions_vars', [ 'ajax_url' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('fluentform_transactions') ]); if ($atts['type'] == 'subscriptions') { $html .= $subscriptionsHtml; } else { $withTitleHtml = '
    '; if (!empty($viewConfig['transactions_title'])) { $withTitleHtml .= '

    ' . $viewConfig['subscriptions_title'] . '

    '; } $html .= $withTitleHtml . $subscriptionsHtml . '
    '; } } else if ($atts['type'] == 'subscriptions') { return '

    ' . __('No subscription payments found', 'fluentformpro') . '

    '; } } $html .= $this->getTransactionsHtml($userId, $viewConfig, $atts); return $html; } public function registerReceiptShortcode($atts, $content = '') { $data = $_REQUEST; return $this->renderPaymentReceiptPage($data, false); } public function renderPaymentReceiptPage($data, $echo = true) { $transactionHash = ArrayHelper::get($data, 'transaction'); $transaction = fluentFormApi('submissions')->transaction($transactionHash, 'transaction_hash'); if(!$transaction) { if($echo) { status_header(200); echo __('Sorry no transaction found', 'fluentformpro'); exit(200); } return ''; } $submission = fluentFormApi('submissions')->find($transaction->submission_id); if ($transaction->transaction_type == 'subscription') { $transaction->subscription = fluentFormApi('submissions')->getSubscription($transaction->subscription_id); } $transaction->form = fluentFormApi('forms')->find($transaction->form_id); $transaction->submission = $submission; $transactionHtml = $this->getTransactionHtml($transaction); if(!$echo) { return $transactionHtml; } add_action('wp_enqueue_scripts', function () { wp_enqueue_style('fluent-form-landing', FLUENTFORMPRO_DIR_URL . 'public/css/frameless.css', [], FLUENTFORMPRO_VERSION); }); $form = fluentFormApi('forms')->find($transaction->form_id); $data = [ 'form' => $form, 'status' => $transaction->status, 'title' => 'Transaction #'.$transaction->id, 'message' => $transactionHtml ]; add_filter('pre_get_document_title', function ($title) use ($data) { return $data['title'] . ' ' . apply_filters('document_title_separator', '-') . ' ' . $data['form']->title; }); status_header(200); $file = FLUENTFORMPRO_DIR_PATH . 'src/views/frameless_view.php'; extract($data); ob_start(); include($file); echo ob_get_clean(); exit(200); } public function routeAjaxEndpoints() { $route = sanitize_text_field(ArrayHelper::get($_REQUEST, 'route')); $this->verifyNonce(); if ($route == 'get_subscription_transactions') { $this->sendSubscriptionPayments(); } else if ('cancel_transaction') { $this->cancelSubscriptionAjax(); } } public function getSubscriptionsHtml($userId, $viewConfig = [], $atts = []) { if (!$viewConfig) { $viewConfig = $this->getViewConfig(); } $subscriptions = fluentFormApi('submissions')->subscriptionsByUserId($userId, [ 'form_title' => true, 'statuses' => ArrayHelper::get($atts, 'subscription_statuses', []) ]); if (!$subscriptions) { return ''; } foreach ($subscriptions as $subscription) { $subscription->formatted_recurring_amount = PaymentHelper::formatMoney($subscription->recurring_amount, $subscription->currency); $billingText = ''; if ($subscription->status == 'active') { if ($subscription->bill_times) { $billingText = sprintf(esc_html__('Will be cancelled after %d payments', 'fluentformpro'), $subscription->bill_times); } else { $billingText = __('will be billed until cancelled', 'fluentformpro'); } } $subscription->billing_text = $billingText; $subscription->starting_date_formated = date_i18n($viewConfig['date_format'], strtotime($subscription->created_at)); $subscription->can_cancel = $this->canCancelSubscription($subscription); $subscription->status = ArrayHelper::get(PaymentHelper::getSubscriptionStatuses(), $subscription->status, $subscription->status); $subscription->billing_interval = ArrayHelper::get(PaymentHelper::getBillingIntervals(), $subscription->billing_interval, $subscription->billing_interval); } return PaymentHelper::loadView('user_subscriptions_table', [ 'subscriptions' => $subscriptions, 'config' => $viewConfig ]); } public function getTransactionsHtml($userId, $viewConfig = [], $atts = []) { if (!$viewConfig) { $viewConfig = $this->getViewConfig(); } $transactions = fluentFormApi('submissions')->transactionsByUserId($userId, [ 'transaction_types' => ['onetime'], 'statuses' => ArrayHelper::get($atts, 'payment_statuses', []) ]); if (!$transactions) { return ''; } foreach ($transactions as $transaction) { $transaction->formatted_amount = PaymentHelper::formatMoney($transaction->payment_total, $transaction->currency); $transaction->formatted_date = date_i18n($viewConfig['date_time_format'], strtotime($transaction->created_at)); if (!$transaction->transaction_hash) { $hash = md5(wp_generate_uuid4() . mt_rand(0, 1000)); wpFluent()->table('fluentform_transactions') ->where('id', $transaction->id) ->update([ 'transaction_hash' => $hash ]); $transaction->transaction_hash = $hash; } $transaction->view_url = $viewConfig['base_url'] . 'transaction=' . $transaction->transaction_hash . '&payment_method=' . $transaction->payment_method; $transaction->status = ArrayHelper::get(PaymentHelper::getPaymentStatuses(), $transaction->status, $transaction->status); } $transactionsHtml = PaymentHelper::loadView('transactions_table', [ 'transactions' => $transactions, 'config' => $viewConfig ]); $html = '
    '; if (!empty($viewConfig['transactions_title'])) { $html .= '

    ' . $viewConfig['transactions_title'] . '

    '; } return $html . $transactionsHtml . '
    '; } public function sendSubscriptionPayments() { $subscriptionId = intval(ArrayHelper::get($_REQUEST, 'subscription_id')); if (!$subscriptionId) { wp_send_json_error([ 'message' => __('Invalid Subscription ID', 'fluentformpro'), ], 423); } $userId = get_current_user_id(); $subscription = wpFluent()->table('fluentform_subscriptions') ->select(['fluentform_subscriptions.*', 'fluentform_submissions.user_id']) ->where('fluentform_submissions.user_id', $userId) ->where('fluentform_subscriptions.id', $subscriptionId) ->join('fluentform_submissions', 'fluentform_submissions.id', '=', 'fluentform_subscriptions.submission_id') ->first(); if (!$subscription) { wp_send_json_error([ 'message' => __('Invalid Subscription ID', 'fluentformpro'), ], 423); } $transactions = fluentFormApi('submissions')->transactionsBySubscriptionId($subscription->id); if (!$transactions) { wp_send_json_error([ 'message' => __('Sorry, no related payments found', 'fluentformpro'), ], 423); } $viewConfig = $this->getViewConfig(); foreach ($transactions as $transaction) { if (!$transaction->transaction_hash) { $hash = md5(wp_generate_uuid4() . mt_rand(0, 1000)); wpFluent()->table('fluentform_transactions') ->where('id', $transaction->id) ->update([ 'transaction_hash' => $hash ]); $transaction->transaction_hash = $hash; } $transaction->formatted_amount = PaymentHelper::formatMoney($transaction->payment_total, $transaction->currency); $transaction->formatted_date = date_i18n($viewConfig['date_time_format'], strtotime($transaction->created_at)); $transaction->view_url = false; //$viewConfig['base_url'] . 'transaction=' . $transaction->transaction_hash . '&payment_method=' . $transaction->payment_method; $transaction->status = ArrayHelper::get(PaymentHelper::getPaymentStatuses(), $transaction->status, $transaction->status); } $viewConfig['has_view_action'] = false; $html = PaymentHelper::loadView('user_subscription_payments', [ 'transactions' => $transactions, 'config' => $viewConfig ]); $html = '

    ' . __('Related Payments', 'fluentformpro') . '

    ' . $html; wp_send_json_success([ 'html' => $html ]); } private function getViewConfig() { $paymentSettings = PaymentHelper::getPaymentSettings(); $pageId = ArrayHelper::get($paymentSettings, 'receipt_page_id'); $urlBase = false; if($pageId) { $urlBase = get_permalink($pageId); } if(!$urlBase) { $urlBase = add_query_arg([ 'fluentform_payment' => 'view', 'route' => 'payment' ], site_url('index.php')); } $urlBase = apply_filters_deprecated( 'fluentform_transaction_view_url', [ $urlBase ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/transaction_view_url', 'Use fluentform/transaction_view_url instead of fluentform_transaction_view_url.' ); $urlBase = apply_filters('fluentform/transaction_view_url', $urlBase); if (!strpos($urlBase, '?')) { $urlBase .= '?'; } else { $urlBase .= '&'; } $wpDateTimeFormat = get_option('date_format') . ' ' . get_option('time_format'); $config = [ 'new_tab' => false, 'view_text' => __('View', 'fluentformpro'), 'base_url' => $urlBase, 'date_format' => get_option('date_format'), 'date_time_format' => $wpDateTimeFormat, 'transactions_title' => __('Payments', 'fluentformpro'), 'subscriptions_title' => __('Subscriptions', 'fluentformpro'), 'sub_cancel_confirm_heading' => __('Are you sure you want to cancel this subscription?', 'fluentformpro'), 'sub_cancel_confirm_btn' => __('Yes, cancel this subscription', 'fluentformpro'), 'sub_cancel_close' => __('Close', 'fluentformpro') ]; $config = apply_filters_deprecated( 'fluentform_payment_view_config', [ $config ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_view_config', 'Use fluentform/payment_view_config instead of fluentform_payment_view_config.' ); return apply_filters('fluentform/payment_view_config', $config); } private function verifyNonce() { $nonce = sanitize_text_field($_REQUEST['_nonce']); if (!wp_verify_nonce($nonce, 'fluentform_transactions')) { wp_send_json_error([ 'message' => __('Security validation failed. Please try again', 'fluentformpro') ], 423); } } private function canCancelSubscription($subscription) { $validStatuses = [ 'active', 'trialling', 'failing' ]; if (!in_array($subscription->status, $validStatuses)) { return false; } $paymentSettings = PaymentHelper::getPaymentSettings(); if ($paymentSettings['user_can_manage_subscription'] != 'yes') { return false; } $submission = fluentFormApi('submissions')->find($subscription->submission_id); if (!$submission) { return false; } $method = $submission->payment_method; $hasCancel = apply_filters_deprecated( 'fluentform_pay_method_has_sub_cancel_' . $method, [ false ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/pay_method_has_sub_cancel_' . $method, 'Use fluentform/pay_method_has_sub_cancel_' . $method . ' instead of fluentform_pay_method_has_sub_cancel_' . $method ); return $method == 'stripe' || apply_filters('fluentform/pay_method_has_sub_cancel_' . $method, $hasCancel); } public function cancelSubscriptionAjax() { $subscriptionId = ArrayHelper::get($_REQUEST, 'subscription_id'); if (!$subscriptionId) { $this->sendError(__('Invalid Request', 'fluentformpro')); } $subscription = fluentFormApi('submissions')->getSubscription($subscriptionId); if (!$subscription) { $this->sendError(__('No subscription found', 'fluentformpro')); } // validate the subscription $userid = get_current_user_id(); $submission = fluentFormApi('submissions')->find($subscription->submission_id); if (!$submission && $submission->user_id != $userid || $this->canCancelSubscription($submission)) { $this->sendError(__('Sorry, you can not cancel this subscription at this moment', 'fluentformpro')); } $handler = apply_filters_deprecated( 'fluentform_payment_manager_class_' . $submission->payment_method, [ false ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_manager_class_' . $submission->payment_method, 'Use fluentform/payment_manager_class_' . $submission->payment_method . ' instead of fluentform_payment_manager_class_' . $submission->payment_method ); // Now let's try to cancel this subscription $handler = apply_filters('fluentform/payment_manager_class_' . $submission->payment_method, $handler); if (!$handler || !method_exists($handler, 'cancelSubscription')) { $this->sendError(__('Sorry, you can not cancel this subscription at this moment', 'fluentformpro')); } $response = $handler->cancelSubscription($subscription, 'user', $submission); if (is_wp_error($response)) { $this->sendError($response->get_error_code() . ' - ' . $response->get_error_message()); } wp_send_json_success([ 'message' => __('Your subscription has been cancelled. Refreshing the page...', 'fluentformpro') ], 200); } private function sendError($message) { wp_send_json_error([ 'message' => $message ], 423); } public function getTransactionHtml($transaction, $withHeader = false) { $orderItems = []; $discountItems = []; $transactionTotal = $subTotal = $orderTotal = PaymentHelper::formatMoney($transaction->payment_total, $transaction->currency); if ($transaction->transaction_type == 'subscription') { $total = PaymentHelper::formatMoney($transaction->payment_total, $transaction->currency); $orderItems[] = (object) [ 'formatted_item_price' => $total, 'formatted_line_total' => $total, 'item_name' => $transaction->subscription->plan_name.' ('.$transaction->subscription->item_name.')', 'quantity' => 1 ]; } else { $receiptClass = new PaymentReceipt($transaction->submission); $orderItems = $receiptClass->getOrderItems(); $discountItems = $receiptClass->getDiscountItems(); $subTotal = OrderData::calculateOrderItemsTotal($orderItems, true, $transaction->currency); $orderTotal = OrderData::calculateOrderItemsTotal($orderItems, true, $transaction->currency, $discountItems); } return PaymentHelper::loadView('transaction_details', [ 'transaction' => $transaction, 'transactionTotal' => $transactionTotal, 'discountItems' => $discountItems, 'items' => $orderItems, 'subTotal' => $subTotal, 'orderTotal' => $orderTotal, ]); } } PK!ssrc/Stubs/index.stubnu[ SetHandler none SetHandler default-handler Options -ExecCGI RemoveHandler .cgi .php .php3 .php4 .php5 .phtml .pl .py .pyc .pyo php_flag engine off # END FluentForm PK!fnc,src/classes/AdminApproval/GlobalSettings.phpnu[optionKey, array($this, 'getSettingsFields'), 10, 1); add_action('fluentform/save_global_integration_settings_' . $this->optionKey, array($this, 'saveSettings'), 10, 1); add_filter('fluentform/global_integration_settings_' . $this->optionKey, array($this, 'getSettings'), 10); } public function addGlobalMenu($setting) { $setting[$this->globalModule] = [ 'hash' => $this->globalModule, 'component' => 'general-integration-settings', 'settings_key' => $this->optionKey, 'title' => __('Admin Approval', 'fluentformpro'), 'top_level_menu' => true, ]; return $setting; } public function getSettingsFields($fields) { \FluentForm\App\Modules\Acl\Acl::verify('fluentform_settings_manager'); return [ 'logo' => FLUENTFORMPRO_DIR_URL . 'public/images/google_map.png', 'menu_title' => __('Admin Approval Settings', 'fluentformpro'), 'menu_description' => __( 'Review & Approve submissions to ensure that submitted data meets your requirements, get notified instantly.', 'fluentformpro' ), 'save_button_text' => __('Save Settings', 'fluentformpro'), 'valid_message' => __('Admin Approval is currently active', 'fluentformpro'), 'invalid_message' => __('Admin Approval is currently not active', 'fluentformpro'), 'fields' => [ 'email_notification' => [ 'type' => 'radio_choice', 'placeholder' => '', 'label' => __('Send Email Notification', 'fluentformpro'), 'options' => [ 'admin_email' => __('Site Admin', 'fluentformpro'), 'custom_email' => __('Custom Email', 'fluentformpro') ] ], 'custom_recipients' => [ 'type' => 'text', 'placeholder' => __('For multiple email addresses, use comma to separate them.', 'fluentformpro'), 'label' => __('Enter Recipient Email Address', 'fluentformpro'), 'dependency' => [ [ 'depends_on' => 'email_notification', 'value' => 'custom_email', 'operator' => '==', ], ], ], 'email_subject' => [ 'type' => 'text', 'placeholder' => __('Subject', 'fluentformpro'), 'label' => __('Email Subject', 'fluentformpro'), ], 'email_body' => [ 'type' => 'wp_editor', 'label' => __('Email Body', 'fluentformpro'), 'info' => __( "Use #approve_link# for approve, #declined_link# for declined, {all_data} for all Data and {submission.admin_view_url} for submission link", 'fluentformpro' ), ], 'asPlainText' => [ 'type' => 'checkbox-single', 'checkbox_label' => __('Send Email as RAW HTML Format', 'fluentformpro'), ], 'auto_delete_status' => [ 'type' => 'checkbox_yes_no', 'checkbox_label' => __( 'Automatically delete Unapproved & Declined entries if not confirmed in certain days', 'fluentformpro' ), ], 'auto_delete_day_span' => [ 'type' => 'input_number', 'label' => __('Waiting Days', 'fluentformpro'), 'dependency' => [ [ 'depends_on' => 'auto_delete_status', 'value' => 'yes', 'operator' => '==', ] ], ], ], 'hide_on_valid' => false, 'discard_settings' => false ]; } public function saveSettings($settings) { \FluentForm\App\Modules\Acl\Acl::verify('fluentform_settings_manager'); update_option($this->optionKey, [ 'status' => boolval($settings['status']), 'email_notification' => sanitize_text_field(Arr::get($settings, 'email_notification')), 'auto_delete_status' => sanitize_text_field(Arr::get($settings, 'auto_delete_status')), 'auto_delete_day_span' => (int)(Arr::get($settings, 'auto_delete_day_span')), 'custom_recipients' => fluentFormSanitizer(Arr::get($settings, 'custom_recipients')), 'email_body' => fluentform_sanitize_html(Arr::get($settings, 'email_body')), 'email_subject' => sanitize_text_field(Arr::get($settings, 'email_subject')), ], 'no'); wp_send_json_success([ 'message' => __('Admin Approval settings has been saved', 'fluentformpro'), 'status' => true ], 200); } public function getSettings($settings) { $globalSettings = get_option($this->optionKey); $defaults = [ 'status' => false, 'email_notification' => 'admin_email', 'custom_recipients' => '', 'email_subject' => 'Submission pending for Approval : {form_title}', 'email_body' => '

    Hello There,

    A new submission is pending approval. Please review and take the necessary action. Click this link to view submission details. You can approve or decline the submission.

    {all_data}

    Approve Decline

    Thank you

    ', 'auto_delete_status' => 'no', 'auto_delete_day_span' => '3' ]; if (!$globalSettings) { $globalSettings = $defaults; } return $globalSettings; } } PK!yEE+src/classes/AdminApproval/AdminApproval.phpnu[isEnabled(); add_filter('fluentform/global_addons', [$this, 'addToIntegrationMenu'], 10, 1); if (!$enabled) { return; } new GlobalSettings(); add_filter('fluentform/entry_statuses_core', [$this, 'addApprovalStatuses'], 10, 2); add_filter('fluentform/form_settings_ajax', [$this, 'injectInFormSettings'], 10, 2); add_action('fluentform/after_save_form_settings', [$this, 'saveFormSettings'], 10, 2); add_action('fluentform/before_form_actions_processing', [$this, 'processOnSubmission'], 10, 3); add_action('fluentform/after_submission_status_update', [$this, 'processStatusUpdate'], 10, 2); add_action('fluentform_do_email_report_scheduled_tasks', [$this, 'maybeDeleteUnApprovedAndDeclinedEntries'], 99); add_filter('fluentform/entries_vars',function($data){ if($status = wpFluentForm('request')->get('submission_status')){ $data['admin_approval_url_query'] = sanitize_text_field($status); } return $data; },10,1); } public function addToIntegrationMenu($addons) { $addons[$this->globalModule] = [ 'title' => 'Admin Approval', 'category' => 'wp_core', 'description' => __('Review & Approve submissions to ensure that submitted data meets your requirements, get notified instantly.', 'fluentformpro'), 'logo' => fluentformMix('img/integrations/admin_approval.png'), 'enabled' => ($this->isEnabled()) ? 'yes' : 'no', ]; return $addons; } public function addApprovalStatuses($statuses, $formId) { if (!$this->isActivatedInForm($formId)) { return $statuses; } $statuses[$this->initialStatusSlug] = __('Unapproved', 'fluentformpro'); $statuses[$this->approvedStatusSlug] = __('Approved', 'fluentformpro'); $statuses[$this->declinedStatusSlug] = __('Declined', 'fluentformpro'); return $statuses; } public function injectInFormSettings($settings, $formId) { if ($approvalSettings = $this->getAdminApproval($formId)) { $settings[$this->globalModule] = $approvalSettings; } return $settings; } public function saveFormSettings($formId, $allSettings) { $adminApproval = ArrayHelper::get($allSettings, 'admin_approval', []); if ($adminApproval) { Helper::setFormMeta($formId, 'admin_approval_settings', $adminApproval); } } public function processOnSubmission($insertId, $formData, $form) { if ($form->has_payment) { return; } $adminApprovalFormSettings = $this->getAdminApproval($form->id, 'public'); $isInActive = ArrayHelper::get($adminApprovalFormSettings, 'status') != 'yes'; $skipIfLoggedIn = ArrayHelper::get($adminApprovalFormSettings, 'skip_if_logged_in') == 'yes' && get_current_user_id(); $submission = Submission::find($insertId); if (!$adminApprovalFormSettings || $isInActive || $skipIfLoggedIn || $submission->status == $this->approvedStatusSlug) { return; } $mailSent = $this->sendApprovalPendingAdminEmail($form, $insertId, $formData); Submission::where('id', $insertId)->update([ 'status' => $this->initialStatusSlug ]); // Admin approval with double opt-in, double Opt-in always run before admin approval. // If double opt-in active, render admin approval status on double Opt-in confirmation page. $doubleOptin = new DoubleOptin(); if ($doubleOptin->isActivated($form->id) && in_array($submission->status, $doubleOptin->getStatuses())) { $this->renderApprovalConfirmationView($submission, $form, $formData); return; } $approvalPendingMessage = ArrayHelper::get($adminApprovalFormSettings, 'approval_pending_message'); $approvalPendingMessage = ShortCodeParser::parse($approvalPendingMessage, $insertId, $formData); $result = [ 'insert_id' => $insertId, 'result' => [ 'redirectTo' => 'samePage', 'message' => $approvalPendingMessage, 'action' => 'hide_form' ], 'error' => '', ]; wp_send_json_success($result, 200); } public function processStatusUpdate($submissionId, $status) { if (!$submission = Submission::find($submissionId)) { return; } $form = Form::find($submission->form_id); if ($status == $this->approvedStatusSlug) { $submissionData = json_decode($submission->response, true); $actionFired = Helper::getSubmissionMeta($submission->id, 'is_form_action_fired') == 'yes'; if (!$actionFired) { $this->logData($form, $submission, $status); (new SubmissionHandlerService())->processSubmissionData($submission->id, $submissionData, $form); } } elseif ($status == $this->declinedStatusSlug) { $mailSent = Helper::getSubmissionMeta($submission->id, 'is_declined_email_sent') == 'yes'; if (!$mailSent) { $this->maybeSendDeclinedEmail($submission); $this->logData($form, $submission, $status); } } } public function maybeDeleteUnApprovedAndDeclinedEntries() { $settings = get_option((new GlobalSettings())->optionKey); $autoDeleteOff = ArrayHelper::get($settings, 'auto_delete_status') != 'yes'; if ($autoDeleteOff) { return; } $daySpan = intval(ArrayHelper::get($settings, 'auto_delete_day_span')); if (!$daySpan) { $daySpan = 7; } $date = date('Y-m-d H:i:s', (time() - $daySpan * DAY_IN_SECONDS)); $oldEntries = wpFluent()->table('fluentform_submissions') ->whereIn('status', [$this->initialStatusSlug, $this->declinedStatusSlug]) ->where('created_at', '<', $date) ->limit(100) ->get(); if ($oldEntries) { // @todo need to move 'deleteEntries' method on helper class (new DoubleOptin())->deleteEntries($oldEntries); } } public function getAdminEmail($adminApprovalSettings) { if (ArrayHelper::get($adminApprovalSettings, 'email_notification') == 'admin_email') { $recipients = [get_option('admin_email')]; } else { $custom_recipients = $adminApprovalSettings['custom_recipients']; $custom_recipients = explode(',', $custom_recipients); $recipients = []; foreach ($custom_recipients as $recipient) { $recipient = trim($recipient); if (is_email($recipient)) { $recipients[] = $recipient; } } } return $recipients; } public function isEnabled() { $helper = new IntegrationManagerHelper(); if (method_exists($helper, 'isIntegrationEnabled')) { return IntegrationManagerHelper::isIntegrationEnabled($this->globalModule); } else { //todo: Fallback function support delete this after few version; static $globalModules = []; if (empty($globalModules)) { $globalModules = get_option('fluentform_global_modules_status'); } if (\FluentForm\Framework\Helpers\ArrayHelper::get($globalModules, $this->globalModule) == 'yes') { return true; } } return false; } private function processEmail($form, $insertId, $data, $settings, $emailFields,$formData) { $data = ShortCodeParser::parse($data, $insertId, $formData); $notification = [ 'name' => 'Admin Approval Notification Email', 'fromName' => ArrayHelper::get($settings, 'fromName'), 'fromEmail' => ArrayHelper::get($settings, 'fromEmail', ''), 'replyTo' => ArrayHelper::get($settings, 'replyTo'), 'bcc' => '', 'subject' => $data['email_subject'], 'message' => $data['email_body'], 'enabled' => true, 'email_template' => '', 'sendTo' => [ 'type' => 'email', 'email' => $emailFields, 'field' => '' ] ]; $emailNotificationClass = new EmailNotification(wpFluentForm()); $emailHeaders = $emailNotificationClass->getHeaders($notification); if (ArrayHelper::get($settings, 'asPlainText') != 'yes') { $emailBody = $emailNotificationClass->getEmailWithTemplate($data['email_body'], $form, $notification); } return wp_mail($emailFields, $data['email_subject'], $emailBody, $emailHeaders); } private function logData($form, $submission, $status) { do_action('fluentform/log_data', [ 'parent_source_id' => $form->id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'AdminApproval', 'status' => 'info', 'title' => 'Submission ' . ucwords($status), 'description' => 'Submission ' . ucwords($status) . ' by ' . wp_get_current_user()->display_name, ]); } public function getAdminApproval($formId, $scope = 'admin') { $defaults = [ 'status' => 'no', 'approval_pending_message' => 'Please wait for admin approval to confirm this submission', 'email_body' => '

    Hello There,

    We regret to inform you that your recent submission has been declined. If you have any questions, please don\'t hesitate to reach out to us.

    Thank you.

    ', 'email_subject' => 'Submission Declined', 'skip_if_logged_in' => 'yes', 'asPlainText' => 'no', ]; $settings = \FluentForm\App\Helpers\Helper::getFormMeta($formId, 'admin_approval_settings', []); if ($settings) { $defaults = wp_parse_args($settings, $defaults); } if ($scope == 'public') { $defaults = wp_parse_args($defaults, $settings); } return $defaults; } protected function isActivatedInForm($formId = false) { if (!$formId) { return false; } static $activated; if ($activated) { return $activated == 'yes'; } $settings = $this->getAdminApproval($formId); if ($settings && !empty($settings['status'])) { $activated = $settings['status']; } return $activated == 'yes'; } private function sendApprovalPendingAdminEmail($form, $insertId, $formData) { $globalSettings = (new GlobalSettings())->getSettings([]); $emailFields = $this->getAdminEmail($globalSettings); if ($emailFields) { $emailFields = array_filter($emailFields, 'is_email'); if (empty($emailFields)) { return; } $emailSubject = ArrayHelper::get($globalSettings, 'email_subject'); $data['email_body'] = ArrayHelper::get($globalSettings, 'email_body'); $approvedLink = admin_url('admin.php?page=fluent_forms&route=entries&form_id=' . $form->id . '&update_status=' . $this->approvedStatusSlug . '#/entries/' . $insertId); $declinedLink = admin_url('admin.php?page=fluent_forms&route=entries&form_id=' . $form->id . '&update_status=' . $this->declinedStatusSlug . '#/entries/' . $insertId); $data['email_body'] = str_replace(['#approve_link#', '#declined_link#'], [$approvedLink, $declinedLink], $data['email_body']); $data['email_subject'] = $emailSubject; $mailSent = $this->processEmail($form, $insertId, $data, $globalSettings, $emailFields,$formData); do_action('fluentform/log_data', [ 'parent_source_id' => $form->id, 'source_type' => 'submission_item', 'source_id' => $insertId, 'component' => 'AdminApproval', 'status' => 'info', 'title' => __('Admin Approval Notification Email sent', 'fluentformpro'), 'description' => __('Email sent to admin email : [', 'fluentformpro') . implode(', ', $emailFields) . ']', ]); return $mailSent; } } private function maybeSendDeclinedEmail($submission) { $formSettings = $this->getAdminApproval($submission->form_id); $emailField = ArrayHelper::get($formSettings, 'email_field'); if (!$emailField) { return; } $formData = json_decode($submission->response, true); $emailId = trim(ArrayHelper::get($formData, $emailField)); if (!$emailId || !is_email($emailId)) { return; } $form = Form::find($submission->form_id); $data['email_body'] = ArrayHelper::get($formSettings, 'email_body'); $data['email_subject'] = ArrayHelper::get($formSettings, 'email_subject'); $data = ShortCodeParser::parse($data, $submission->id, $formData); $this->processEmail($form, $submission->id, $data, $formSettings, [$emailId],$formData); do_action('fluentform/log_data', [ 'parent_source_id' => $form->id, 'source_type' => 'submission_item', 'source_id' => $submission->id, 'component' => 'AdminApproval', 'status' => 'info', 'title' => __('Submission Declined Notification Email sent to User', 'fluentformpro'), 'description' => __('Email sent to user email : [', 'fluentformpro') . $emailId . ']', ]); Helper::setSubmissionMeta($submission->id, 'is_declined_email_sent', 'yes'); } public function isEntryOnAdminApprovalMode($entryStatus) { return $this->isEnabled() && in_array($entryStatus, [$this->initialStatusSlug, $this->declinedStatusSlug, $this->approvedStatusSlug]); } public function renderApprovalConfirmationView($submission, $form, $formData) { $approvalSettings = $this->getAdminApproval($form->id, 'public'); if ($submission->status == $this->approvedStatusSlug) { $landingContent = ArrayHelper::get($approvalSettings, 'approval_success_message', __("Submission verified and approved by Admin", 'fluentformpro')); } elseif ($submission->status == $this->declinedStatusSlug) { $landingContent = ArrayHelper::get($approvalSettings, 'approval_failed_message', __("Submission verified and declined by Admin", 'fluentformpro')); } else { $landingContent = ArrayHelper::get($approvalSettings, 'approval_pending_message', __('Please wait for admin to confirm this submission', 'fluentformpro')); } $landingContent = ShortCodeParser::parse($landingContent, $submission->id, $formData); $sharePage = new SharePage(); $statusTitle = ucfirst($submission->status); $settings = $sharePage->getSettings($form->id); $submissionVars = [ 'settings' => $settings, 'title' => "Submission $statusTitle - {$form->title}", 'form_id' => $form->id, 'entry' => $submission, 'form' => $form, 'bg_color' => ArrayHelper::get($settings, 'custom_color', '#4286c4'), 'landing_content' => $landingContent, 'has_header' => false, 'isEmbeded' => !!ArrayHelper::get($_GET, 'embedded') ]; $submissionVars = apply_filters_deprecated( 'fluentform_submission_vars', [ $submissionVars, $form->id ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/submission_vars', 'Use fluentform/submission_vars instead of fluentform_submission_vars.' ); $landingVars = apply_filters('fluentform/submission_vars', $submissionVars, $form->id); $sharePage->loadPublicView($landingVars); } } PK!s s src/classes/Chat/ChatApi.phpnu[key = $key; } public function makeRequest($args = [], $token = '') { if (!$token) { $token = ArrayHelper::get(get_option($this->key), 'access_token'); } $headers = [ 'Authorization' => 'Bearer ' . $token, 'Content-Type' => 'application/json', ]; $bodyArgs = [ "model" => "gpt-3.5-turbo", "messages" => [ $args ?: [ "role" => "system", "content" => "You are a helpful assistant." ] ] ]; add_filter('http_request_timeout', function($timeout) { return 60; // Set timeout to 60 seconds }); $request = wp_remote_post($this->url, [ 'headers' => $headers, 'body' => json_encode($bodyArgs) ]); if (did_filter('http_request_timeout')) { add_filter('http_request_timeout', function($timeout) { return 5; // Set timeout to original 5 seconds }); } if (is_wp_error($request)) { $message = $request->get_error_message(); return new \WP_Error(423, $message); } $body = json_decode(wp_remote_retrieve_body($request), true); $code = wp_remote_retrieve_response_code($request); if ($code !== 200) { $error = __('Something went wrong.', 'fluentformpro'); if (isset($body['error']['message'])) { $error = __($body['error']['message'], 'fluentformpro'); } return new \WP_Error(423, $error); } return $body; } public function isAuthenticated($token) { $result = $this->makeRequest([], $token); if (is_wp_error($result)) { return $result; } return isset($result['id']); } public function isApiEnabled() { $settings = get_option($this->key); if (!$settings || empty($settings['status'])) { $settings = [ 'access_token' => '', 'status' => false, ]; } return ArrayHelper::isTrue($settings, 'status'); } } PK!RˊWII(src/classes/Chat/ChatFieldController.phpnu[app = $app; $this->api = new ChatApi($this->optionKey); $this->boot(); } public function boot() { $isEnabled = $this->isEnabled(); $this->enableIntegration($isEnabled); if (!$isEnabled) { return; } $isApiEnabled = $this->api->isApiEnabled(); if ($isApiEnabled) { add_filter('fluentform/all_editor_shortcodes', [$this, 'insertAllEditorShortcode'], 10, 1); add_filter('fluentform/all_forms_vars', function ($settings) { $settings['has_gpt_feature'] = true; return $settings; }); new ChatFormBuilder(); } add_filter('fluentform/global_settings_components', [$this, 'addGlobalMenu'], 11, 1); add_filter('fluentform/global_integration_settings_' . $this->integrationKey, [$this, 'getGlobalSettings'], 11, 1); add_filter('fluentform/global_integration_fields_' . $this->integrationKey, [$this, 'getGlobalFields'], 11, 1); add_action('fluentform/save_global_integration_settings_' . $this->integrationKey, [$this, 'saveGlobalSettings'], 11,1); add_filter('fluentform/global_notification_types', [$this, 'addNotificationType'], 11, 1); add_filter('fluentform/get_available_form_integrations', [$this, 'pushIntegration'], 11, 2); add_filter('fluentform/global_notification_feed_' . $this->settingsKey, [$this, 'setFeedAttributes'], 11, 2); add_filter('fluentform/get_integration_defaults_' . $this->integrationKey, [$this, 'getIntegrationDefaults'], 11, 2); add_filter('fluentform/get_integration_settings_fields_' . $this->integrationKey, [$this, 'getSettingsFields'], 11, 2); add_filter('fluentform/save_integration_settings_' . $this->integrationKey, [$this, 'setMetaKey'], 11, 2); add_filter('fluentform/get_integration_values_' . $this->integrationKey, [$this, 'prepareIntegrationFeed'], 11, 3); add_filter('fluentform/save_integration_value_' . $this->integrationKey, [$this, 'validate'], 10, 3); add_filter('fluentform/form_class', [$this, 'beforeFormRenderCss'], 10, 2); // add_action('wp_ajax_fluentform_openai_chat_completion', [$this, 'chatCompletion'], 11, 0); // add_action('wp_ajax_nopriv_fluentform_openai_chat_completion', [$this, 'chatCompletion'], 11, 0); // new ChatField(); } public function loadScripts() { $message = apply_filters('fluentform/chat_gpt_waiting_message', __('Please wait while getting the data from ChatGPT. Do not refresh or close the window', 'fluentformpro')); wp_register_script( 'fluentform-chat-field-script', FLUENTFORMPRO_DIR_URL . 'public/js/chatFieldScript.js', ['jquery'], FLUENTFORMPRO_VERSION, true ); wp_localize_script( 'fluentform-chat-field-script', 'fluentform_chat', [ 'message' => $message, ] ); wp_enqueue_script('fluentform-chat-field-script'); } public function enableIntegration($isEnabled) { add_filter('fluentform/global_addons', function($addOns) use ($isEnabled) { $addOns[$this->integrationKey] = [ 'title' => 'OpenAI ChatGPT', 'description' => __('Connect OpenAI ChatGPT to add integrations or create forms using AI prompts', 'fluentformpro'), 'logo' => fluentFormMix('img/integrations/openai.png'), 'enabled' => ($isEnabled) ? 'yes' : 'no', 'config_url' => admin_url('admin.php?page=fluent_forms_settings#general-openai-settings'), 'category' => '', //Category : All ]; return $addOns; }, 9); } public function addGlobalMenu($setting) { $setting[$this->integrationKey] = [ 'hash' => 'general-' . $this->integrationKey . '-settings', 'component' => 'general-integration-settings', 'settings_key' => $this->integrationKey, 'title' => 'ChatGPT Integration', ]; return $setting; } public function getGlobalSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'access_token' => '' ]; return wp_parse_args($globalSettings, $defaults); } public function getGlobalFields($fields) { return [ 'logo' => fluentFormMix('img/integrations/openai.png'), 'menu_title' => __('OpenAI ChatGPT Integration', 'fluentformpro'), 'menu_description' => __('The OpenAI ChatGPT API can be applied to create forms and dynamic submission confirmation message.', 'fluentformpro'), 'valid_message' => __('Your OpenAI ChatGPT connection is valid', 'fluentformpro'), 'invalid_message' => __('Your OpenAI ChatGPT connection is not valid', 'fluentformpro'), 'save_button_text' => __('Verify OpenAI ChatGPT', 'fluentformpro'), 'fields' => [ 'button_link' => [ 'type' => 'link', 'link_text' => __('Get OpenAI ChatGPT API Keys', 'fluentformpro'), 'link' => 'https://platform.openai.com/account/api-keys', 'target' => '_blank', 'tips' => __('Please click on this link get API keys from OpenAI ChatGPT.', 'fluentformpro'), ], 'access_token' => [ 'type' => 'password', 'placeholder' => __('API Keys', 'fluentformpro'), 'label_tips' => __("Please find API Keys by clicking 'Get OpenAI ChatGPT API Keys' Button then paste it here", 'fluentformpro'), 'label' => __('Access Code', 'fluentformpro'), ] ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => __('Your OpenAI ChatGPT integration is up and running', 'fluentformpro'), 'button_text' => __('Disconnect OpenAI ChatGPT', 'fluentformpro'), 'data' => [ 'access_token' => '' ], 'show_verify' => true ] ]; } public function saveGlobalSettings($settings) { $token = $settings['access_token']; if (empty($token)) { $integrationSettings = [ 'access_token' => '', 'status' => false ]; // Update the reCaptcha details with siteKey & secretKey. update_option($this->optionKey, $integrationSettings, 'no'); wp_send_json_success([ 'message' => __('Your settings has been updated', 'fluentformpro'), 'status' => false ], 200); } // Verify API key now try { $isAuth = $this->api->isAuthenticated($token); if ($isAuth && !is_wp_error($isAuth)) { $token = [ 'status' => true, 'access_token' => $settings['access_token'] ]; } else { throw new \Exception($isAuth->get_error_message(), $isAuth->get_error_code()); } update_option($this->optionKey, $token, 'no'); } catch (\Exception $exception) { wp_send_json_error([ 'message' => $exception->getMessage() ], 400); } wp_send_json_success([ 'message' => __('Your OpenAI ChatGPT API key has been verified and successfully set', 'fluentformpro'), 'status' => true ], 200); } public function addNotificationType($types) { $types[] = $this->settingsKey; return $types; } public function pushIntegration($integrations, $formId) { $integrations[$this->integrationKey] = [ 'title' => 'OpenAI ChatGPT', 'logo' => fluentFormMix('img/integrations/openai.png'), 'is_active' => $this->isEnabled(), 'configure_title' => __('Configuration required!', 'fluentformpro'), 'global_configure_url' => admin_url('admin.php?page=fluent_forms_settings#general-openai-settings'), 'configure_message' => __('OpenAI ChatGPT is not configured yet! Please configure your OpenAI api first', 'fluentformpro'), 'configure_button_text' => __('Set OpenAI ChatGPT API', 'fluentformpro') ]; return $integrations; } public function setFeedAttributes($feed, $formId) { $feed['provider'] = $this->integrationKey; $feed['provider_logo'] = fluentFormMix('img/integrations/openai.png'); return $feed; } public function getIntegrationDefaults($settings, $formId) { return [ 'name' => '', 'role' => '', 'prompt_field' => '', 'conditionals' => [ 'conditions' => [], 'status' => false, 'type' => 'all' ], 'enabled' => true ]; } public function getSettingsFields($settings, $formId) { return [ 'fields' => [ [ 'key' => 'name', 'label' => __('Feed Name', 'fluentformpro'), 'required' => true, 'placeholder' => __('Your Feed Name', 'fluentformpro'), 'component' => 'text' ], [ 'key' => 'role', 'label' => __('Select Role', 'fluentformpro'), 'tips' => __('Select how the AI should respond and behave', 'fluentformpro'), 'required' => true, 'component' => 'select', 'options' => [ 'system' => __('System', 'fluentformpro'), 'assistant' => __('Assistant', 'fluentformpro'), 'user' => __('User', 'fluentformpro') ] ], [ 'key' => 'prompt_field', 'label' => __('Write Query', 'fluentformpro'), 'placeholder' => __('Write your query to get OpenAI ChatGPT generated result', 'fluentformpro'), 'tips' => __('Write your query to get OpenAI ChatGPT generated result', 'fluentformpro'), 'required' => true, 'component' => 'value_textarea', ], [ 'require_list' => false, 'key' => 'conditionals', 'label' => __('Conditional Logics', 'fluentformpro'), 'tips' => __('Allow this integration conditionally based on your submission values', 'fluentformpro'), 'component' => 'conditional_block' ], [ 'require_list' => false, 'key' => 'enabled', 'label' => __('Status', 'fluentformpro'), 'component' => 'checkbox-single', 'checkbox_label' => __('Enable this feed', 'fluentformpro') ] ], 'button_require_list' => false, 'integration_title' => 'OpenAI ChatGPT' ]; } public function setMetaKey($data) { $data['meta_key'] = $this->settingsKey; return $data; } public function prepareIntegrationFeed($setting, $feed, $formId) { $defaults = $this->getIntegrationDefaults([], $formId); foreach ($setting as $settingKey => $settingValue) { if ('true' == $settingValue) { $setting[$settingKey] = true; } elseif ('false' == $settingValue) { $setting[$settingKey] = false; } elseif ('conditionals' == $settingKey) { if ('true' == $settingValue['status']) { $settingValue['status'] = true; } elseif ('false' == $settingValue['status']) { $settingValue['status'] = false; } $setting['conditionals'] = $settingValue; } } if (!empty($setting['list_id'])) { $setting['list_id'] = (string)$setting['list_id']; } return wp_parse_args($setting, $defaults); } public function validate($settings, $integrationId, $formId) { $error = false; $errors = []; if (empty($settings['role'])) { $error = true; $errors['role'] = __('Select Role is required', 'fluentformpro'); } if (empty($settings['prompt_field'])) { $error = true; $errors['prompt_field'] = __('Write query is required', 'fluentformpro'); } if ($error) { wp_send_json_error([ 'message' => __('Validation Failed', 'fluentformpro'), 'errors' => $errors ], 423); } return $settings; } private function isEnabled() { $globalModules = get_option('fluentform_global_modules_status'); $openAiModule = ArrayHelper::get($globalModules, $this->integrationKey); if ($openAiModule == 'yes') { return true; } return false; } private function getFeeds($formId = '') { if (!$formId) { $request = $this->app->request->get(); $formId = ArrayHelper::get($request, 'form_id'); } $feeds = []; if ($formId) { $feeds = FormMeta::when($formId, function($q) use ($formId) { return $q->where('form_id', $formId); })->where('meta_key', $this->settingsKey)->get()->toArray(); } return $feeds; } public function insertAllEditorShortcode($data = []) { $feeds = $this->getFeeds(); if (!$feeds) { return $data; } $chatGPTShortCodesContainer = [ 'title' => __('ChatGPT', 'fluentformpro'), 'shortcodes' => [] ]; foreach ($feeds as $feed) { $value = json_decode(ArrayHelper::get($feed, 'value'), true); if (!ArrayHelper::isTrue($value, 'enabled')) { continue; } $feedId = ArrayHelper::get($feed, 'id'); $formId = ArrayHelper::get($feed, 'form_id'); $feedName = ArrayHelper::get($value, 'name'); $chatGPTShortCodesContainer['shortcodes']['{chat_gpt_response.'. $formId . '_' . $feedId . '}'] = __(sprintf('ChatGPT Response for %s', $feedName), 'fluentformpro'); } $data[] = $chatGPTShortCodesContainer; return $data; } public function chatGPTSubmissionMessageHandler($formId, $feedId, $parser) { $feed = FormMeta ::where('id', $feedId) ->where('form_id', $formId) ->where('meta_key', $this->settingsKey) ->first(); if (!$feed) { return ''; } $value = json_decode($feed->value, true); if (!ArrayHelper::isTrue($value, 'enabled')) { return ''; } $role = ArrayHelper::get($value, 'role'); $content = ArrayHelper::get($value, 'prompt_field'); $submission = $parser::getEntry(); $submittedData = \json_decode($submission->response, true); $submissionId = $submission->id; $form = $parser::getForm(); $content = ShortCodeParser::parse( $content, $submissionId, $submittedData, $form, false, true ); $args = [ "role" => $role, "content" => $content ]; $result = $this->api->makeRequest($args); if (is_wp_error($result)) { return ''; } return trim(ArrayHelper::get($result, 'choices.0.message.content'), '"'); } public function beforeFormRenderCss($class, $form) { $formSettings = $form->settings; $message = ArrayHelper::get($formSettings, 'confirmation.messageToShow'); $hasChatGpt = ArrayHelper::get($formSettings, 'confirmation.redirectTo') === 'samePage' && strpos($message, '{chat_gpt_response.') !== false; if ($hasChatGpt) { $class .= ' ff-has-chat-gpt'; $this->loadScripts(); } return $class; } // ajax handler for chat field /*public function chatCompletion() { $request = $this->app->request->get(); $formId = ArrayHelper::get($request, 'form_id', ''); $form = Form::find($formId); $fields = ArrayHelper::get(json_decode($form->form_fields, true), 'fields'); $role = ''; $content = ArrayHelper::get($request, 'content'); $failedMessage = ''; foreach ($fields as $field) { if (ArrayHelper::get($field, 'element') == 'chat') { $role = ArrayHelper::get($field, 'settings.open_ai_role'); $content = $content ?: ArrayHelper::get($field, 'settings.open_ai_content'); $failedMessage = ArrayHelper::get($field, 'settings.failed_message'); } } $args = [ "role" => $role, "content" => $content ]; $token = ArrayHelper::get(get_option($this->optionKey), 'access_token'); $result = $this->makeRequest($token, $args); if (is_wp_error($result)) { wp_send_json_error($failedMessage, 422); } wp_send_json_success($result, 200); }*/ } PK!u:)@)@$src/classes/Chat/ChatFormBuilder.phpnu[generateForm($this->app->request->all()); $form = $this->prepareAndSaveForm($form); wp_send_json_success([ 'formId' => $form->id, 'redirect_url' => admin_url( 'admin.php?page=fluent_forms&form_id=' . $form->id . '&route=editor' ), 'message' => __('Successfully created a form.', 'fluentform'), ], 200); } catch (Exception $e) { wp_send_json_error([ 'message' => $e->getMessage(), ], 422); } } /** * @param array $form * @throws Exception * @return Form|\FluentForm\Framework\Database\Query\Builder */ protected function prepareAndSaveForm($form) { $allFields = $this->getDefaultFields(); $fluentFormFields = []; $fields = Arr::get($form, 'fields', []); $isConversational = Arr::isTrue($form, 'is_conversational'); $hasStep = false; $lastFieldIndex = count($fields) - 1; foreach ($fields as $index => $field) { if ($inputKey = $this->resolveInput($field)) { if (!$hasStep && 'form_step' === $inputKey) { if (0 === $index || $lastFieldIndex === $index) { continue; } $hasStep = true; } $fluentFormFields[] = $this->processField($inputKey, $field, $allFields); } } $fluentFormFields = $this->maybeAddPayments($fluentFormFields, $allFields); $fluentFormFields = array_filter($fluentFormFields); if (!$fluentFormFields) { throw new Exception(__('Empty form. Please try again!', 'fluentformpro')); } $title = Arr::get($form, 'title', ''); return $this->saveForm($fluentFormFields, $title, $hasStep, $isConversational); } /** * @param array $args * @throws Exception * @return array response form fields */ protected function generateForm($args) { $startingQuery = "Create a form for "; $query = \FluentForm\Framework\Support\Sanitizer::sanitizeTextField(Arr::get($args, 'query')); if (empty($query)) { throw new Exception(__('Query is empty!', 'fluentformpro')); } $additionalQuery = \FluentForm\Framework\Support\Sanitizer::sanitizeTextField(Arr::get($args, 'additional_query')); if ($additionalQuery) { $query .= "\n including questions for information like " . $additionalQuery . "."; } $query .= "\nField includes 'type', 'name', 'label', 'placeholder', 'required' status. \nIf field has 'options', it will be format 'value' 'label' pair. \nIf has field like full name, first name, last name, field key type will be 'name'. If has field like phone, field key type will be 'phone'. \nIf has field like payment, field key type will be 'payment'. \nIf has field like rating, review, feedback, star, field key type will be 'ratings' and include options as label value pair. \nIf has field like slider, range, scale, field key type will be 'range' and include min and max value as property of field array. \nIf has field like layout, container, field key type will be 'container' and include fields on 'fields' array. \nIf form has steps, tabs, multipage or multi-page, add a field key with type 'steps' on every step break. \nAdd 'is_conversational' key to define the form is conversational form or not. \nAdd 'title' key to define the form title. \nIgnore my previous chat history. \nReturn the form data in JSON format, adhering to FluentForm's structure. Only include the form fields inside the 'fields' array."; $args = [ "role" => 'system', "content" => $startingQuery . $query, ]; $result = (new ChatApi())->makeRequest($args); $response = trim(Arr::get($result, 'choices.0.message.content'), '"'); $response = json_decode($response, true); if (is_wp_error($response) || empty($response['fields'])) { throw new Exception(__('Invalid response: Please try again! :', 'fluentformpro')); } return $response; } protected function getDefaultFields() { $components = wpFluentForm()->make('components')->toArray(); //todo remove disabled elements $disabledComponents = $this->getDisabledComponents(); if(!(isset($components['payments']))){ $components['payments'] = []; } $general = Arr::get($components, 'general', []); $advanced = Arr::get($components, 'advanced', []); $container = Arr::get($components, 'container', []); $payments = Arr::get($components, 'payments', []); return array_merge($general, $advanced, $payments, ['container' => $container]); } protected function getElementByType($allFields, $type) { foreach ($allFields as $element) { if (isset($element['element']) && $element['element'] === $type) { return $element; } } return null; } protected function processField($inputKey, $field, $allFields) { if ('container' == $inputKey) { $fields = Arr::get($field, 'fields', []); return $this->resolveContainerFields($fields, $allFields); } $matchedField = $this->getElementByType($allFields, $inputKey); if (!$matchedField) { return []; } $matchedField['uniqElKey'] = "el_" . uniqid(); $matchedFieldType = Arr::get($matchedField, 'element'); if ('form_step' === $inputKey) { return $matchedField; } if ($fieldName = Arr::get($field, 'name')) { $matchedField['attributes']['name'] = $fieldName; } if ($label = Arr::get($field, 'label')) { $required = Arr::isTrue($field, 'required'); if (isset($matchedField['settings']['label'])) { $matchedField['settings']['label'] = $label; if (isset($matchedField['settings']['validation_rules']['required']['value'])) { $matchedField['settings']['validation_rules']['required']['value'] = $required; } } $placeholder = Arr::get($field, 'placeholder'); if ($placeholder) { if (isset($matchedField['attributes']['placeholder'])) { $matchedField['attributes']['placeholder'] = $placeholder; } elseif (isset($matchedField['settings']['placeholder'])) { $matchedField['settings']['placeholder'] = $placeholder; } } if (isset($matchedField['fields'])) { $subFields = $matchedField['fields']; $subNames = explode(" ", $label); if (count($subNames) > 1) { $counter = 0; foreach ($subFields as $subFieldkey => $subFieldValue) { if (Arr::get($subNames, $counter)) { if (Arr::has($subFieldValue, 'settings.visible') && !Arr::isTrue($subFieldValue, 'settings.visible')) { continue; } if (isset($subFieldValue['settings']['label'])) { $subFields[$subFieldkey]['settings']['label'] = Arr::get($subNames, $counter); $subFields[$subFieldkey]['settings']['validation_rules']['required']['value'] = $required; } $counter++; } } } $matchedField['fields'] = $subFields; } } if ($options = $this->getOptions(Arr::get($field, 'options'))) { if (isset($matchedField['settings']['advanced_options'])) { $matchedField['settings']['advanced_options'] = $options; } if ('ratings' == $matchedFieldType) { $matchedField['options'] = array_column($options, 'label', 'value'); } } if ('rangeslider' == $matchedFieldType) { if ($min = Arr::get($field, 'min')) { $matchedField['attributes']['min'] = intval($min); } if ($max = intval(Arr::get($field, 'max', 10))) { $matchedField['attributes']['max'] = $max; } } return $matchedField; } protected function resolveInput($field) { $type = Arr::get($field, 'type'); $searchTags = fluentformLoadFile('Services/FormBuilder/ElementSearchTags.php'); $form = ['type'=>'']; $form = json_decode(json_encode($form)); $searchTags = apply_filters('fluentform/editor_element_search_tags', $searchTags, $form); foreach ($searchTags as $inputKey => $tags) { if (array_search($type, $tags) !== false) { return $inputKey; } else { foreach ($tags as $tag) { if (strpos($tag, $type) !== false) { return $inputKey; } } } } return false; } protected function getOptions($options = []) { $formattedOptions = []; if (empty($options) || !is_array($options)) { return $options; } foreach ($options as $key => $option) { if (is_string($option) || is_numeric($option)) { $value = $label = $option; } elseif (is_array($option)) { $label = Arr::get($option, 'label'); $value = Arr::get($option, 'value'); } else { continue; } if (!$value || !$label) { $value = $value ?? $label; $label = $label ?? $value; } if (!$value || !$label) { continue; } $formattedOptions[] = [ 'label' => $label, 'value' => $value, ]; } return $formattedOptions; } protected function getBlankFormConfig() { $attributes = ['type' => 'form', 'predefined' => 'blank_form']; $customForm = Form::resolvePredefinedForm($attributes); $customForm['form_fields'] = json_decode($customForm['form_fields'], true); $customForm['form_fields']['submitButton'] = $customForm['form']['submitButton']; $customForm['form_fields'] = json_encode($customForm['form_fields']); return $customForm; } protected function saveForm($formattedInputs, $title, $isStepFrom = false, $isConversational = false) { $customForm = $this->getBlankFormConfig(); $fields = json_decode($customForm['form_fields'], true); $submitButton = $customForm['form']['submitButton']; $fields['form_fields']['fields'] = $formattedInputs; $fields['form_fields']['submitButton'] = $submitButton; if ($isStepFrom) { $fields['form_fields']['stepsWrapper'] = $this->getStepWrapper(); } $customForm['form_fields'] = json_encode($fields['form_fields']); $data = Form::prepare($customForm); $form = $this->model->create($data); $form->title = $title ?? $form->title . ' (ChatGPT#' . $form->id . ')'; if ($isConversational) { $formMeta = FormMeta::prepare(['type' => 'form', 'predefined' => 'conversational'], $customForm); $form->fill([ 'form_fields' => Converter::convertExistingForm($form), ])->save(); } else { $form->save(); $formMeta = FormMeta::prepare(['type' => 'form', 'predefined' => 'blank_form'], $customForm); } FormMeta::store($form, $formMeta); do_action('fluentform/inserted_new_form', $form->id, $data); return $form; } protected function maybeAddPayments($fluentFormFields, $allFields) { $paymentElements = ['payment_method', 'multi_payment_component']; $foundElements = []; if (empty($fluentFormFields)) { return []; } foreach ($fluentFormFields as $item) { if (in_array(Arr::get($item, "element", []), $paymentElements)) { $foundElements[] = $item["element"]; } } // Find the elements in $paymentElements that are not in $foundElements $remainingElements = array_diff($paymentElements, $foundElements); $formPaymentElm = []; if ($foundElements && !empty($remainingElements)) { foreach ($remainingElements as $elmKey) { $formPaymentElm[] = $this->getElementByType($allFields, $elmKey); } return array_merge($fluentFormFields, $formPaymentElm); } return $fluentFormFields; } protected function resolveContainerFields($fields, $allFields) { $fieldsCount = count($fields); if (!$fieldsCount || $fieldsCount > 6) { return []; } $matchedField = Arr::get($allFields, 'container.container_' . $fieldsCount . '_col'); if (!$matchedField) { return []; } $columnWidth = round(100 / $fieldsCount, 2); $formattedColumnsFields = []; foreach ($fields as $field) { if ($fieldKey = $this->resolveInput($field)) { if ($columnField = $this->processField($fieldKey, $field, $allFields)) { $formattedColumnsFields[] = [ 'width' => $columnWidth, 'fields' => [$columnField], ]; } } } if ($formattedColumnsFields) { $matchedField['columns'] = $formattedColumnsFields; } else { return []; } return $matchedField; } /** * @return array */ protected function getStepWrapper() { return [ 'stepStart' => [ 'element' => 'step_start', 'attributes' => [ 'id' => '', 'class' => '', ], 'settings' => [ 'progress_indicator' => 'progress-bar', 'step_titles' => [], 'disable_auto_focus' => 'no', 'enable_auto_slider' => 'no', 'enable_step_data_persistency' => 'no', 'enable_step_page_resume' => 'no', ], 'editor_options' => [ 'title' => 'Start Paging' ], ], 'stepEnd' => [ 'element' => 'step_end', 'attributes' => [ 'id' => '', 'class' => '', ], 'settings' => [ 'prev_btn' => [ 'type' => 'default', 'text' => 'Previous', 'img_url' => '' ] ], 'editor_options' => [ 'title' => 'End Paging' ], ] ]; } } PK!ZRP#P#src/classes/Chat/ChatField.phpnu[ 25, 'element' => $this->key, 'attributes' => [ 'name' => $this->key, 'class' => '', 'value' => '', 'type' => '', 'placeholder' => __('Chat with OpenAI ChatGPT', 'fluentformpro') ], 'settings' => [ 'container_class' => '', 'placeholder' => '', 'label' => $this->title, 'label_placement' => '', 'help_message' => '', 'admin_field_label' => '', 'validation_rules' => [ 'required' => [ 'value' => false, 'global' => true, 'message' => Helper::getGlobalDefaultMessage('required'), 'global_message' => Helper::getGlobalDefaultMessage('required'), ], ], 'conditional_logics' => [], 'disable_submit_button' => false, 'open_ai_role' => 'system', 'open_ai_content' => __('You are a helpful assistant.', 'fluentformpro'), 'self_chat_bg_color' => '#EEF1F6', 'reply_chat_bg_color' => '#FBF5F4', 'failed_message' => __('An error has been occurred! Please try again.', 'fluentformpro'), 'show_chat_limit' => 10, ], 'editor_options' => [ 'title' => $this->title, 'icon_class' => 'el-icon-chat-line-square', 'template' => 'inputText' ], ]; } public function getGeneralEditorElements() { return [ 'label', 'admin_field_label', 'placeholder', 'value', 'label_placement', 'validation_rules', 'disable_submit_button', 'open_ai_role', 'open_ai_content' ]; } public function generalEditorElement() { return [ 'disable_submit_button' => [ 'template' => 'radio', 'label' => __('Disable Submit Button', 'fluentformpro'), 'options' => [ [ 'value' => true, 'label' => __('Yes', 'fluentformpro'), ], [ 'value' => false, 'label' => __('No', 'fluentformpro'), ], ], ], 'open_ai_role' => [ 'template' => 'select', 'label' => __('Select Role', 'fluentformpro'), 'help_text' => 'Select a Role Type', 'options' => [ [ 'label' => __('System', 'fluentformpro'), 'value' => 'system' ], [ 'label' => __('User', 'fluentformpro'), 'value' => 'user' ], [ 'label' => __('Assistant', 'fluentformpro'), 'value' => 'assistant' ], ], ], 'open_ai_content' => [ 'template' => 'inputTextarea', 'label' => __('OpenAI ChatGPT Content', 'fluentformpro'), 'help_text' => __('How AI gonna Behave?', 'fluentformpro'), ] ]; } public function getAdvancedEditorElements() { return [ 'name', 'help_message', 'container_class', 'class', 'conditional_logics', 'self_chat_bg_color', 'reply_chat_bg_color', 'failed_message', 'show_chat_limit' ]; } public function advancedEditorElement() { return [ 'self_chat_bg_color' => [ 'template' => 'inputText', 'label' => __('Self Chat BG Color', 'fluentformpro'), 'help_text' => __('Set self typed chat background color', 'fluentformpro') ], 'reply_chat_bg_color' => [ 'template' => 'inputText', 'label' => __('Reply Chat BG color', 'fluentformpro'), 'help_text' => __('Set replied chat background color', 'fluentformpro'), ], 'failed_message' => [ 'template' => 'inputText', 'label' => __('Failed Message', 'fluentformpro'), 'help_text' => __('Set failure message if error occurs', 'fluentformpro'), ], 'show_chat_limit' => [ 'template' => 'inputText', 'label' => __('Show Chat Count', 'fluentformpro'), 'help_text' => __('Total chat to show in the DOM including self reply', 'fluentformpro') ] ]; } public function render($data, $form) { $elementName = $data['element']; $data = apply_filters('fluentform/rendering_field_data_' . $elementName, $data, $form); $textareaValue = $this->extractValueFromAttributes($data); $data['attributes']['class'] = trim('ff-el-form-control ' . $data['attributes']['class']); $data['attributes']['id'] = $this->makeElementId($data, $form); if ($tabIndex = Helper::getNextTabIndex()) { $data['attributes']['tabindex'] = $tabIndex; } $ariaRequired = 'false'; if (ArrayHelper::get($data, 'settings.validation_rules.required.value')) { $ariaRequired = 'true'; } $data = $this->pushScripts($data, $form); $elMarkup = ''; $atts = $this->buildAttributes($data['attributes']); $elMarkup = sprintf( $elMarkup, $atts, esc_attr($textareaValue) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $atts is escaped before being passed in. $html = $this->buildElementMarkup($elMarkup, $data, $form); $this->printContent('fluentform/rendering_field_html_' . $elementName, $html, $data, $form); } private function pushScripts($data, $form) { $token = ArrayHelper::get(get_option('_fluentform_openai_settings'), 'access_token'); $sendSvgIcon = ''; $chatSvgIcon = apply_filters('fluentform/chat_field_send_icon', $sendSvgIcon); wp_register_script( 'fluentform-chat-field-script', FLUENTFORMPRO_DIR_URL . 'public/js/chatFieldScript.js', ['jquery'], FLUENTFORMPRO_VERSION, true ); wp_enqueue_script('fluentform-chat-field-script'); wp_localize_script( 'fluentform-chat-field-script', 'fluentform_chat', [ 'nonce' => wp_create_nonce(), 'content' => ArrayHelper::get($data, 'settings.open_ai_content'), 'disable_submit_button' => ArrayHelper::get($data, 'settings.disable_submit_button'), 'send_svg_icon' => $chatSvgIcon, 'self_chat_bg_color' => ArrayHelper::get($data, 'settings.self_chat_bg_color'), 'reply_chat_bg_color' => ArrayHelper::get($data, 'settings.reply_chat_bg_color'), 'show_chat_limit' => ArrayHelper::get($data, 'settings.show_chat_limit') ] ); $data['attributes']['data-ff-chat-field'] = "true"; return apply_filters('fluentform/chat_field_before_render', $data, $form); } } PK!%5src/classes/EntriesImport/EntriesImportController.phpnu[app = App::getInstance(); $this->service = new EntriesImportService(); } public function boot() { $this->app->addAction('wp_ajax_fluentform-import-entries-map-fields', [$this, 'mappingFields']); $this->app->addAction('wp_ajax_fluentform-import-entries', [$this, 'importEntries']); } public function mappingFields() { try { Acl::verify('fluentform_manage_entries', null, __('You do not have permission to perform this action.', 'fluentformpro'), false); $attrs = array_merge($this->app->request->all(), ['file' => $this->app->request->file('file')]); wp_send_json([ 'success' => true, 'data' => $this->service->mappingFields($attrs) ], 200); } catch (\Exception $exception) { wp_send_json([ 'success' => false, 'message' => $exception->getMessage() ], 424); } } public function importEntries() { try { Acl::verify('fluentform_manage_entries', null, __('You do not have permission to perform this action.', 'fluentformpro'), false); $attrs = array_merge($this->app->request->all(), ['file' => $this->app->request->file('file')]); wp_send_json([ 'success' => true, 'data' => $this->service->importEntries($attrs) ], 200); } catch (\Exception $exception) { wp_send_json([ 'success' => false, 'message' => $exception->getMessage() ], 424); } } }PK!|w,"WW2src/classes/EntriesImport/EntriesImportService.phpnu[prepare($attrs); if ($this->isCsvFile()) { $this->formatCsvFileData(); } elseif ($this->isJsonFile()) { $this->formatJsonFileData(); } return [ 'has_lots_of_entries' => $this->hasLotsOfData, 'mapping_fields' => $this->formattedFileData, 'form_fields' => $this->getFormattedFormFields(), 'submission_info_fields' => $this->getFormattedSubmissionInfoFields(), ]; } /** * @throws Exception */ public function importEntries($attrs) { $this->prepare($attrs); if (Arr::isTrue($attrs, 'delete_existing_submissions')) { $this->resetEntries(); } if ($this->isCsvFile()) { return $this->importFromCsvFile(); } elseif ($this->isJsonFile()) { return $this->importFromJsonFile(); } $this->failed(); } /** * @throws Exception */ protected function prepare($attrs) { $this->attrs = $attrs; $this->setFile(Arr::get($attrs, 'file')); $fileType = Arr::get($attrs, 'file_type'); if ( (!$this->isCsvFile() && !$this->isJsonFile()) || ($this->isCsvFile() && 'csv' != $fileType) || ($this->isJsonFile() && 'json' != $fileType) ) { $this->failed(); } $this->setForm(Arr::get($attrs, 'form_id')); $this->setFileData(); } /** * @throws Exception */ protected function formatCsvFileData() { $data = $this->getCsvData(); if (is_array($data) && count($data) && is_array($data[0])) { $this->hasLotsOfData = count($data) > 1000; foreach ($data[0] as $value) { $this->formattedFileData[] = [ 'label' => $value, 'value' => $value ]; } return; } $this->failed("You have a faulty csv file, please import correct file."); } /** * @throws Exception */ protected function formatJsonFileData() { $firstEntry = Arr::get($this->fileData, 0, []); if (!isset($firstEntry['response'])) { $this->failed(); } Arr::forget($firstEntry, 'response'); Arr::forget($firstEntry, 'id'); Arr::forget($firstEntry, 'form_id'); $formattedFileDate = [ 'form_fields' => [], 'submission_info_fields' => [], ]; if ($userInputs = Arr::get($firstEntry, 'user_inputs')) { $formInputs = FormFieldsParser::getEntryInputs($this->form, ['admin_label', 'element']); foreach ($userInputs as $key => $value) { $formattedFileDate['form_fields'][] = [ 'label' => Arr::get($formInputs, "$key.admin_label", $key), 'value' => $key ]; } Arr::forget($firstEntry, 'user_inputs'); } foreach ($firstEntry as $name => $value) { $formattedFileDate['submission_info_fields'][] = [ 'label' => $name, 'value' => $name, ]; } $this->formattedFileData = $formattedFileDate; } /** * @return array * @throws Exception */ protected function importFromCsvFile() { $csvData = $this->getCsvData(); if (is_array($csvData) && count($csvData) && is_array($csvData[0])) { list($formMappingFields, $submissionInfoMappingFields, $formInputs) = $this->getResponsibleMappingFields(); $csvHeader = array_flip(array_shift($csvData)); $newSubmissions = []; $this->hasLotsOfData = count($csvData) > 1000; $oldMaxExecutionTime = $this->maybeIncreaseMaxExecutionTime(); foreach ($csvData as $data) { $newSubmission = []; // Form Field Mapping $newResponse = []; $this->resolveFormFieldMapping($formMappingFields, $data, $newResponse, $formInputs, $csvHeader); if (!$newResponse) { continue; } $newSubmission['response'] = \json_encode($newResponse); // Submission Info Mapping $this->resolveSubmissionInfoMapping($submissionInfoMappingFields, $data, $newSubmission, $csvHeader); $newSubmissions[] = $newSubmission; } if ($newSubmissions) { $response = $this->insertSubmissions($newSubmissions); if ($oldMaxExecutionTime) { ini_set('max_execution_time', $oldMaxExecutionTime); } return $response; } } $this->failed("File has not data to import"); } /** * @throws Exception */ protected function importFromJsonFile() { list($formMappingFields, $submissionInfoMappingFields, $formInputs) = $this->getResponsibleMappingFields(); $newSubmissions = []; $oldMaxExecutionTime = $this->maybeIncreaseMaxExecutionTime(); foreach ($this->fileData as $data) { $newSubmission = []; $response = Arr::get($data, 'response'); if (!is_array($response)) { continue; } // Form Field Mapping $newResponse = []; $this->resolveFormFieldMapping($formMappingFields, $response, $newResponse, $formInputs); if (!$newResponse) { continue; } $newSubmission['response'] = \json_encode($newResponse); // Submission Info Mapping $this->resolveSubmissionInfoMapping($submissionInfoMappingFields, $data, $newSubmission); $newSubmissions[] = $newSubmission; } if ($newSubmissions) { $response = $this->insertSubmissions($newSubmissions); if ($oldMaxExecutionTime) { ini_set('max_execution_time', $oldMaxExecutionTime); } return $response; } $this->failed("File has not data to import"); } protected function maybeIncreaseMaxExecutionTime() { $oldMaxExecutionTime = false; if ($this->hasLotsOfData && function_exists('ini_set')) { $oldMaxExecutionTime = ini_set('max_execution_time', '300'); // set max execution time 5 min } return $oldMaxExecutionTime; } /** * @throws Exception */ protected function setForm($formId) { if ($form = Form::find(intval($formId))) { $this->form = $form; return; } $this->failed('Form not found, please select correct form.'); } /** * @throws Exception */ protected function setFile($file) { if ($file instanceof File) { $this->file = $file; return; } $this->failed(); } /** * @throws Exception */ protected function setFileData() { if ($data = $this->file->getContents()) { if ($this->isJsonFile()) { if (Helper::isJson($data)) { $data = \json_decode($data, true); } if (!is_array($data)) { $this->failed(); } if (!count($data)) { $this->failed(); } $this->hasLotsOfData = count($data) > 1000; } $this->fileData = $data; return; } $this->failed(); } protected function isCsvFile() { return 'csv' == $this->file->getClientOriginalExtension(); } protected function isJsonFile() { return 'json' == $this->file->getClientOriginalExtension(); } /** * Throws failed exception * * @throws Exception */ protected function failed($message = '') { if ($message) { $message = __($message, 'fluentformpro'); } else { $type = Arr::get($this->attrs, 'file_type', ''); $message = __("You have a faulty $type file, please import correct file.", 'fluentformpro'); } throw new Exception($message); } /** * Return responsible mapping fields as array list * * @return array [$formMappingField, $submissionInfoMappingField, $formInputs] */ protected function getResponsibleMappingFields() { $formMappingFields = Arr::get($this->attrs, 'form_fields', []); if (Helper::isJson($formMappingFields)) { $formMappingFields = \json_decode($formMappingFields, true); } $submissionInfoFields = Arr::get($this->attrs, 'submission_info_fields', []); if (Helper::isJson($submissionInfoFields)) { $submissionInfoFields = \json_decode($submissionInfoFields, true); } $formInputs = FormFieldsParser::getInputs($this->form, ['element', 'attributes', 'admin_label', 'raw']); return [$formMappingFields, $submissionInfoFields, $formInputs]; } protected function resolveFormFieldMapping($fields, $data, &$newResponse, $formFields, $csvHeader = []) { foreach ($fields as $field) { $bindingField = Arr::get($field, 'binding_field'); $fieldName = sanitize_text_field(Arr::get($field, 'value'), ''); if (!$bindingField || !$fieldName) { continue; } $formField = Arr::get($formFields, $fieldName, []); $formField['name'] = $fieldName; if ($this->isCsvFile()) { if (!isset($csvHeader, $bindingField)) { continue; } $fieldKey = $csvHeader[$bindingField]; } else { if (!isset($data, $bindingField)) { continue; } $fieldKey = $bindingField; } $fieldValue = $this->filterAndValidateFieldValue(Arr::get($data, $fieldKey), $formField); if (false !== $fieldValue) { $newResponse[$fieldName] = fluentFormSanitizer($fieldValue, $fieldName, $formField); } } } protected function resolveSubmissionInfoMapping($fields, $data, &$newData, $csvHeader = []) { $supportedSubmissionInfoFields = $this->getSubmissionInfoFields(); foreach ($fields as $field) { $bindingField = Arr::get($field, 'binding_field'); $fieldName = sanitize_text_field(Arr::get($field, 'value'), ''); if (!$bindingField || !$fieldName || !in_array($fieldName, $supportedSubmissionInfoFields)) { continue; } if ($this->isCsvFile()) { if (!isset($csvHeader, $bindingField)) { continue; } $fieldKey = Arr::get($csvHeader, $bindingField); } else { if (!isset($data, $bindingField)) { continue; } $fieldKey = $bindingField; } $fieldInfoValue = Arr::get($data, $fieldKey); // Skip, if submission info value is array, or object if (is_array($fieldInfoValue) || is_object($fieldInfoValue)) { continue; } $fieldInfoValue = fluentFormSanitizer($fieldInfoValue); if (in_array($fieldName, ['payment_total', 'total_paid']) && !is_numeric($fieldInfoValue)) { if (isset($newData['payment_status'])) { unset($newData['payment_status']); } if (isset($newData['payment_method'])) { unset($newData['payment_method']); } continue; } if (in_array($fieldName, ['payment_status', 'payment_method'])) { $fieldInfoValue = strtolower($fieldInfoValue); } $newData[$fieldName] = $fieldInfoValue; } } protected function filterAndValidateFieldValue($fieldValue, $formField) { $element = Arr::get($formField, 'element'); if (('select' == $element && Arr::isTrue($formField, 'attributes.multiple'))) { $element = 'multi_select'; } $formattedFieldValue = $fieldValue; $formattingFields = [ 'input_name', 'input_checkbox', 'multi_select', 'address', 'repeater_field', 'tabular_grid' ]; if (in_array($element, $formattingFields) && is_string($fieldValue)) { $formattedFieldValue = []; if ('input_name' == $element) { $formattedFieldValue['first_name'] = $fieldValue; } elseif (in_array($element, ['input_checkbox', 'multi_select'])) { if (strpos($fieldValue, ', ') !== false) { $formattedFieldValue = explode(', ', $fieldValue); } else { $formattedFieldValue[] = $fieldValue; } } elseif ('address' == $element) { $formattedFieldValue['address_line_1'] = $fieldValue; } elseif (in_array($element, ['repeater_field', 'tabular_grid'])) { $formattedFieldValue = false; } } $formData = [ $formField['name'] => $formattedFieldValue ]; if (method_exists(Helper::class, 'validateInput')) { if (Helper::validateInput($formField, $formData, $this->form)) { return false; } } return $formattedFieldValue; } /** * Return response array on success otherwise, throws fail Exception * * @param array $submissions * @return array response * @throws Exception */ protected function insertSubmissions($submissions) { $previousItem = Submission::where('form_id', $this->form->id) ->orderBy('id', 'DESC') ->first(); if ($previousItem) { $serialNumber = $previousItem->serial_number + 1; } else { $serialNumber = 1; } $isSubmissionInserted = false; foreach ($submissions as $submission) { if (!Arr::get($submission, 'user_id')) { $submission['user_id'] = get_current_user_id(); } if (!isset($submission['source_url'])) { $submission['source_url'] = ''; } if (!isset($submission['browser'])) { $submission['browser'] = ''; } if (!isset($submission['device'])) { $submission['device'] = ''; } if (!isset($submission['ip'])) { $submission['ip'] = ''; } if (!isset($submission['created_at'])) { $submission['created_at'] = current_time('mysql'); } $submission['updated_at'] = current_time('mysql'); $submission['form_id'] = $this->form->id; $submission['serial_number'] = $serialNumber; if ($insertId = Submission::insertGetId($submission)) { if (!$isSubmissionInserted) { $isSubmissionInserted = true; } if (isset($submission['response']) && Helper::isJson($submission['response']) && $submissionDetails = \json_decode($submission['response'], true)) { (new SubmissionService())->recordEntryDetails($insertId, $this->form->id, $submissionDetails); } $serialNumber++; } } if ($isSubmissionInserted) { return [ 'message' => __("Entries Imported Successfully", 'fluentformpro'), 'entries_page_url' => admin_url('admin.php?page=fluent_forms&route=entries&form_id=' . $this->form->id), ]; } $this->failed("File has not data to import"); } protected function getCsvData() { require_once(FLUENTFORMPRO_DIR_PATH . '/libs/CSVParser/CSVParser.php'); $csvParser = new \CSVParser(); $csvParser->load_data($this->fileData); $csvDelimiter = Arr::get($this->attrs, 'csv_delimiter'); if ('comma' == $csvDelimiter) { $csvDelimiter = ","; } elseif ('semicolon' == $csvDelimiter) { $csvDelimiter = ";"; } else { $csvDelimiter = $csvParser->find_delimiter(); } return $csvParser->parse($csvDelimiter); } protected function getFormattedFormFields() { $fields = FormFieldsParser::getFields($this->form, true); $inputs = FormFieldsParser::getInputs($this->form, ['admin_label']); $labels = $this->getFileDataAdminLabels('form_fields'); $flattenedFields = []; foreach ($fields as $field) { if ('container' === $field['element'] && $columns = Arr::get($field, 'columns')) { foreach ($columns as $column) { $flattenedFields = array_merge($flattenedFields, Arr::get($column, 'fields', [])); } } else { $flattenedFields[] = $field; } } $formattedFormFields = []; if ($this->isCsvFile()) { $flattenedFields = array_filter($flattenedFields, function ($field) { return !in_array($field['element'], ['tabular_grid', 'repeater_field']); }); } foreach ($flattenedFields as $field) { $name = Arr::get($field, 'attributes.name'); if (!$name) { continue; } $label = Arr::get($inputs, "$name.admin_label", $name); $bindingField = ''; if (in_array($label, $labels)) { $bindingField = $name; if ($this->isCsvFile()) { $bindingField = $label; } } $formattedFormFields[$name] = [ 'value' => $name, 'label' => $label, 'binding_field' => $bindingField, ]; } return $formattedFormFields; } protected function getFormattedSubmissionInfoFields() { $labels = $this->getFileDataAdminLabels('submission_info_fields'); $submissionInfoField = []; foreach ($this->getSubmissionInfoFields() as $field) { $bindingField = ''; if (in_array($field, $labels)) { $bindingField = $field; } $submissionInfoField[$field] = [ 'value' => $field, 'label' => $field, 'binding_field' => $bindingField, ]; } return $submissionInfoField; } protected function getFileDataAdminLabels($fieldKey = '') { $adminLabels = []; if ($this->formattedFileData) { if ($this->isJsonFile() && $fields = Arr::get($this->formattedFileData, $fieldKey, [])) { $adminLabels = array_column($fields, 'label'); } elseif ($this->isCsvFile()) { $adminLabels = array_column($this->formattedFileData, 'label'); } } return $adminLabels; } protected function getSubmissionInfoFields() { $submissionInfoFields = [ 'source_url', 'user_id', 'status', 'is_favourite', 'browser', 'device', 'ip', 'city', 'country', 'created_at', ]; if ($this->form->has_payment) { $submissionInfoFields = array_merge($submissionInfoFields, ['payment_status', 'payment_method', 'payment_type', 'currency', 'payment_total', 'total_paid']); } return $submissionInfoFields; } protected function resetEntries() { Submission::where('form_id', $this->form->id) ->delete(); SubmissionMeta::where('form_id', $this->form->id) ->delete(); EntryDetails::where('form_id', $this->form->id) ->delete(); FormAnalytics::where('form_id', $this->form->id) ->delete(); Log::where('parent_source_id', $this->form->id) ->whereIn('source_type', ['submission_item', 'form_item', 'draft_submission_meta']) ->delete(); if ($this->form->has_payment) { wpFluent()->table('fluentform_order_items') ->where('form_id', $this->form->id) ->delete(); wpFluent()->table('fluentform_transactions') ->where('form_id', $this->form->id) ->delete(); wpFluent()->table('fluentform_subscriptions') ->where('form_id', $this->form->id) ->delete(); } } } PK!x7H,H,1src/classes/Inventory/InventoryFieldsRenderer.phpnu[isPaymentField($field); $optionKey = $isPaymentInput ? 'pricing_options' : 'advanced_options'; $options = Arr::get($field, 'settings.' . $optionKey); if (empty($options)) { return $options; } $inventoryType = Arr::get($attr, 'inventoryType'); $maybeAllOptionStockOut = 'yes'; foreach ($options as $key => $option) { $item = [ 'parent_input_name' => Arr::get($field, 'attributes.name'), 'item_name' => Arr::get($option, 'label'), 'item_value' => Arr::get($option, 'value'), 'quantity' => Arr::get($option, 'quantity'), ]; if ('simple' == $inventoryType) { if ($isPaymentInput) { $itemPrice = \FluentFormPro\Payments\PaymentHelper::convertToCents($item['item_value']); $used = InventoryValidation::getPaymentItemSubmissionQuantity($attr['formId'], $item['parent_input_name'], $item['item_name'], $itemPrice); } else { $used = InventoryValidation::getRegularItemUsedQuantity($attr['previousSubmissionData'], $item); } $totalQuantity = Arr::get($option,'quantity'); } else { $inventorySlug = Arr::get($option, 'global_inventory'); if (!$inventorySlug) { continue; } list ($totalQuantity, $used) = $inventoryValidation->getGlobalInventoryInfo($inventorySlug); } $remaining = max($totalQuantity - $used, 0); if ($attr['showStock'] && $isPaymentInput) { $options[$key]['quantity_remaining'] = $remaining; $options[$key]['quantiy_label'] = str_replace('{remaining_quantity}', $remaining, $attr['stockLabel']); } elseif ($attr['showStock']) { $options[$key]['label'] .= str_replace('{remaining_quantity}', $remaining, $attr['stockLabel']); } if ($remaining > 0) { $maybeAllOptionStockOut = 'no'; } //maybe disable option stock out item $disableStockOut = Arr::get($field, 'settings.disable_input_when_stockout') == 'yes'; if($disableStockOut && $remaining <=0 ){ $options[$key]['disabled'] = true; } if ($attr['hideChoice'] && $remaining == 0) { unset($options[$key]); } } // Hide Inputs When All Option Is Stock-out $hideStockInput = Arr::get($field, 'settings.hide_input_when_stockout') == 'yes'; if ($maybeAllOptionStockOut == 'yes' && $hideStockInput) { $field['settings']['container_class'] .= 'has-conditions ff_excluded '; //condition to return false always if Stock-out for conversational form $field['settings']['conditional_logics'] = [ 'status' => true, 'type' => 'all', 'conditions' => [ [ 'field' => Arr::get($field, 'attributes.name'), 'operator' => '!=', 'value' => null ] ] ]; } $field['settings.' . $optionKey] = array_values($options); return $field; } public function adjustSinglePaymentItem($field, $form, $stockLabel, $inventoryType) { $itemName = Arr::get($field, 'settings.label'); $parentName = Arr::get($field, 'attributes.name'); $value = Arr::get($field, 'attributes.value'); $itemPrice = \FluentFormPro\Payments\PaymentHelper::convertToCents($value); if ($inventoryType == 'simple') { $availableQuantity = (int)Arr::get($field, 'settings.single_inventory_stock'); $usedQuantity = InventoryValidation::getPaymentItemSubmissionQuantity($form->id, $parentName, $itemName, $itemPrice); $remaining = max($availableQuantity - $usedQuantity, 0); } else { $inventoryValidation = (new InventoryValidation([], $form)); $inventorySlug = Arr::get($field, 'settings.global_inventory'); list ($totalQuantity, $usedQuantity) = $inventoryValidation->getGlobalInventoryInfo($inventorySlug); if (!$totalQuantity) { return $field; } $remaining = max($totalQuantity - $usedQuantity, 0); } $field['settings']['label'] .= str_replace('{remaining_quantity}', $remaining, $stockLabel); $field['settings']['quantity_remaining'] = $remaining; $hideStockoutInput = Arr::get($field, 'settings.hide_input_when_stockout') == 'yes'; if ($hideStockoutInput && $remaining == 0) { $field['settings']['container_class'] .= 'has-conditions ff_excluded '; } return $field; } public function processInventoryFields($field, $form, $previousSubmissionData, $inventoryType) { list($inputType, $showStock, $stockLabel, $hideChoice) = $this->validationMessages($field); if ($inputType == 'single') { $field = $this->adjustSinglePaymentItem($field, $form, $stockLabel, $inventoryType); } elseif ($inputType == 'radio' || $inputType == 'checkbox' || $inputType == 'select') { $attr = [ 'formId' => $form->id, 'field' => $field, 'form' => $form, 'previousSubmissionData' => $previousSubmissionData, 'stockLabel' => $stockLabel, 'showStock' => $showStock, 'hideChoice' => $hideChoice, 'inventoryType' => $inventoryType, ]; $field = $this->adjustOptions($attr); } $field = apply_filters_deprecated( 'fluentform_inventory_fields_before_render', [ $field, $form, $previousSubmissionData ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/inventory_fields_before_render', 'Use fluentform/inventory_fields_before_render instead of fluentform_survey_shortcode_defaults' ); return apply_filters('fluentform/inventory_fields_before_render', $field, $form, $previousSubmissionData); } /** * Get Inventory Settings Activated Fields * @param $form * @param $type simple|global * @return array */ public static function getInventoryFields($form, $types = ['simple', 'global']) { $inventoryAllowedInputs = InventorySettingsManager::getInventoryInputs(); $inventoryFields = FormFieldsParser::getElement($form, $inventoryAllowedInputs, ['element', 'attributes', 'settings','label']); $inventoryActivatedFields = []; foreach ($inventoryFields as $fieldName => $field) { $inventoryType = Arr::get($field, 'settings.inventory_type'); if (in_array($inventoryType, $types)) { $inventoryActivatedFields[$fieldName] = $field; } } return $inventoryActivatedFields; } /** * Get Inventory Quantity Activated Fields * @param $form * @return array */ public static function getQuantityFieldsMapping($form) { $quantityItems = []; $quantityFields = FormFieldsParser::getElement($form, ['item_quantity_component', 'rangeslider'], ['element', 'attributes', 'settings']); foreach ($quantityFields as $field) { if ('rangeslider' == Arr::get($field, 'element') && 'yes' != Arr::get($field, 'settings.enable_target_product')) { continue; } if ($targetProductName = Arr::get($field, 'settings.target_product')) { $quantityItems[$targetProductName] = Arr::get($field, 'attributes.name'); } } return $quantityItems; } /** * Show or Hide Remaining Inventory Options Comparing Previous Submissions * @return void * @throws \Exception */ public function processBeforeFormRender() { static $previousSubmissionCache = []; add_filter('fluentform/rendering_form', function ($form) use ($previousSubmissionCache) { $simpleInventory = static::getInventoryFields($form, ['simple']); if (!isset($previousSubmissionCache[$form->id]) && !empty($simpleInventory)) { $inventoryFieldsNames = array_keys($simpleInventory); $previousSubmissionCache[$form->id] = (new \FluentForm\App\Modules\Entries\Report(wpFluentForm()))->getInputReport($form->id, $inventoryFieldsNames, false); } $globalInventory = static::getInventoryFields($form, ['global']); if (empty($globalInventory) && empty($simpleInventory)) { return $form; } $inventoryFields = array_merge($simpleInventory, $globalInventory); foreach ($inventoryFields as $inventoryField) { $element = $inventoryField['element']; $inventoryType = Arr::get($inventoryField, 'settings.inventory_type', false); add_filter('fluentform/rendering_field_data_' . $element, function ($field, $form) use ( $previousSubmissionCache, $inventoryField, $inventoryType ) { if (Arr::get($inventoryField, 'attributes.name') == Arr::get($field, 'attributes.name')) { $submissionCache = isset($previousSubmissionCache[$form->id]) ? $previousSubmissionCache[$form->id] : []; $field = $this->processInventoryFields($field, $form, $submissionCache, $inventoryType); } return $field; }, 10, 2); } return $form; }); } private function validationMessages($field) { $inputType = Arr::get($field, 'attributes.type') ? Arr::get($field, 'attributes.type') : Arr::get($field, 'element'); $showStock = Arr::get($field, 'settings.show_stock') == 'yes'; $stockLabel = wp_kses_post(Arr::get($field, 'settings.stock_quantity_label')); $hideChoice = Arr::get($field, 'settings.hide_choice_when_stockout') == 'yes'; return [$inputType, $showStock, $stockLabel, $hideChoice]; } } PK!+j6L6L-src/classes/Inventory/InventoryValidation.phpnu[formData = $formData; $this->form = $form; $this->maybeSetItemQuantity(); } private function maybeSetItemQuantity() { $this->quantityItems = InventoryFieldsRenderer::getQuantityFieldsMapping($this->form); } /** * Validates Inventory Items */ public function validate() { $this->validateSimpleInventory(); $this->validateGlobalInventory(); } public function getQuantity($productName, $formData) { $quantity = 1; if (!$this->quantityItems) { return $quantity; } if (!isset($this->quantityItems[$productName])) { return $quantity; } $inputName = $this->quantityItems[$productName]; $quantity = Arr::get($formData, $inputName); if (!$quantity) { return 0; } return intval($quantity); } public static function getPaymentItemSubmissionQuantity($formId, $parentName, $name, $price) { static $quantityCache = []; if (!isset($quantityCache[$formId])) { $quantityCache[$formId] = self::runSumQuantityQuery($formId); } if (!empty($quantityCache[$formId])) { foreach ($quantityCache[$formId] as $qty) { if ($qty->item_name == $name && $qty->item_price == $price && $qty->parent_holder == $parentName) { return (int)$qty->total_count; } } } return 0; } public static function getItemFromOptionName($item, $key) { $isPaymentInput = Arr::get($item, 'settings.is_payment_field') == 'yes'; if ($isPaymentInput) { $options = Arr::get($item, 'settings.pricing_options'); } else { $options = Arr::get($item, 'settings.advanced_options'); } $selectedOption = []; if (empty($options)) { return false; } foreach ($options as $option) { $label = sanitize_text_field($option['label']); $value = sanitize_text_field($option['value']); if ($label == $key || $value == $key) { $selectedOption = $option; } } if (!$selectedOption || empty($selectedOption['value'])) { return false; } return [ 'parent_input_name' => Arr::get($item, 'attributes.name'), 'item_name' => Arr::get($selectedOption, 'label'), 'item_value' => Arr::get($selectedOption, 'value'), 'global_inventory'=> Arr::get($selectedOption, 'global_inventory'), 'quantity' => Arr::get($selectedOption, 'quantity') ]; } public static function getRegularItemUsedQuantity($previousSubmissionData, $item) { $name = Arr::get($item, 'parent_input_name'); $optionName = Arr::get($item, 'item_name'); $optionValue = Arr::get($item, 'item_value'); $data = Arr::get($previousSubmissionData, $name . '.reports'); if (!empty($data)) { foreach ($data as $datum) { if (($datum['value'] == $optionName) || $datum['value'] == $optionValue) { return intval($datum['count']); } } } return 0; } private function handleSinglePaymentInput($inputName, $item, $inventoryType = 'simple') { $selectedQuantity = $this->getQuantity($inputName, $this->formData); if (!$selectedQuantity) { throw new \Exception("continue"); } $itemName = Arr::get($item, 'settings.label'); $parentName = Arr::get($item, 'attributes.name'); $availableQuantity = 0; $usedQuantity = 0; $itemPrice = null; if ($inventoryType == 'simple') { $availableQuantity = (int)Arr::get($item, 'settings.single_inventory_stock'); $itemPrice = \FluentFormPro\Payments\PaymentHelper::convertToCents(Arr::get($item, 'attributes.value')); } elseif ($inventoryType == 'global') { $attachedGlobalInventory = Arr::get($this->globalInventoryFieldsName, $inputName); $availableQuantity = intval(Arr::get($this->globalInventoryItems, $attachedGlobalInventory . '.quantity')); } $usedQuantity = $this->getPaymentItemSubmissionQuantity($this->form->id, $parentName, $itemName, $itemPrice) + $selectedQuantity; if ($usedQuantity > $availableQuantity) { throw new \Exception("stock-out"); } } private function handleRadioSelect($key, $item, $prevSubmissions, $isPaymentInput, $inventoryType = 'simple') { $item = self::getItemFromOptionName($item, $this->formData[$key]); if ($item) { $availableQuantity = $item['quantity']; $usedQuantity = 0; $selectedQuantity = 1; if ($inventoryType == 'simple') { $itemName = $item['item_name']; if ($isPaymentInput) { $selectedQuantity = $this->getQuantity($item['parent_input_name'], $this->formData); $itemPrice = \FluentFormPro\Payments\PaymentHelper::convertToCents($item['item_value']) ; $usedQuantity = $this->getPaymentItemSubmissionQuantity($this->form->id, $item['parent_input_name'], $itemName, $itemPrice); } else { $usedQuantity = $this->getRegularItemUsedQuantity($prevSubmissions, $item); } } elseif ($inventoryType == 'global') { if ($isPaymentInput) { $selectedQuantity = $this->getQuantity($item['parent_input_name'], $this->formData); } $availableQuantity = intval(Arr::get($this->globalInventoryItems, $item['global_inventory'] . '.quantity')); $usedQuantity = (int)Arr::get($this->usedGlobalItemsRecords, $item['global_inventory']); } $usedQuantity += $selectedQuantity; if ($usedQuantity > $availableQuantity) { throw new \Exception("stock-out"); } } } /** * @throws \Exception */ private function handleCheckbox($key, $field, $prevSubmissions, $isPaymentInput, $inventoryType = 'simple') { $selectedItems = $this->formData[$key]; //Global inventory multiple option can use same slug //Store total selected quantity $totalSelectedQuantity = []; foreach ($selectedItems as $selectedItem) { $item = $this->getItemFromOptionName($field, $selectedItem); if (!$item) { throw new \Exception("continue"); } $selectedQuantity = 1; if ($inventoryType == 'simple') { $availableQuantity = $item['quantity']; if ($isPaymentInput) { $itemName = $item['item_name']; $itemPrice = \FluentFormPro\Payments\PaymentHelper::convertToCents($item['item_value']); $usedQuantity = $this->getPaymentItemSubmissionQuantity($this->form->id, $item['parent_input_name'], $itemName, $itemPrice); $selectedQuantity = $this->getQuantity($item['parent_input_name'], $this->formData); if (!$selectedQuantity) { throw new \Exception("continue"); } } else { $usedQuantity = $this->getRegularItemUsedQuantity($prevSubmissions, $item); } $this->validateStockOut($usedQuantity + $selectedQuantity, $availableQuantity); } elseif ($inventoryType == 'global') { $slug = Arr::get($item, 'global_inventory'); if (!$slug) { continue; } if ($isPaymentInput) { $selectedQuantity = $this->getQuantity($item['parent_input_name'], $this->formData); if (!$selectedQuantity) { throw new \Exception("continue"); } } if (Arr::exists($totalSelectedQuantity, $slug)) { $totalSelectedQuantity[$slug] += $selectedQuantity; } else { $totalSelectedQuantity[$slug] = $selectedQuantity; } } } //validate global inventory multiple options foreach ($totalSelectedQuantity as $slug => $totalSelected) { $usedQuantity = Arr::get($this->usedGlobalItemsRecords, $slug); $availableQuantity = intval(Arr::get($this->globalInventoryItems, $slug . '.quantity')); $this->validateStockOut($usedQuantity + $totalSelected, $availableQuantity); } } /** * @throws \Exception */ private function validateStockOut($used, $available) { if ($used > $available) { throw new \Exception("stock-out"); } } private function isEmpty($key) { if (!isset($this->formData[$key])) { throw new \Exception("continue"); } } private static function runSumQuantityQuery($formId) { global $wpdb; $quantity = wpFluent()->table('fluentform_order_items') ->select([ 'fluentform_order_items.item_name', 'fluentform_order_items.item_price', 'fluentform_order_items.quantity', 'fluentform_order_items.parent_holder', wpFluent()->raw('sum(' . $wpdb->prefix . 'fluentform_order_items.quantity) as total_count') ]) ->where('fluentform_order_items.form_id', $formId) ->groupBy('fluentform_order_items.item_name') ->groupBy('fluentform_order_items.item_price') ->groupBy('fluentform_order_items.parent_holder') ->where('fluentform_submissions.payment_status', '!=', 'refunded') ->rightJoin('fluentform_submissions', 'fluentform_submissions.id', '=', 'fluentform_order_items.submission_id') ->get(); return (array)$quantity; } public static function getValidationMessage($item) { $stockOutMsg = sanitize_text_field(Arr::get($item, 'settings.inventory_stockout_message')); $isPaymentInput = Arr::get($item, 'settings.is_payment_field') == 'yes'; $inputType = Arr::get($item, 'attributes.type') ? Arr::get($item, 'attributes.type') : Arr::get($item, 'element'); return array($stockOutMsg, $isPaymentInput, $inputType); } /** * @param $form * @return array * # Array Format * $usedGlobalItemsRecords = [ * 'inventory-item-name' => [ * 'multiple-option-input-name' => [ * 'option_name' => count * ], * 'single-option-input-name' => count * ] * ]; */ public function usedGlobalInventoryItemCount() { $usedGlobalInventoryItems = $this->usedGlobalInventories(); if (empty($usedGlobalInventoryItems)) { return []; } return self::calculateGlobalInventory($usedGlobalInventoryItems); } public function usedGlobalInventories() { $this->globalInventoryItems = get_option('ff_inventory_list'); if (!is_array($this->globalInventoryItems)) { return []; } $globalInventoryField = InventoryFieldsRenderer::getInventoryFields($this->form, ['global']); if (empty($globalInventoryField)) { return []; } $inventoryFields = []; $inventorySlugs = []; foreach ($globalInventoryField as $fieldName => $field) { if ($this->isSingleInventoryField($field)) { $slug = Arr::get($globalInventoryField,$fieldName . '.settings.global_inventory'); $attachedGlobalInventorySlug = $slug; $inventorySlugs[] = $slug; } else { $options = $this->getOptions($field); $isPaymentField = $this->isPaymentField($field); $attachedGlobalInventorySlug = []; foreach ($options as $option) { $key = $isPaymentField ? 'label' : 'value'; $slug = Arr::get($option, 'global_inventory'); $attachedGlobalInventorySlug[Arr::get($option, $key)] = $slug; $inventorySlugs[] = $slug; } } $inventoryFields[$fieldName] = $attachedGlobalInventorySlug; } $this->globalInventoryFieldsName = $inventoryFields; return self::getSubmittedGlobalInventories(array_filter(array_unique($inventorySlugs))); } public function getGlobalInventoryInfo($slug) { if (!$this->usedGlobalItemsRecords) { $this->usedGlobalItemsRecords = $this->usedGlobalInventoryItemCount(); } $quantity = (int)Arr::get($this->globalInventoryItems, $slug . '.quantity'); $usedQuantity = (int)Arr::get($this->usedGlobalItemsRecords, $slug, 0); return [$quantity, $usedQuantity]; } public function isSingleInventoryField($field) { return 'single' == Arr::get($field, 'attributes.type'); } public function getOptions($field) { $optionKey = $this->isPaymentField($field) ? 'pricing_options' : 'advanced_options'; return Arr::get($field, 'settings.' . $optionKey, []); } public function isPaymentField($field) { return 'yes' == Arr::get($field, 'settings.is_payment_field'); } public static function getSubmittedGlobalInventories($usedInventoryFields) { return SubmissionMeta::select(['name', 'value']) ->where('meta_key', 'ff_used_global_inventory_item') ->whereIn('name', $usedInventoryFields) ->with(['form' => function ($query) { $query->select(['title']); }]) ->get()->transform(function ($item) { $item->value = json_decode($item->value, true); return $item; }); } public static function calculateGlobalInventory($usedGlobalInventoryItems, $asFormat = false) { $usedGlobalItemsRecords = []; foreach ($usedGlobalInventoryItems as $item) { $name = $item->name; $value = $item->value['value']; $quantity = $item->value['quantity']; if (is_string($value)) { self::formatRecords($usedGlobalItemsRecords, $name, $value, $quantity, $asFormat); } else { foreach ($value as $subItem) { self::formatRecords($usedGlobalItemsRecords, $name, $subItem, $quantity, $asFormat); } } } return $usedGlobalItemsRecords; } private static function formatRecords(&$usedGlobalItemsRecords, $name, $subItem, $quantity, $asFormat) { if ($asFormat) { $usedGlobalItemsRecords[$name][$subItem] = isset($usedGlobalItemsRecords[$name][$subItem]) ? $usedGlobalItemsRecords[$name][$subItem] + $quantity : $quantity; } else { $usedGlobalItemsRecords[$name] = isset($usedGlobalItemsRecords[$name]) ? $usedGlobalItemsRecords[$name] + $quantity : $quantity; } } private function validateSimpleInventory() { $inventoryFields = InventoryFieldsRenderer::getInventoryFields($this->form, ['simple']); if (empty($inventoryFields)) { return; } $prevSubmissions = (new Report(wpFluentForm()))->getInputReport($this->form->id, array_keys($inventoryFields), false); $errors = $this->processInventoryFields($inventoryFields, $prevSubmissions,'simple'); if (!empty($errors)) { $errors = $this->applyValidationFilters($errors); wp_send_json(['errors' => $errors], 423); } } public function validateGlobalInventory() { $this->usedGlobalItemsRecords = $this->usedGlobalInventoryItemCount(); $globalInventoryFields = InventoryFieldsRenderer::getInventoryFields($this->form, ['global']); $errors = $this->processInventoryFields($globalInventoryFields, $this->usedGlobalItemsRecords, 'global'); if (!empty($errors)) { $errors = $this->applyValidationFilters($errors); wp_send_json(['errors' => $errors], 423); } } private function processInventoryFields($inventoryFields, $prevSubmissions, $inventoryType) { $errors = []; foreach ($inventoryFields as $fieldName => $field) { list($stockOutMsg, $isPaymentInput, $inputType) = self::getValidationMessage($field); try { $this->isEmpty($fieldName); if ($inputType == 'single') { $this->handleSinglePaymentInput($fieldName, $field, $inventoryType); } elseif ($inputType == 'radio' || $inputType == 'select') { $this->handleRadioSelect($fieldName, $field, $prevSubmissions, $isPaymentInput, $inventoryType); } elseif ($inputType == 'checkbox') { $this->handleCheckbox($fieldName, $field, $prevSubmissions, $isPaymentInput, $inventoryType); } } catch (\Exception $e) { if ($e->getMessage() == 'continue') { continue; } elseif ($e->getMessage() == 'stock-out') { $errors[$fieldName] = [ 'stock-out' => wpFluentForm()->applyFilters('fluentform/inventory_validation_error', $stockOutMsg, $fieldName, $field, $this->formData, $this->form) ]; break; } } } return $errors; } private function applyValidationFilters($errors) { $app = wpFluentForm(); $fields = FormFieldsParser::getInputs($this->form, ['rules', 'raw']); $errors = apply_filters_deprecated( 'fluentform_validation_error', [$errors, $this->form, $fields, $this->formData], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/validation_error', 'Use fluentform/validation_error instead of fluentform_validation_error.' ); return $app->applyFilters('fluentform/validation_error', $errors, $this->form, $fields, $this->formData); } } PK!+e---src/classes/Inventory/InventoryController.phpnu[isEnabled(); add_filter('fluentform/global_addons', function ($addOns) use ($enabled) { $addOns[$this->key] = [ 'title' => 'Inventory Module', 'description' => __('Powerful Inventory Management. Manage resources for events booking, reservations, or for selling products and tickets!', 'fluentformpro'), 'logo' => fluentFormMix('img/integrations/inventory.png'), 'enabled' => ($enabled) ? 'yes' : 'no', 'config_url' => '', 'category' => '' //Category : All ]; return $addOns; }, 9); if (!$enabled) { return; } add_filter('fluentform/global_settings_components', array($this, 'addGlobalMenu'), 1); add_action('fluentform/submission_inserted', [$this, 'insertGlobalInventory'], 10, 3); /** * Validate Inventory Form Fields */ add_action('fluentform/before_insert_submission', function ($insertData, $formData, $form) { (new InventoryValidation($formData, $form))->validate(); }, 10, 3); /** * Process Inventory Fields Options Comparing Previous Submissions */ (new InventoryFieldsRenderer())->processBeforeFormRender(); add_action('wp_ajax_fluentform_get_global_inventory_list', [$this, 'getGlobalInventoryList']); add_action('wp_ajax_fluentform_store_global_inventory_list', [$this, 'storeGlobalInventory']); add_action('wp_ajax_fluentform_delete_global_inventory_list', [$this, 'deleteGlobalInventory']); add_action('wp_ajax_fluentform_reset_global_inventory_item', [$this, 'resetGlobalInventory']); InventorySettingsManager::boot(); InventoryList::boot(); } public function isEnabled() { $globalModules = get_option('fluentform_global_modules_status'); $inventoryModule = ArrayHelper::get($globalModules, $this->key); if ($inventoryModule == 'yes') { return true; } return false; } public function addGlobalMenu($setting) { $setting['InventoryManager'] = [ 'hash' => 'inventory_manager', 'title' => 'Inventory Manager', ]; return $setting; } public function getGlobalInventoryList() { $inventoryList = get_option('ff_inventory_list'); if ($inventoryList !== false) { $formattedList = []; $items = array_filter(array_keys($inventoryList)); $usedItems = InventoryValidation::getSubmittedGlobalInventories($items); $formattedUsedItems = InventoryValidation::calculateGlobalInventory($usedItems, true); foreach ($inventoryList as $inventoryKey => $value) { if (!empty($inventoryKey) && !empty($value['slug'])) { if (array_key_exists($inventoryKey, $formattedUsedItems)) { $totalUsed = array_reduce($formattedUsedItems[$inventoryKey], function ($res, $item) { return $res + $item; }, 0); $value['remaining'] = max($value['quantity'] - $totalUsed, 0); $value['details'] = $formattedUsedItems[$inventoryKey]; } elseif ($qty = Arr::get($value, 'quantity')) { $value['remaining'] = $qty; } $formattedList[$inventoryKey] = $value; } } $inventoryList = $formattedList; } else { $inventoryList = []; } wp_send_json_success([ 'success' => true, 'inventory_list' => $inventoryList ]); } public function storeGlobalInventory() { try { $item = Arr::get($_REQUEST, 'inventory'); $this->validate($item); //If request has slug, requested for update $slug = Arr::get($item, 'slug'); $postedInventory = [ 'name' => sanitize_text_field($item['name']), 'quantity' => $item['quantity'], 'slug' => $slug ? sanitize_title($slug) : sanitize_title($item['name']), ]; $inventoryList = get_option('ff_inventory_list'); if (is_array($inventoryList)) { if (Arr::exists($inventoryList, $postedInventory['slug'])) { if ($slug) { //Updating an existing item $inventoryList[$slug] = $postedInventory; $message = __('Inventory Updated', 'fluentformpro'); } else { //Trying to create new, but inventory slug already exists throw new ValidationException(__('Inventory name already exists', 'fluentformpro')); } } else { //Adding a new item $inventoryList[$postedInventory['slug']] = $postedInventory; $message = __('New Inventory Added', 'fluentformpro'); } } else { //Adding the first item $message = __('New Inventory Added', 'fluentformpro'); $inventoryList = [ $postedInventory['slug'] => $postedInventory ]; } update_option('ff_inventory_list', $inventoryList, false); wp_send_json_success([ 'success' => true, 'message' => $message, 'inventory_list' => array_values($inventoryList) ]); } catch (ValidationException $exception) { $errors = $exception->errors(); if (!$errors) { $errors = [ 'errors' => [ 'name' => $exception->getMessage() ] ]; } wp_send_json_error($errors, 422); } } public function deleteGlobalInventory() { $itemSlug = sanitize_text_field($_REQUEST['slug']); $inventoryList = get_option('ff_inventory_list'); if ($itemSlug && array_key_exists($itemSlug, $inventoryList)) { unset($inventoryList[$itemSlug]); update_option('ff_inventory_list', $inventoryList, false); wp_send_json_success([ 'success' => true, 'message' => __("Deleted Successfully", 'fluentformpro'), ]); } wp_send_json_success([ 'success' => true, 'message' => __("Invalid Item", 'fluentformpro'), ]); } public function resetGlobalInventory() { $itemSlug = sanitize_text_field($_REQUEST['slug']); $inventoryList = get_option('ff_inventory_list'); if ($itemSlug && array_key_exists($itemSlug, $inventoryList)) { SubmissionMeta::where('meta_key', 'ff_used_global_inventory_item') ->where('name', $itemSlug) ->delete(); wp_send_json_success([ 'success' => true, 'message' => __('Item was successfully reset', 'fluentformpro'), ]); } wp_send_json_error([ 'success' => true, 'message' => __("Invalid Item", 'fluentformpro'), ]); } public function insertGlobalInventory($insertId, $formData, $form) { $inventoryValidation = (new InventoryValidation($formData, $form)); $inventoryFields = InventoryFieldsRenderer::getInventoryFields($form, ['global']); $usedInventoryFields = []; //@improve handle single payment input foreach ($inventoryFields as $inventoryFieldName => $field) { if (!empty(ArrayHelper::get($formData, $inventoryFieldName))) { $usedInventoryFields[$inventoryFieldName] = $formData[$inventoryFieldName]; } } if (empty($usedInventoryFields)) { return; } foreach ($usedInventoryFields as $fieldName => $value) { $globalInventoryItems = []; $field = Arr::get($inventoryFields, $fieldName); if ($inventoryValidation->isSingleInventoryField($field)) { $inventorySlug = Arr::get($field,'settings.global_inventory'); $globalInventoryItems[$inventorySlug] = $value; } else { $options = $inventoryValidation->getOptions($field); $optionKey = $inventoryValidation->isPaymentField($field) ? 'label' : 'value'; $options = array_filter($options, function ($option) use ($value, $optionKey) { if (is_array($value)) { return in_array($option[$optionKey], $value); } return $option[$optionKey] == $value; }); foreach ($options as $option) { if ($inventorySlug = Arr::get($option, 'global_inventory')) { if (is_array($value)) { $item = $option[$optionKey]; if (Arr::exists($globalInventoryItems, $inventorySlug)) { $globalInventoryItems[$inventorySlug][] = $item; } else { $globalInventoryItems[$inventorySlug] = [$item]; } } else { $globalInventoryItems[$inventorySlug] = $value; } } } } $quantity = $inventoryValidation->getQuantity($fieldName, $formData); if ($quantity == 0) { continue; } foreach ($globalInventoryItems as $inventoryItemSlug => $dataValue) { SubmissionMeta::insertGetId([ 'form_id' => $form->id, 'response_id' => $insertId, 'meta_key' => 'ff_used_global_inventory_item', 'value' => json_encode([ 'value' => $dataValue, 'quantity' => $quantity, ]), 'name' => $inventoryItemSlug ]); } } } private function validate($inventory) { $rules = [ 'name' => 'required', 'quantity' => 'required|numeric|min:1', ]; $validatorInstance = new Validator(); $validator = $validatorInstance->make($inventory, $rules); $errors = null; if ($validator->validate()->fails()) { $errors = $validator->errors(); } if ($errors) { throw new ValidationException('', 0, null, [ 'errors' => $errors, ]); } } } PK!X~!!'src/classes/Inventory/InventoryList.phpnu[ 0) { $formAdminMenus['inventory_list'] = [ 'hash' => '/', 'slug' => 'inventory_list', 'title' => __('Inventory', 'fluentformpro'), 'url' => admin_url( 'admin.php?page=fluent_forms&form_id=' . $form_id . '&route=inventory_list' ) ]; } return $formAdminMenus; } public function renderInventoryList($form_id) { $this->enqueueScript(); $form = Form::find($form_id); $inventoryFields = $this->getInventoryFields($form); $fields = FormFieldsParser::getInputs($form, ['element', 'settings', 'label','attributes']); $submissionRecords = ReportHelper::getInputReport($form->id, array_keys($inventoryFields)); $formattedSubmissions = []; if (!$submissionRecords || count($submissionRecords) < count($inventoryFields)) { $submissionRecords = array_merge($inventoryFields, $submissionRecords); } $quantityMappingFields = InventoryFieldsRenderer::getQuantityFieldsMapping($form); foreach ($submissionRecords as $name => $submission) { $submissionItems = ArrayHelper::get($submission, 'reports', []); $input = ArrayHelper::get($fields, $name); $isSinglePaymentItem = ArrayHelper::get($input, 'element') == 'multi_payment_component' && ArrayHelper::get($input, 'attributes.type') == 'single'; $label = ArrayHelper::get($input, 'label'); if ($submissionItems && ArrayHelper::exists($quantityMappingFields, $name)) { $this->resolveSubmissionQuantity($submissionItems, $name, $isSinglePaymentItem, $input, $form); } $formattedSubmissions[$name]['label'] = $label; if ($isSinglePaymentItem) { $formattedSubmissions[$name]['options'][] = $this->formatSinglePaymentSubmission($name, $input, $submissionItems); } else { $formattedSubmissions[$name]['options'] = $this->formatOtherSubmissions($name, $input, $submissionItems); } } $vars = [ 'no_found_text' => __('Sorry! No Inventory record found.', 'fluentformpro'), 'submissions' => $formattedSubmissions, 'inventory_fields' => InventoryFieldsRenderer::getInventoryFields($form) ]; $ffInventoryListVars = apply_filters('fluentform/step_form_entry_vars', $vars, $form); wp_localize_script( 'fluentform_inventory_list', 'fluentform_inventory_list_vars', $ffInventoryListVars ); ob_start(); require(FLUENTFORMPRO_DIR_PATH . 'src/views/inventory_list.php'); echo ob_get_clean(); } public function formatSinglePaymentSubmission($name, $input,$submissionItems) { $quantity = ArrayHelper::get($input,'settings.single_inventory_stock'); $usedCount = (int)ArrayHelper::get($submissionItems, '0.count', 0); $quantity = (int)$quantity; $remaining = $quantity - $usedCount; return [ 'key' => $name, 'label' => ArrayHelper::get($input, 'settings.label'), 'used_count' => $usedCount, 'quantity' => $quantity, 'remaining' => $this->stockMessage($remaining) ]; } protected function enqueueScript() { wp_enqueue_script( 'fluentform_inventory_list', FLUENTFORMPRO_DIR_URL . 'public/js/inventory-list.js', ['jquery'], FLUENTFORM_VERSION, true ); } public function setRoutePermission($permissions) { $permissions['inventory_list'] = 'fluentform_forms_manager'; return $permissions; } private function getInventoryFields($form) { return InventoryFieldsRenderer::getInventoryFields($form); } public function getFormattedItems($submissionItems, $inputItems, $isPaymentItem) { $mergedArray = []; $tempInputItems = $inputItems; //for payment items merge with label $attribute = $isPaymentItem ? 'label' : 'value'; foreach ($inputItems as $index => $item) { foreach ($submissionItems as $submission) { if ($submission["value"] === $item[$attribute]) { $mergedArray[] = array_merge($submission, $item); ArrayHelper::forget($tempInputItems, $index); } } } return array_merge($mergedArray, $tempInputItems); } private function formatOtherSubmissions( $name, $input, $submissionItems) { $isPaymentItem = ArrayHelper::get($input, 'element') == 'multi_payment_component'; if ($isPaymentItem) { $inputItems = ArrayHelper::get($input, 'settings.pricing_options'); } else { $inputItems = ArrayHelper::get($input, 'settings.advanced_options'); } $formattedItems = $this->getFormattedItems($submissionItems, $inputItems, $isPaymentItem); $items= []; foreach ($formattedItems as $item) { $usedCount = (int)ArrayHelper::get($item, 'count', 0); $quantity = (int)ArrayHelper::get($item, 'quantity'); $remaining = $quantity - $usedCount; $items[] = [ 'key' => $name, 'label' => ArrayHelper::get($item, 'label'), 'used_count' => $usedCount, 'quantity' => $quantity, 'remaining' => $this->stockMessage($remaining) ]; } return $items; } private function resolveSubmissionQuantity(&$submissionItems, $name, $isSinglePaymentItem, $input, $form) { if ($isSinglePaymentItem) { $label = ArrayHelper::get($input, 'label', ''); $price = PaymentHelper::convertToCents(ArrayHelper::get($input, 'attributes.value', 0)); if (isset($submissionItems[0])) { $submissionItems[0]['count'] = InventoryValidation::getPaymentItemSubmissionQuantity($form->id, $name, $label, $price); } } else { $options = ArrayHelper::get($input, 'settings.pricing_options', []); foreach ($options as $option) { $optionLabel = ArrayHelper::get($option, 'label', ''); $price = PaymentHelper::convertToCents(ArrayHelper::get($option, 'value', 0)); $used = InventoryValidation::getPaymentItemSubmissionQuantity($form->id, $name, $optionLabel, $price); foreach ($submissionItems as &$item) { if ($optionLabel === $item['value']) { $item['count'] = $used; break; } } } } } private function stockMessage($remaining) { $inStock = __('In Stock', 'fluentformpro'); $outOfStock = __('Out of Stock', 'fluentformpro'); return $remaining > 0 ? sprintf('%s (%d)', $inStock, $remaining) : sprintf('%s (%d)', $outOfStock, $remaining); } } PK!~h+#&&2src/classes/Inventory/InventorySettingsManager.phpnu[insertDefaultValues(); $this->insertDefaultValuesToExistingForm(); $this->insertEditorSettings(); } public function insertDefaultValues() { $upgradableInputs = static::getInventoryInputs(); add_filter('fluentform/editor_components', function ($components) use ($upgradableInputs) { //mapping select,input_radio,input_checkbox, multi_payment_component keys and groups $inventoryFieldsKeyGroupMaps = [ 8 => 'general', 9 => 'general', 10 => 'general', 0 => 'payments', ]; foreach ($inventoryFieldsKeyGroupMaps as $key => $group) { $item = Arr::get($components, $group . '.' . $key); if (in_array(Arr::get($item, 'element'), $upgradableInputs)) { $inventorySettings = [ 'inventory_type' => false, 'inventory_stockout_message' => __('This Item is Stock Out', 'fluentformpro'), 'hide_choice_when_stockout' => 'no', 'hide_input_when_stockout' => 'no', 'disable_input_when_stockout'=> 'no', 'show_stock' => 'no', 'simple_inventory' => '', 'single_inventory_stock' => 10, 'stock_quantity_label' => sprintf(__(' - %s available', 'fluentformpro'),'{remaining_quantity}'), 'global_inventory' => '' ]; if (isset($components[$group][$key]['settings'])) { $components[$group][$key]['settings'] = array_merge($components[$group][$key]['settings'], $inventorySettings); } } } return $components; }, 10, 1); } public function insertEditorSettings() { add_filter('fluentform/editor_element_settings_placement', function ($placements) { $upgradableInputs = static::getInventoryInputs(); foreach ($upgradableInputs as $inputKey) { if (!isset($placements[$inputKey])) { break; } $placements[$inputKey]['advanced'][] = [ array_keys($this->getAdditionalSettings()) ]; $placements[$inputKey]['advancedExtras'] = $this->getAdditionalSettings(); } return $placements; }); } public function getAdditionalSettings() { return [ 'inventory_type' => [ 'template' => 'radio', 'label' => __('Inventory Settings', 'fluentformpro'), 'options' => [ [ 'value' => false, 'label' => __('Disable', 'fluentformpro'), ], [ 'value' => 'simple', 'label' => __('Simple', 'fluentformpro'), ], [ 'value' => 'global', 'label' => __('Global', 'fluentformpro'), ], ], ], 'global_inventory' => [ 'template' => 'inventoryStock', 'label' => __('Global Inventory', 'fluentform'), 'help_text' => __('Select a Global Inventory', 'fluentform'), 'options' => $this->getGloablInventoryList(), 'dependency' => [ 'depends_on' => 'settings/inventory_type', 'value' => 'global', 'operator' => '==' ] ], 'simple_inventory' => [ 'template' => 'inventoryStock', 'label' => __('Stock Quantity', 'fluentformpro'), 'dependency' => [ 'depends_on' => 'settings/inventory_type', 'value' => 'simple', 'operator' => '==' ], ], 'inventory_stockout_message' => [ 'template' => 'inputText', 'label' => __('Stock Out Message', 'fluentformpro'), 'dependency' => [ 'depends_on' => 'settings/inventory_type', 'value' => false, 'operator' => '!=' ] ], 'hide_choice_when_stockout' => [ 'template' => 'inputYesNoCheckBox', 'label' => __('Hide Choice When Stock is Out', 'fluentformpro'), 'dependency' => [ 'depends_on' => 'settings/inventory_type', 'value' => false, 'operator' => '!=' ] ], 'hide_input_when_stockout' => [ 'template' => 'inputYesNoCheckBox', 'label' => __('Hide Input When Stock is Out', 'fluentformpro'), 'dependency' => [ 'depends_on' => 'settings/inventory_type', 'value' => false, 'operator' => '!=' ] ], 'disable_input_when_stockout' => [ 'template' => 'inputYesNoCheckBox', 'label' => __('Disable Input When Stock is Out', 'fluentformpro'), 'dependency' => [ 'depends_on' => 'settings/inventory_type', 'value' => false, 'operator' => '!=' ] ], 'show_stock' => [ 'template' => 'inputYesNoCheckBox', 'label' => __('Show Available Stock', 'fluentformpro'), 'dependency' => [ 'depends_on' => 'settings/inventory_type', 'value' => false, 'operator' => '!=' ] ], 'stock_quantity_label' => [ 'template' => 'inputText', 'label' => __('Inventory Label', 'fluentformpro'), 'inline_help_text' => __('This Label will be appended to the field’s label or field’s Options', 'fluentformpro'), 'dependency' => [ 'depends_on' => 'settings/inventory_type', 'value' => false, 'operator' => '!=' ] ], ]; } public static function getInventoryInputs() { $fields = [ 'select', 'input_radio', 'input_checkbox', 'multi_payment_component' ]; $fields = apply_filters_deprecated( 'fluentform_inventory_inputs', [ $fields ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/inventory_inputs', 'Use fluentform/inventory_inputs instead of fluentform_inventory_inputs.' ); return apply_filters('fluentform/inventory_inputs', $fields); } public function getGloablInventoryList() { $inventoryList = get_option('ff_inventory_list'); if ($inventoryList !== false) { $formattedList = []; foreach ($inventoryList as $inventoryKey => $item){ if(!empty($inventoryKey) && !empty($item['slug'])){ $formattedList[] = [ 'value' => $item['slug'], 'label' => $item['name'] ]; } } $inventoryList = $formattedList; } else { $inventoryList = []; } return $inventoryList; } protected function insertDefaultValuesToExistingForm() { $upgradableInputs = static::getInventoryInputs(); foreach ($upgradableInputs as $inputKey) { add_filter('fluentform/editor_init_element_' . $inputKey, function ($field) { $defaultSettings = [ 'inventory_stockout_message' => __('This Item is Stock Out', 'fluentformpro'), 'inventory_type' => '', 'hide_choice_when_stockout' => '', 'disable_input_when_stockout' => '', 'hide_input_when_stockout' => '', 'show_stock' => '', 'simple_inventory' => '', 'single_inventory_stock' => 1, 'stock_quantity_label' => sprintf(__(' - %s available', 'fluentformpro'), '{remaining_quantity}') ]; foreach ($defaultSettings as $settingKey => $defaultValue) { if (!isset($field['settings'][$settingKey])) { $field['settings'][$settingKey] = $defaultValue; } } if (!isset($field['settings']['global_inventory'])) { $field['settings']['global_inventory'] = ''; } return $field; }); } } } PK!"Qvv#src/classes/Quiz/QuizController.phpnu[app = $app; $enabled = $this->isEnabled(); $this->addToGlobalMenu($enabled); if (!$enabled) { return; } $this->addToFormSettingsMenu(); $this->maybeRandomize(); $this->registerAjaxHandlers(); add_filter('fluentform/all_editor_shortcodes', function ($shortCodes) { $shortCodes[] = [ 'title' => __('Quiz', 'fluentformpro'), 'shortcodes' => [ '{quiz_result}' => 'Quiz Result Table' ] ]; return $shortCodes; }); new QuizScoreComponent(); add_filter('safe_style_css', function ($styles) { $style_tags = ['display']; $style_tags = apply_filters('fluentform/allowed_css_properties', $style_tags); foreach ($style_tags as $tag) { $styles[] = $tag; } return $styles; }); add_filter('fluentform/shortcode_parser_callback_quiz_result', [$this, 'getQuizResultTable'], 10, 2); add_filter('fluentform/form_submission_confirmation', [$this, 'maybeAppendResult'], 10, 3); add_filter('fluentform/submission_cards', [$this, 'pushQuizResult'], 10, 3); } public function registerAjaxHandlers() { $this->app->addAdminAjaxAction('ff_get_quiz_module_settings', [$this, 'getSettingsAjax']); $this->app->addAdminAjaxAction('ff_store_quiz_module_settings', [$this, 'saveSettingsAjax']); } public function getSettingsAjax() { $formId = intval($_REQUEST['form_id']); Acl::verify('fluentform_forms_manager', $formId); $settings = $this->getSettings($formId); wp_send_json_success([ 'settings' => $settings, 'quiz_fields' => $this->getQuizFields($formId), 'settings_fields' => QuizController::getIntegrationFields(), ]); } public function saveSettingsAjax() { $formId = intval($_REQUEST['form_id']); Acl::verify('fluentform_forms_manager', $formId); $settings = $_REQUEST['settings']; $formattedSettings = wp_unslash($settings); Helper::setFormMeta($formId, $this->metaKey, $formattedSettings); wp_send_json_success([ 'message' => __('Settings successfully updated'), ]); } public function getSettings($formId) { $settings = Helper::getFormMeta($formId, $this->metaKey, []); $form = $this->getForm($formId); $fields = $this->getQuizFields($form); $resultType = self::getScoreType($form); $defaults = [ 'enabled' => false, 'randomize_answer' => false, 'append_result' => true, 'randomize_question' => false, 'saved_quiz_fields' => $fields, 'grades' => [ [ 'label' => 'A', 'min' => 90, 'max' => 100, ], [ 'label' => 'B', 'min' => 80, 'max' => 89, ], [ 'label' => 'C', 'min' => 70, 'max' => 79, ], ] ]; $settings = $this->removeDeletedFields($settings, $fields); $settings = wp_parse_args($settings, $defaults); $settings['saved_quiz_fields'] = empty($settings['saved_quiz_fields']) ? [] : $settings['saved_quiz_fields']; $settings['result_type'] = $resultType; return $settings; } protected function getForm($formId) { return wpFluent()->table('fluentform_forms')->find($formId); } public static function getIntegrationFields() { return [ [ 'key' => 'append_result', 'label' => 'Append Result', 'component' => 'checkbox-single', 'checkbox_label' => __('Show Result on confirmation page', 'fluentformpro') ], [ 'key' => 'randomize_question', 'label' => 'Randomize Questions', 'checkbox_label' => __('Questions will be randomized each time its loaded', 'fluentformpro'), 'component' => 'checkbox-single' ], [ 'key' => 'randomize_answer', 'label' => 'Randomize Options', 'checkbox_label' => __('Options will be randomized each time its loaded', 'fluentformpro'), 'component' => 'checkbox-single' ], ]; } public function isEnabled() { $globalModules = get_option('fluentform_global_modules_status'); $quizAddon = Arr::get($globalModules, $this->key); if ($quizAddon == 'yes') { return true; } return false; } public function addToGlobalMenu($enabled) { add_filter('fluentform/global_addons', function ($addOns) use ($enabled) { $addOns[$this->key] = [ 'title' => 'Quiz Module', 'description' => __('With this module, you can create quizzes and show scores with grades, points, fractions, or percentages', 'fluentformpro'), 'logo' => fluentFormMix('img/integrations/quiz-icon.svg'), 'enabled' => ($enabled) ? 'yes' : 'no', 'config_url' => '', 'category' => '' ]; return $addOns; }, 9); } public function addToFormSettingsMenu() { add_filter('fluentform/form_settings_menu', function ($menu) { $menu['quiz_settings'] = [ 'title' => __('Quiz Settings', 'fluentform'), 'slug' => 'form_settings', 'hash' => 'quiz_settings', 'route' => '/quiz_settings' ]; return $menu; }); } /** * Maybe Randomize Questions and Answers * * @return void */ public function maybeRandomize() { add_filter('fluentform/rendering_form', function ($form) { $settings = $this->getSettings($form->id); $enabled = $settings['enabled'] == 'yes'; if (!$enabled) { return $form; } if ($settings['randomize_answer']) { $this->randomizeCheckableInputs(); } if (!$settings['randomize_question']) { return $form; } $fields = $form->fields; $quizFields = $this->getQuizFields($form); $quizFieldsKeys = array_keys($quizFields); $formQuizFields = array_filter($fields['fields'], function ($field) use ($quizFieldsKeys) { return in_array(Arr::get($field, 'attributes.name'), $quizFieldsKeys); }); if (empty($formQuizFields)) { return $form; } $quizGroup = []; $i = 0; foreach ($formQuizFields as $key => $field) { $inSequence = isset($formQuizFields[$key + 1]) ? $formQuizFields[$key + 1] : false; if ($inSequence) { $quizGroup[$i][$key] = $field; } else { $quizGroup[$i][$key] = $field; $i++; } } //shuffle groups and replace their positions in the original array foreach ($quizGroup as $group) { $startIndex = Arr::get(array_keys($group), '0'); shuffle($group); $length = count($group); array_splice($fields['fields'], $startIndex, $length, $group); } $form->fields = $fields; return $form; }, 10, 1); } /** * Generate Quiz Result Table * * @param $shortCode * @param ShortCodeParser $parser * * @return string|void */ public function getQuizResultTable($shortCode, ShortCodeParser $parser) { $form = $parser::getForm(); $entry = $parser::getEntry(); $quizSettings = $this->getSettings($form->id); $quizFields = Arr::get($quizSettings,'saved_quiz_fields'); if (!$entry || !$form || $quizSettings['enabled'] != 'yes') { return; } $scoreType = self::getScoreType($form); $response = json_decode($entry->response, true); $results = $this->getFormattedResults($quizSettings, $response, $form); /* For full width in single entry page */ $width = defined('FLUENTFORM_RENDERING_ENTRIES') ? '' : ' width="600"'; $html = ''; $hasRightWrongAns = !in_array($scoreType, ['total_point', 'personality']) ? true : false; $rightWrongHtml = ''; $forPdf = method_exists($parser, 'getProvider') && 'pdfFeed' === $parser::getProvider(); foreach ($results as $name => $result) { if( !in_array($name,array_keys($quizFields))){ continue; } //question $icon = $result['correct'] == true ? self::getRightIcon($forPdf) : self::getWrongIcon($forPdf); $rightWrongHtml = $hasRightWrongAns ? "
    $icon
    " : ''; $html .= ""; //answer if ('personality' == $scoreType) { $result['user_value'] = static::labelFromValue($result['user_value'], $result['options'], $result, 'user_value'); } $userValueFormatted = is_array($result['user_value']) ? join(', ', $result['user_value']) : $result['user_value']; $userValueFormatted = empty($userValueFormatted) ? '-' :$userValueFormatted; if (is_string($userValueFormatted)) { $userValueFormatted = isset($result['options'][$userValueFormatted]) ? $result['options'][$userValueFormatted] : $userValueFormatted; } $html .= sprintf( "", $userValueFormatted ); $correctAnsFormatted = is_array($result['correct_value']) ? join(', ', $result['correct_value']) : $result['correct_value']; //skip right wrong for when total point is selected if ($scoreType == 'total_point') { $score = 0; if ($result['has_advance_scoring'] == 'yes') { $score = $result['advance_points_score']; } else { if ($result['correct']) { $score = $result['points']; } } $html .= sprintf( "", __('Point', 'fluentformpro'), $score ); } else if (!$result['correct'] && $scoreType != 'total_point' && $scoreType != 'personality') { $conditionText = ''; if ($result['correct_ans_condition'] == 'not_includes') { $conditionText = 'does Not includes '; } elseif ($result['correct_ans_condition'] == 'includes_any') { $conditionText = 'any of the following '; } elseif ($result['correct_ans_condition'] == 'includes_all') { $conditionText = 'all of the following '; } if($rightWrongHtml){ $html .= sprintf( "", __('Correct answer', 'fluentformpro'), $conditionText, $correctAnsFormatted ); } } $html .= ''; } if ($scoreType == 'personality') { $scoreInput = self::getScoreInput($form); $personalityResult = $this->getUserSelectedValues($results); $result = QuizScoreComponent::determinePersonality($personalityResult, $scoreInput, $form); $result = Arr::get($scoreInput, "raw.options.$result", $result); $personalityLabel = apply_filters('fluentform/quiz_personality_label',__('Personality', 'fluentformpro'),$form); $html .= sprintf( "", $personalityLabel ); $html .= sprintf( "", $result ); $html .= ''; } $html .= '
    {$rightWrongHtml}
    {$result['label']}
    %s
    %s : %s
    %s %s: %s
    %s
    %s
    '; return apply_filters('fluentform/quiz_result_table_html', $html, $form, $results, $quizSettings, $entry); } /** * Get Available Quiz Fields * * @param $form * * @return array|mixed */ protected function getQuizFields($form) { $fields = FormFieldsParser::getEntryInputs($form, ['admin_label', 'label', 'element', 'options']); $supportedQuizFields = [ 'input_text', 'input_radio', 'input_checkbox', 'select', 'input_number', 'input_date', 'rangeslider' ]; $fields = array_filter($fields, function ($field) use ($supportedQuizFields) { return in_array($field['element'], $supportedQuizFields); }); foreach ($fields as $name => $value) { $fields[$name]['enabled'] = false; $fields[$name]['points'] = 1; $fields[$name]['correct_answer'] = []; $fields[$name]['condition'] = 'equal'; $fields[$name]['has_advance_scoring'] = 'no'; $fields[$name]['advance_points'] = $this->advancePoints($fields[$name]); } return $fields; } /** * Remove Deleted inputs * * @param $settings * @param $fields * * @return mixed */ protected function removeDeletedFields($settings, $fields) { if (!isset($settings['saved_quiz_fields'])) { return $settings; } $savedFields = $settings['saved_quiz_fields']; foreach ($savedFields as $fieldKey => $value) { if (!isset($fields[$fieldKey])) { unset($savedFields[$fieldKey]); } if (Arr::exists($fields,$fieldKey) && Arr::exists($fields[$fieldKey], 'options')) { $savedFields[$fieldKey]['options'] = Arr::get($fields[$fieldKey], 'options'); } } $settings['saved_quiz_fields'] = $savedFields; return $settings; } /** * Validate Answer * * @param $settings * @param $userValue * @param $correctValue * * @return bool */ protected function isCorrect($settings, $userValue, $correctValue = '', $options = []) { $isCorrect = false; $element = $settings['element']; switch ($element) { case 'input_radio': if (!$userValue) { break; } if (in_array($userValue, $correctValue)) { $isCorrect = true; } break; case 'select': case 'input_text': case 'rangeslider': case 'input_date': case 'input_checkbox': case 'input_number': if (!$userValue) { break; } $hasAdvanceScoring = $settings['has_advance_scoring'] === 'yes'; if ($hasAdvanceScoring) { //check if select is not a multiselect if ($element == 'select' && is_string($correctValue)) { $isCorrect = $userValue == $correctValue; break; } //if it has advance scoring then for right answer match all value greater than 0 with user values //else assume as wrong answer but count the scores $correctValues = static::labelFromValue($correctValue, $options, $settings, 'correct_value'); return count(array_intersect($userValue, $correctValues)) == count($userValue); } $condition = Arr::get($settings, 'condition'); if ($condition == 'equal') { if (is_array($correctValue)) { $correctValue = array_shift($correctValue); } if (is_array($userValue)) { $userValue = array_shift($userValue); } if (apply_filters('fluentform/quiz_case_sensitive_off', __return_false())) { $userValue = strtolower($userValue); $correctValue = strtolower($correctValue); } if ($userValue == $correctValue) { $isCorrect = true; } } elseif ($condition == 'includes_any') { //check if any user values exists in correct answers if (!is_array($userValue)) { $userValue = [$userValue]; } $isCorrect = (bool)array_intersect($correctValue, $userValue); } elseif ($condition == 'includes_all') { //check if all user values exists in correct answers if (!is_array($userValue)) { $userValue = [$userValue]; } $commonValue = array_intersect($correctValue, $userValue); $isCorrect = $commonValue && count($correctValue) == count($commonValue); } elseif ($condition == 'not_includes') { //check if all user values not exists in correct answers if (!is_array($userValue)) { $userValue = [$userValue]; } $isCorrect = !array_intersect($correctValue, $userValue); } break; } return $isCorrect; } /** * Get Formatted Quiz Result * * @param $quizFields * @param $response * * @return array */ public function getFormattedResults($quizSettings, $response, $form) { $quizFields = $quizSettings['saved_quiz_fields']; $quizType = Arr::get($quizSettings,'result_type'); $inputs = FormFieldsParser::getInputs($form, ['element', 'options', 'label']); $quizResults = []; $quizFields = $this->arrayReposition($quizFields, array_keys($inputs)); foreach ($quizFields as $key => $settings) { if ($settings['enabled'] != true) { continue; } $correctValue = Arr::get($settings, 'correct_answer'); $userValue = Arr::get($response, $key, ''); $options = Arr::get($inputs, $key . '.options'); $quizResults[$key] = [ 'correct' => $this->isCorrect($settings, $userValue, $correctValue, $options), 'correct_value' => static::labelFromValue($correctValue, $options, $settings, 'correct_value'), 'correct_ans_condition' => $settings['condition'], 'options' => $options, 'user_value' => ($quizType != 'personality') ? static::labelFromValue($userValue, $options, $settings, 'user_value') : $userValue, 'points' => $settings['points'], 'label' => Arr::get($inputs, $key . '.label'), 'has_advance_scoring' => $settings['has_advance_scoring'], 'advance_points' => array_reduce($settings['advance_points'], function ($sum, $itemScore) { $sum += $itemScore; return $sum; }), 'advance_points_score' => $this->calcAdvancePoints($settings, $userValue), ]; } return $quizResults; } /** * Calculate user selected values from quiz results. * * @param array $quizResults * @return array */ public function getUserSelectedValues($quizResults) { $userSelectedValues = []; foreach ($quizResults as $result) { if(empty($result['user_value'])){ continue; } if (is_array($result['user_value'])) { // If 'user_value' is an array $userSelectedValues = array_merge($userSelectedValues, $result['user_value']); } else { // If 'user_value' is a string, convert it to an array $userSelectedValues[] = $result['user_value']; } } return $userSelectedValues; } /** * Array Restructured to get Form Fields structure * @param $array * @param $keys * @return array */ protected function arrayReposition($array, $keys) { $returnArray = []; foreach ($keys as $key) { if (Arr::get($array, $key)) { $returnArray[$key] = Arr::get($array, $key); } } return $returnArray; } /** * Get input label from value * * @param $targetValues * @param $options * @param $settings * @param $type * @return array|mixed */ private static function labelFromValue($targetValues, $options, $settings, $type) { $hasAdvanceScoring = $settings['has_advance_scoring'] === 'yes'; if ($hasAdvanceScoring && $type == 'correct_value') { $advanceScores = Arr::get($settings, 'advance_points'); $correctOptions = []; foreach ($advanceScores as $label => $score) { if ($score >= 1) { $correctOptions[] = $label; } } return $correctOptions; } if (is_array($targetValues)) { $formattedValue = []; foreach ($targetValues as $value) { $formattedValue[] = isset($options[$value]) ? $options[$value] : $value; } $targetValues = $formattedValue; } else { $targetValues = isset($options[$targetValues]) ? $options[$targetValues] : $targetValues; } return $targetValues; } /** * Maybe Append quiz result * * @param $data * @param $formData * @param $form * * @return mixed */ public function maybeAppendResult($data, $formData, $form) { $settings = $this->getSettings($form->id); if ($settings['append_result'] == true) { $data['messageToShow'] .= '{quiz_result}'; } return $data; } /** * Adds quiz result in the single entry page * @param $cards * @param $entryData * @param $submission * @return array|mixed */ public function pushQuizResult($cards, $entryData, $submission) { $formId = $submission->form_id; $settings = $this->getSettings($formId); if (($settings['enabled'] != 'yes')) { return $cards; } $form = $this->getForm($formId); $contents = '

    {quiz_result}

    '; $resultHtml = ShortCodeParser::parse( $contents, $submission->id, $entryData, $form ); $widgetData = [ 'title' => __('Quiz Result', 'fluentformpro'), 'content' => $resultHtml ]; $cards['quiz_result'] = $widgetData; return $cards; } /** * Wrong Answer Icon * * @return string */ protected static function getWrongIcon($forPdf) { $icon = ''; if ($forPdf) { $icon = ''; } return apply_filters('fluentform/quiz_wrong_ans_icon', $icon); } /** * Right Answer Icon * * @return string */ protected static function getRightIcon($forPdf) { $icon = ''; if ($forPdf) { $icon = ''; } return apply_filters('fluentform/quiz_right_ans_icon', $icon); } public function advancePoints($options) { if (!isset($options['options'])) { return (object)[]; } $formattedOptions = []; foreach ($options['options'] as $key => $value) { $formattedOptions[$key] = 0; } return $formattedOptions; } private function calcAdvancePoints($settings, $userValue) { $hasAdvancePoint = Arr::get($settings, 'has_advance_scoring'); if ($hasAdvancePoint) { $advancePoints = Arr::get($settings, 'advance_points'); $userValue = is_array($userValue) ? $userValue : [$userValue]; $total = 0; foreach ($userValue as $value) { $value = Arr::get($advancePoints, $value, 0); if (!is_numeric($value)) { continue; } $total += $value; } return $total; } else { return Arr::get($settings, 'points'); } } private static function getScoreType($form) { $scoreType = ''; $scoreInput = self::getScoreInput($form); if ($scoreInput) { $scoreType = Arr::get($scoreInput, 'raw.settings.result_type'); } return $scoreType; } public static function getScoreInput($form){ $scoreInput = \FluentForm\App\Modules\Form\FormFieldsParser::getInputsByElementTypes($form,['quiz_score'],['raw']); if ($scoreInput) { return array_shift($scoreInput); } return false; } public function randomizeCheckableInputs() { add_filter('fluentform/rendering_field_data_input_checkbox', function ($data) { $options = $data['settings']['advanced_options']; shuffle($options); $data['settings']['advanced_options'] = $options; return $data; }, 10, 1); add_filter('fluentform/rendering_field_data_input_radio', function ($data) { $options = $data['settings']['advanced_options']; shuffle($options); $data['settings']['advanced_options'] = $options; return $data; }, 10, 1); } } PK!.R # #'src/classes/Quiz/QuizScoreComponent.phpnu[key}",function ($element) { if(!isset($element['options'])){ $element['options'] = [ 'Hero' => 'Hero', 'Villain' => 'Villain', 'Mentor' => 'Mentor', 'Sage' => 'Sage', 'Innocent' => 'Innocent', 'Rebel' => 'Rebel', 'Explorer' => 'Explorer', ]; } if(!isset($element['settings']['select_options'])){ $element['settings']['select_options'] = ''; } return $element; }); add_filter("fluentform/input_data_{$this->key}", [$this, 'addScoreToSubmission'], 10, 4); } public function getComponent() { return [ 'index' => 6, 'element' => $this->key, 'attributes' => array( 'type' => 'hidden', 'name' => 'quiz-score', 'value' => 'empty', ), 'settings' => array( 'admin_field_label' => 'Quiz Score', 'result_type' => 'total_point', 'quiz_info' => '', 'select_options' => '', ), 'options' => [ 'Hero' => __('Hero', 'fluentformpro'), 'Mentor' => __('Mentor', 'fluentformpro'), 'Sage' => __('Sage', 'fluentformpro'), 'Innocent' => __('Innocent', 'fluentformpro'), ], 'editor_options' => array( 'title' => __('Quiz Score', 'fluentformpro'), 'icon_class' => 'el-icon-postcard', 'template' => 'inputHidden' ), ]; } public function getGeneralEditorElements() { return [ 'admin_field_label', 'name', 'result_type', 'quiz_info', 'select_options', ]; } public function getEditorCustomizationSettings() { return [ 'result_type' => [ 'template' => 'select', 'label' => __('Select Score Type', 'fluentformpro'), 'help_text' => __('Select Score Type that you want to show', 'fluentformpro'), 'options' => [ [ 'label' => __('Total Point. Example: 70', 'fluentformpro'), 'value' => 'total_point' ], [ 'label' => __('Total Correct Questions. Example: 6', 'fluentformpro'), 'value' => 'total_correct' ], [ 'label' => __('Fraction Point. Example: 6/10', 'fluentformpro'), 'value' => 'fraction_point' ], [ 'label' => __('Grade System. Example: A', 'fluentformpro'), 'value' => 'grade' ], [ 'label' => __('Percentage. Example: 70%', 'fluentformpro'), 'value' => 'percent' ], [ 'label' => __('Personality Quiz', 'fluentformpro'), 'value' => 'personality' ] ] ], 'select_options' => [ 'template' => 'selectOptions', 'label' => __('Personality Types', 'fluentform'), 'help_text' => __('Create visual options for the field and checkmark them for default selection.', 'fluentform'), 'hide_default_value' => true, 'show_values' => true, 'dependency' => [ 'depends_on' => 'settings/result_type', 'value' => 'personality', 'operator' => '==', ], ], 'quiz_info' => [ 'template' => 'infoBlock', 'text' => __('
    Personality Quiz Instruction
    Personality will be determined based on most answered option. The quiz answers and personality option value must match, so please add your answers value accordingly.
    ', 'fluentformpro'), 'dependency' => [ 'depends_on' => 'settings/result_type', 'value' => 'personality', 'operator' => '==', ], ], ]; } public function render($data, $form) { return (new Text())->compile($data, $form); } /** * Process and generate quiz result from result type for Submission * * @param $fieldValue * @param $field * @param $submissionData * @param $form * @return Quiz Result */ public function addScoreToSubmission($fieldValue, $field, $submissionData, $form) { $quizController = new QuizController(); $quizSettings = $quizController->getSettings($form->id); $quizResults = $quizController->getFormattedResults($quizSettings, $submissionData, $form); $score = 0; $totalCorrect = 0; $totalPoints = 0; $advancePoints = 0; $quizFields = $quizSettings['saved_quiz_fields']; $scoreType = Arr::get($field, 'raw.settings.result_type'); foreach ($quizResults as $name => $result) { if( !in_array($name,array_keys($quizFields))){ continue; } if ($result['has_advance_scoring'] == 'yes') { $score += $result['advance_points_score']; $totalCorrect++; $totalPoints += $result['advance_points']; } else { if ($result['correct']) { $score += $result['points']; $totalCorrect++; } $totalPoints += $result['points']; } } $result = apply_filters('fluentform/quiz_no_grade_label', __('Not Graded', 'fluentformpro')); switch ($scoreType) { case 'total_point': $result = $score; break; case 'total_correct': $result = $totalCorrect; break; case 'fraction_point': $result = $totalCorrect . '/' . count($quizResults); break; case 'percent': $result = number_format((($score / $totalPoints) * 100), 2) . '%'; break; case 'grade': $grades = $quizSettings['grades']; foreach ($grades as $grade) { if (($score >= Arr::get($grade, 'min')) && ($score <= Arr::get($grade, 'max'))) { $result = Arr::get($grade, 'label'); } } break; case 'personality': $userSelections = $quizController->getUserSelectedValues($quizResults); $result = $this->determinePersonality($userSelections, $field, $form); break; } return apply_filters('fluentform/quiz_score_value', $result, $form->id, $scoreType, $quizResults); } public static function determinePersonality($userSelectedValues, $field, $form) { $personalityResult = apply_filters('fluentform/quiz_personality_test_fallback_label', __('Did not match any options!'), $form); $personalityOptions = Arr::get($field, 'raw.options'); if(empty($userSelectedValues) || empty($personalityOptions)){ return $personalityResult; } $mostSelectedOption = array_search(max(array_count_values($userSelectedValues)), array_count_values($userSelectedValues)); foreach ($personalityOptions as $key => $value) { if ($key === $mostSelectedOption) { $personalityResult = $key; break; } } return $personalityResult; } } PK!Hz('('#src/classes/SharePage/SharePage.phpnu[isEnabled(); add_action('wp', [$this, 'renderLandingForm']); add_filter('fluentform/global_addons', function ($addOns) use ($enabled) { $addOns['sharePages'] = [ 'title' => 'Landing Pages', 'description' => __('Create completely custom "distraction-free" form landing pages to boost conversions', 'fluentformpro'), 'logo' => fluentFormMix('img/integrations/landing_pages.png'), 'enabled' => ($enabled) ? 'yes' : 'no', 'config_url' => '', 'category' => '' ]; return $addOns; }, 9); if (!$enabled) { return; } add_filter('fluentform/form_settings_menu', function ($menu) { $menu['landing_pages'] = [ 'title' => __('Landing Page', 'fluentformpro'), 'slug' => 'form_settings', 'hash' => 'landing_pages', 'route' => '/landing_pages' ]; return $menu; }); add_action('wp_ajax_ff_get_landing_page_settings', [$this, 'getSettingsAjax']); add_action('wp_ajax_ff_store_landing_page_settings', [$this, 'saveSettingsAjax']); } public function getSettingsAjax() { $formId = intval($_REQUEST['form_id']); Acl::verify('fluentform_forms_manager', $formId); $settings = $this->getSettings($formId); $shareUrl = ''; if ($settings['status'] == 'yes') { $params = [ 'ff_landing' => $formId ]; $shareUrl = add_query_arg($params, site_url('/')); } wp_send_json_success([ 'settings' => $settings, 'share_url' => $shareUrl ]); } public function saveSettingsAjax() { $formId = intval($_REQUEST['form_id']); Acl::verify('fluentform_forms_manager', $formId); $settings = $_REQUEST['settings']; $formattedSettings = wp_unslash($settings); $formattedSettings['description'] = wp_kses_post(wp_unslash($settings['description'])); Helper::setFormMeta($formId, $this->metaKey, $formattedSettings); $shareUrl = ''; if ($formattedSettings['status'] == 'yes') { $shareUrl = add_query_arg(['ff_landing' => $formId], site_url('/')); } wp_send_json_success([ 'message' => __('Settings successfully updated'), 'share_url' => $shareUrl ]); } public function getSettings($formId) { $settings = Helper::getFormMeta($formId, $this->metaKey, []); $defaults = [ 'status' => 'no', 'logo' => '', 'title' => '', 'description' => '', 'color_schema' => '#4286c4', 'custom_color' => '#4286c4', 'design_style' => 'modern', 'featured_image' => '', 'background_image' => '', 'layout' => 'default', 'media' => fluentFormGetRandomPhoto(), 'brightness' => 0, 'alt_text' => '', 'media_x_position' => 50, 'media_y_position' => 50 ]; return wp_parse_args($settings, $defaults); } public function renderLandingForm() { $ff_landing = ArrayHelper::get($_GET, 'ff_landing'); if (!$ff_landing || is_admin()) { return; } $hasConfirmation = false; if (isset($_REQUEST['entry_confirmation'])) { do_action_deprecated( 'fluentformpro_entry_confirmation', [ $_REQUEST ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/entry_confirmation', 'Use fluentform/entry_confirmation instead of fluentformpro_entry_confirmation.' ); do_action('fluentform/entry_confirmation', $_REQUEST); $hasConfirmation = true; } $formId = intval($_GET['ff_landing']); $form = wpFluent()->table('fluentform_forms')->where('id', $formId)->first(); if (!$form) { return; } $settings = $this->getSettings($formId); if (ArrayHelper::get($settings, 'status') != 'yes') { return; } $pageTitle = $form->title; if ($settings['title']) { $pageTitle = $settings['title']; } add_action('wp_enqueue_scripts', function () use ($formId) { $theme = Helper::getFormMeta($formId, '_ff_selected_style'); $styles = $theme ? [$theme] : []; do_action('fluentform/load_form_assets', $formId, $styles); wp_enqueue_style('fluent-form-styles'); wp_enqueue_style('fluentform-public-default'); wp_enqueue_script('fluent-form-submission'); }); $backgroundColor = ArrayHelper::get($settings, 'color_schema'); if ($backgroundColor == 'custom') { $backgroundColor = ArrayHelper::get($settings, 'custom_color'); } $landingContent = '[fluentform id="' . $formId . '"]'; if(!$hasConfirmation) { $salt = ArrayHelper::get($settings, 'share_url_salt'); if($salt && $salt != ArrayHelper::get($_REQUEST, 'form')) { $landingContent = __('Sorry, You do not have access to this form', 'fluentformpro'); $pageTitle = __('No Access', 'fluentformpro'); $settings['title'] = ''; $settings['description'] = ''; } } $data = [ 'settings' => $settings, 'title' => $pageTitle, 'form_id' => $formId, 'form' => $form, 'bg_color' => $backgroundColor, 'landing_content' => $landingContent, 'has_header' => $settings['logo'] || $settings['title'] || $settings['description'], 'isEmbeded' => !!ArrayHelper::get($_GET, 'embedded') ]; $data = apply_filters_deprecated( 'fluentform_landing_vars', [ $data, $formId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/landing_vars', 'Use fluentform/landing_vars instead of fluentform_landing_vars.' ); $landingVars = apply_filters('fluentform/landing_vars', $data, $formId); $this->loadPublicView($landingVars); } public function loadPublicView($landingVars) { add_action('wp_enqueue_scripts', function () { wp_enqueue_style( 'fluent-form-landing', FLUENTFORMPRO_DIR_URL . 'public/css/form_landing.css', [], FLUENTFORMPRO_VERSION ); }); add_filter('pre_get_document_title', function ($title) use ($landingVars) { $separator = apply_filters('document_title_separator', '-'); return $landingVars['title'] . ' ' . $separator . ' ' . get_bloginfo('name', 'display'); }); // let's deregister all the style and scripts here add_action('wp_print_scripts', function () { global $wp_scripts; $contentUrl = content_url(); if ($wp_scripts) { foreach ($wp_scripts->queue as $script) { if (!isset($wp_scripts->registered[$script])) { continue; } $src = $wp_scripts->registered[$script]->src; $shouldLoad = strpos($src, $contentUrl) !== false && ( strpos($src, 'fluentform') !== false || strpos($src, 'AffiliateWP') !== false ); if (!$shouldLoad) { wp_dequeue_script($wp_scripts->registered[$script]->handle); // wp_deregister_script($wp_scripts->registered[$script]->handle); } } } },1); if(isset($_GET['embedded'])) { add_action('wp_print_styles', function () { global $wp_styles; if($wp_styles) { foreach ($wp_styles->queue as $style) { $src = $wp_styles->registered[$style]->src; if (!strpos($src, 'fluentform') !== false) { wp_dequeue_style($wp_styles->registered[$style]->handle); } } } }, 1); if($landingVars['settings']['design_style'] == 'modern') { $landingVars['settings']['design_style'] = 'classic'; $landingVars['bg_color'] = '#fff'; } } status_header(200); echo $this->loadView('landing_page_view', $landingVars); exit(200); } public function loadView($view, $data = []) { $file = FLUENTFORMPRO_DIR_PATH . 'src/views/' . $view . '.php'; extract($data); ob_start(); include($file); return ob_get_clean(); } public function isEnabled() { $globalModules = get_option('fluentform_global_modules_status'); $sharePages = ArrayHelper::get($globalModules, 'sharePages'); if (!$sharePages || $sharePages == 'yes') { return true; } return false; } } PK!unMMsrc/classes/DoubleOptin.phpnu[isActivated($formId)) { $statuses[$this->initialStatusSlug] = __('Unconfirmed', 'fluentformpro'); $statuses[$this->confirmedStatusSlug] = __('Confirmed', 'fluentformpro'); } return $statuses; }, 10, 2); add_filter('fluentform/form_settings_ajax', function ($settings, $formId) { if ($optinSettings = $this->getDoubleOptinSettings($formId)) { $settings['double_optin'] = $optinSettings; } return $settings; }, 10, 2); add_action('fluentform/after_save_form_settings', array($this, 'saveFormSettings'), 10, 2); add_action('fluentform/before_form_actions_processing', array($this, 'processOnSubmission'), 10, 3); add_action('fluentform/entry_confirmation', array($this, 'confirmSubmission'), 1, 1); add_action('wp_ajax_fluentform_get_global_double_optin', array($this, 'getGlobalSettingsAjax')); add_action('wp_ajax_fluentform_save_global_double_optin', array($this, 'updateGlobalSettingsAjax')); add_action('fluentform_do_email_report_scheduled_tasks', array($this, 'maybeDeleteUnconfirmedEntries'), 99); add_action('fluentform/maybe_scheduled_jobs', array($this, 'maybeDeleteUnconfirmedEntries'), 99); add_action('fluentform_do_email_report_scheduled_tasks', array($this, 'maybeDeleteOldEntries')); } public function isActivated($formId = false) { if (!$formId) { return false; } static $activated; if ($activated) { return $activated == 'yes'; } $settings = $this->getDoubleOptinSettings($formId); if ($settings && !empty($settings['status'])) { $activated = $settings['status']; } return $activated == 'yes'; } /** * Get all double opt-in statuses * * @return array */ public function getStatuses() { return [$this->initialStatusSlug, $this->confirmedStatusSlug]; } public function saveFormSettings($formId, $allSettings) { $doubleOptinSettings = ArrayHelper::get($allSettings, 'double_optin', []); if ($doubleOptinSettings) { Helper::setFormMeta($formId, 'double_optin_settings', $doubleOptinSettings); } } public function getDoubleOptinSettings($formId, $scope = 'admin') { $defaults = [ 'status' => 'no', 'confirmation_message' => __('Please check your email inbox to confirm this submission', 'fluentformpro'), 'email_body_type' => 'global', 'email_subject' => '', 'email_body' => '', 'email_field' => '', 'skip_if_logged_in' => 'yes', 'skip_if_fc_subscribed' => 'yes', 'asPlainText' => 'no' ]; $settings = \FluentForm\App\Helpers\Helper::getFormMeta($formId, 'double_optin_settings', []); if ($settings) { $defaults = wp_parse_args($settings, $defaults); } $globalSettings = $this->getGlobalSettings(); if ($globalSettings['enabled'] != 'yes') { return false; } if (empty($defaults['email_body']) || $defaults['email_body_type'] == 'global') { $defaults['email_body'] = $globalSettings['email_body']; } if (empty($defaults['email_subject']) || $defaults['email_body_type'] == 'global') { $defaults['email_subject'] = $globalSettings['email_subject']; } if ($scope == 'public') { $defaults = wp_parse_args($defaults, $globalSettings); } return $defaults; } public function processOnSubmission($insertId, $formData, $form) { $doubleOptinSettings = $this->getDoubleOptinSettings($form->id, 'public'); $submission = Submission::find($insertId); if ( !$doubleOptinSettings || ArrayHelper::get($doubleOptinSettings, 'status') != 'yes' || (ArrayHelper::get($doubleOptinSettings, 'skip_if_logged_in') == 'yes' && get_current_user_id()) || $submission->status == $this->initialStatusSlug || (new AdminApproval())->isEntryOnAdminApprovalMode($submission->status) ) { return; } $emailField = ArrayHelper::get($doubleOptinSettings, 'email_field'); if (!$emailField) { return; } $emailId = trim(ArrayHelper::get($formData, $emailField)); if (!$emailId || !is_email($emailId)) { return; } if (ArrayHelper::get($doubleOptinSettings, 'skip_if_fc_subscribed') == 'yes' && defined('FLUENTCRM')) { $crmContact = FluentCrmApi('contacts')->getContact($emailId); if ($crmContact && $crmContact->status == 'subscribed') { return; } } wpFluent()->table('fluentform_submissions') ->where('id', $insertId) ->update([ 'status' => $this->initialStatusSlug ]); $data = ArrayHelper::only($doubleOptinSettings, [ 'confirmation_message', 'email_subject', 'email_body' ]); $data = ShortCodeParser::parse($data, $insertId, $formData); $emailBody = $data['email_body']; $confirmationUrl = add_query_arg([ 'ff_landing' => $form->id, 'entry_confirmation' => Helper::getSubmissionMeta($insertId, '_entry_uid_hash') ], site_url()); $emailBody = str_replace('#confirmation_url#', $confirmationUrl, $emailBody); $notification = [ 'name' => 'Double Optin Email', 'fromName' => ArrayHelper::get($doubleOptinSettings, 'fromName'), 'fromEmail' => ArrayHelper::get($doubleOptinSettings, 'fromEmail', ''), 'replyTo' => ArrayHelper::get($doubleOptinSettings, 'replyTo'), 'bcc' => '', 'subject' => $data['email_subject'], 'message' => $data['email_body'], 'enabled' => true, 'email_template' => '', 'sendTo' => [ 'type' => 'email', 'email' => $emailId, 'field' => '' ] ]; $emailNotificationClass = new EmailNotification(wpFluentForm()); $emailHeaders = $emailNotificationClass->getHeaders($notification); if (ArrayHelper::get($doubleOptinSettings, 'asPlainText') != 'yes') { $emailBody = $emailNotificationClass->getEmailWithTemplate($emailBody, $form, $notification); } $mailSent = wp_mail($emailId, $data['email_subject'], $emailBody, $emailHeaders); do_action('fluentform/log_data', [ 'parent_source_id' => $form->id, 'source_type' => 'submission_item', 'source_id' => $insertId, 'component' => 'DoubleOptin', 'status' => 'info', 'title' => __('Double Optin Confirmation Email sent', 'fluentformpro'), 'description' => __('Double Optin Email sent to form submitter [', 'fluentformpro') . $emailId . ']', ]); $result = [ 'insert_id' => $insertId, 'result' => [ 'redirectTo' => 'samePage', 'message' => $data['confirmation_message'], 'action' => 'hide_form' ], 'error' => '', 'optin_sent' => $mailSent ]; wp_send_json_success($result, 200); } private function getGlobalSettings() { $defaults = [ 'email_body' => '

    Please Confirm Your Submission

     

    Confirm Submission

     

    If you received this email by mistake, simply delete it. Your form submission won\'t proceed if you don\'t click the confirmation link above.

    ', 'email_subject' => __('Please confirm your form submission', 'fluentformpro'), 'fromName' => '', 'fromEmail' => '', 'replyTo' => '', 'enabled' => 'yes', 'auto_delete_status' => 'yes', 'auto_delete_day_span' => 5, 'asPlainText' => 'no' ]; if ($settings = get_option('_fluentform_double_optin_settings')) { return wp_parse_args($settings, $defaults); } return $defaults; } public function confirmSubmission($data) { $formId = intval(ArrayHelper::get($data, 'ff_landing')); if (!$this->isActivated($formId)) { die('Sorry! Invalid Form Confirmation URL'); } $hash = sanitize_text_field(ArrayHelper::get($data, 'entry_confirmation')); $meta = wpFluent()->table('fluentform_submission_meta') ->where('form_id', $formId) ->where('meta_key', '_entry_uid_hash') ->where('value', $hash) ->first(); if (!$meta) { die('Sorry! Invalid Confirmation URL'); } $insertId = $meta->response_id; $entry = wpFluent()->table('fluentform_submissions') ->where('form_id', $formId) ->where('id', $insertId) ->first(); if (!$entry) { die('Sorry! Invalid Confirmation URL.'); } $submissionData = json_decode($entry->response, true); $form = wpFluent()->table('fluentform_forms')->find($formId); // Double opt-in with admin approval, admin approval always run after double opt-in confirmation. // If submission already on admin approval mode, render admin approval status on double Opt-in confirmation page. $adminApproval = new AdminApproval(); if ($adminApproval->isEntryOnAdminApprovalMode($entry->status)) { $adminApproval->renderApprovalConfirmationView($entry, $form, $submissionData); return; } if ($entry->status == $this->initialStatusSlug || Helper::getSubmissionMeta($insertId, 'is_form_action_fired') != 'yes') { do_action('fluentform/log_data', [ 'parent_source_id' => $form->id, 'source_type' => 'submission_item', 'source_id' => $insertId, 'component' => 'DoubleOptin', 'status' => 'info', 'title' => 'Double Optin Confirmed', 'description' => 'Form submitter confirmed the double optin email from IP address: ' . wpFluentForm()->request->getIp(), ]); $confirmation = (new SubmissionHandlerService())->processSubmissionData($insertId, $submissionData, $form); $result = $confirmation['result']; wpFluent()->table('fluentform_submissions') ->where('id', $insertId) ->update([ 'status' => $this->confirmedStatusSlug ]); } else { $result = (new SubmissionHandlerService())->getReturnData($insertId, $form, $submissionData); } if ($redirectUrl = ArrayHelper::get($result, 'redirectUrl')) { wp_redirect($redirectUrl); exit(); } $sharePage = new SharePage(); $settings = $sharePage->getSettings($formId); $message = ShortCodeParser::parse($result['message'], $insertId, $submissionData); $submissionVars = [ 'settings' => $settings, 'title' => 'Submission Confirmed - ' . $form->title, 'form_id' => $formId, 'entry' => $entry, 'form' => $form, 'bg_color' => $settings['custom_color'], 'landing_content' => $message, 'has_header' => false, 'isEmbeded' => !!ArrayHelper::get($_GET, 'embedded') ]; $submissionVars = apply_filters_deprecated( 'fluentform_submission_vars', [ $submissionVars, $formId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/submission_vars', 'Use fluentform/submission_vars instead of fluentform_submission_vars.' ); // We have to show the message now $landingVars = apply_filters('fluentform/submission_vars', $submissionVars, $formId); $sharePage->loadPublicView($landingVars); } public function getGlobalSettingsAjax() { \FluentForm\App\Modules\Acl\Acl::verify('fluentform_settings_manager'); wp_send_json_success([ 'settings' => $this->getGlobalSettings() ], 200); } public function updateGlobalSettingsAjax() { \FluentForm\App\Modules\Acl\Acl::verify('fluentform_settings_manager'); $settings = wp_unslash($_REQUEST['settings']); update_option('_fluentform_double_optin_settings', $settings, 'no'); wp_send_json_success([ 'message' => 'Settings successfully updated' ], 200); } public function maybeDeleteUnconfirmedEntries() { $this->maybeDeleteOldEntries(); $settings = $this->getGlobalSettings(); if ( ArrayHelper::get($settings, 'auto_delete_status') != 'yes' || ArrayHelper::get($settings, 'enabled') != 'yes' ) { return; } $daySpan = intval(ArrayHelper::get($settings, 'auto_delete_day_span')); if (!$daySpan) { $daySpan = 7; } $date = date('Y-m-d H:i:s', (time() - $daySpan * DAY_IN_SECONDS)); $oldEntries = wpFluent()->table('fluentform_submissions') ->where('status', $this->initialStatusSlug) ->where('created_at', '<', $date) ->limit(100) ->get(); if ($oldEntries) { $this->deleteEntries($oldEntries); } } public function maybeDeleteOldEntries() { $autoDeleteFormMetas = wpFluent()->table('fluentform_form_meta') ->where('meta_key', 'auto_delete_days') ->get(); if (!$autoDeleteFormMetas) { return; } $formGroups = []; foreach ($autoDeleteFormMetas as $meta) { if (!isset($formGroups[$meta->value])) { $formGroups[$meta->value] = []; } $formGroups[$meta->value][] = $meta->form_id; } foreach ($formGroups as $delayDays => $formIds) { $date = date('Y-m-d H:i:s', (time() - $delayDays * DAY_IN_SECONDS)); $oldEntries = wpFluent()->table('fluentform_submissions') ->whereIn('form_id', $formIds) ->where('created_at', '<', $date) ->limit(100) ->get(); $this->deleteEntries($oldEntries); } } // @todo need to move on helper class public function deleteEntries($entries) { if (!$entries) { return; } $deletingIds = []; foreach ($entries as $entry) { $deletingIds[] = $entry->id; $this->deleteAssociateFiles($entry); } $deletingIds = array_filter($deletingIds); if (!$deletingIds) { return; } wpFluent()->table('fluentform_submissions') ->whereIn('id', $deletingIds) ->delete(); wpFluent()->table('fluentform_submission_meta') ->whereIn('response_id', $deletingIds) ->delete(); wpFluent()->table('fluentform_logs') ->whereIn('source_id', $deletingIds) ->where('source_type', 'submission_item') ->delete(); wpFluent()->table('fluentform_entry_details') ->whereIn('submission_id', $deletingIds) ->delete(); ob_start(); try { wpFluent()->table('fluentform_order_items') ->whereIn('submission_id', $deletingIds) ->delete(); wpFluent()->table('fluentform_transactions') ->whereIn('submission_id', $deletingIds) ->delete(); wpFluent()->table('ff_scheduled_actions') ->whereIn('origin_id', $deletingIds) ->where('type', 'submission_action') ->delete(); } catch (\Exception $exception) { // ... } $errors = ob_get_clean(); } private function deleteAssociateFiles($entry) { $status = apply_filters_deprecated( 'fluentform_disable_attachment_delete', [ false, $entry->form_id ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/disable_attachment_delete', 'Use fluentform/disable_attachment_delete instead of fluentform_disable_attachment_delete.' ); if (apply_filters('fluentform/disable_attachment_delete', $status, $entry->form_id)) { return; } $fileFields = $this->getFileFields($entry->form_id); if (!$fileFields) { return; } $data = json_decode($entry->response, true); foreach ($fileFields as $field) { if (!empty($data[$field])) { $files = $data[$field]; if (!is_array($files)) { $files = [$files]; } foreach ($files as $file) { $file = wp_upload_dir()['basedir'] . FLUENTFORM_UPLOAD_DIR . '/' . basename($file); if (is_readable($file) && !is_dir($file)) { @unlink($file); } } } } } private function getFileFields($formId) { static $fieldsCache = []; if (isset($formsCache[$formId])) { return $formsCache; } $form = wpFluent()->table('fluentform_forms')->find($formId); if (!$form) { return []; } $fields = FormFieldsParser::getAttachmentInputFields($form, ['element', 'attributes']); $filesFieldNames = []; foreach ($fields as $field) { if (!empty($field['attributes']['name'])) { $filesFieldNames[] = $field['attributes']['name']; } } $fieldsCache[$formId] = $filesFieldNames; return $fieldsCache[$formId]; } } PK! !=ttsrc/classes/FormStyler.phpnu[app = wpFluentForm(); $this->request = $this->app['request']; } public function boot() { add_action('wp_enqueue_scripts', [$this, 'addAdvancedCSS']); $this->app->addAction('fluentform/form_styler', [$this, 'initStyler']); $this->app->addAction('fluentform/form_imported', [$this, 'maybeGenerateStyle'], 10, 1); $this->app->addAction('fluentform/form_duplicated', [$this, 'maybeGenerateStyle'], 10, 1); $this->app->addFilter('fluentform/build_style_from_theme', [$this, 'buildStyleFromTheme'], 10, 3); $this->app->addFilter('fluentform/block_editor_style_presets', [$this, 'getBlockPresets']); $this->app->addAdminAjaxAction('fluentform_save_form_styler', [$this, 'saveStylerSettings']); $this->app->addAdminAjaxAction('fluentform_get_form_styler', [$this, 'getStylerSettings']); $this->app->addAdminAjaxAction('fluentform_export_form_style', [$this, 'export']); $this->app->addAdminAjaxAction('fluentform_import_form_style', [$this, 'import']); } public function addAdvancedCSS() { $formId = intval($this->request->get('preview_id')); $fluentFormPages = $this->request->get('fluent_forms_pages'); if ($fluentFormPages && $formId) { add_action('wp_head', function () use ($formId) { $theme = Helper::getFormMeta($formId, '_ff_selected_style'); $styles = $theme ? [$theme] : []; do_action('fluentform/load_form_assets', $formId, $styles); }, 99); } } public function initStyler($formId) { wp_enqueue_style('fluentform_styler', FLUENTFORMPRO_DIR_URL . 'public/css/styler_app.css', [], FLUENTFORMPRO_VERSION); wp_enqueue_script('fluentform_styler', FLUENTFORMPRO_DIR_URL . 'public/js/styler_app.js', ['jquery'], FLUENTFORMPRO_VERSION); wp_enqueue_style('dashicons'); wp_localize_script('fluentform_styler', 'fluent_styler_vars', [ 'ajaxurl' => admin_url('admin-ajax.php'), 'form_id' => $formId, 'nonce' => wp_create_nonce(), 'styler_str' => [ 'Save Settings' => __('Save Settings', 'fluentformpro'), 'General' => __('General', 'fluentformpro'), 'Form Style Template' => __('Form Style Template', 'fluentformpro'), 'Reset' => __('Reset', 'fluentformpro'), 'Export' => __('Export', 'fluentformpro'), 'Select Preset Styles' => __('Select Preset Styles', 'fluentformpro'), 'Customize Selected Preset' => __('Customize Selected Preset', 'fluentformpro'), 'Label Styles' => __('Label Styles', 'fluentformpro'), 'Input & Textarea' => __('Input & Textarea', 'fluentformpro'), 'Placeholder' => __('Placeholder', 'fluentformpro'), 'Custom Html & Section Break Style' => __('Custom Html & Section Break Style', 'fluentformpro'), 'Grid Table Style' => __('Grid Table Style', 'fluentformpro'), 'Radio & Checkbox Style' => __('Radio & Checkbox Style', 'fluentformpro'), 'Range Slider Style' => __('Range Slider Style', 'fluentformpro'), 'Net Promoter Style' => __('Net Promoter Style', 'fluentformpro'), 'Payment Summary Style' => __('Payment Summary Style', 'fluentformpro'), 'Payment Coupon Style' => __('Payment Coupon Style', 'fluentformpro'), 'Multi Page - Header Style' => __('Multi Page - Header Style', 'fluentformpro'), 'Multi Page - Next Button Style' => __('Multi Page - Next Button Style', 'fluentformpro'), 'Multi Page - Previous Button Style' => __('Multi Page - Previous Button Style', 'fluentformpro'), 'Image or File Button Style' => __('Image or File Button Style', 'fluentformpro'), 'Submit Button Style' => __('Submit Button Style', 'fluentformpro'), 'Misc' => __('Misc', 'fluentformpro'), 'Container Styles' => __('Container Styles', 'fluentformpro'), 'Asterisk Styles' => __('Asterisk Styles', 'fluentformpro'), 'Inline Error Message Styles' => __('Inline Error Message Styles', 'fluentformpro'), 'After Submit Success Message Styles' => __('After Submit Success Message Styles', 'fluentformpro'), 'After Submit Error Message Styles' => __('After Submit Error Message Styles', 'fluentformpro'), 'Import' => __('Import', 'fluentformpro'), 'Import Styles From Another Form' => __('Import Styles From Another Form', 'fluentformpro'), 'Select an Existing Form to Apply Style' => __('Select an Existing Form to Apply Style', 'fluentformpro'), 'Select Form To Apply' => __('Select Form To Apply', 'fluentformpro'), 'Custom Styles' => __('Custom Styles', 'fluentformpro'), 'General Styles' => __('General Styles', 'fluentformpro'), 'Import Fluent Form Style' => __('Import Fluent Form Style', 'fluentformpro'), 'Unit' => __('Unit', 'fluentformpro'), 'Position' => __('Position', 'fluentformpro'), 'Gradient' => __('Gradient', 'fluentformpro'), 'Classic' => __('Classic', 'fluentformpro'), 'Select' => __('Select', 'fluentformpro'), 'X Position' => __('X Position', 'fluentformpro'), 'Y Position' => __('Y Position', 'fluentformpro'), 'Attachment' => __('Attachment', 'fluentformpro'), 'Repeat' => __('Repeat', 'fluentformpro'), 'Size' => __('Size', 'fluentformpro'), 'X Size' => __('X Size', 'fluentformpro'), 'Y Size' => __('Y Size', 'fluentformpro'), 'Primary Color' => __('Primary Color', 'fluentformpro'), 'Location' => __('Location', 'fluentformpro'), 'Secondary Color' => __('Secondary Color', 'fluentformpro'), 'Type' => __('Type', 'fluentformpro'), 'Radial' => __('Radial', 'fluentformpro'), 'Linear' => __('Linear', 'fluentformpro'), 'Angle' => __('Angle', 'fluentformpro'), 'Default' => __('Default', 'fluentformpro'), 'Center Center' => __('Center Center', 'fluentformpro'), 'Center Left' => __('Center Left', 'fluentformpro'), 'Center Right' => __('Center Right', 'fluentformpro'), 'Center Top' => __('Center Top', 'fluentformpro'), 'Top Left' => __('Top Left', 'fluentformpro'), 'Top Right' => __('Top Right', 'fluentformpro'), 'Bottom Center' => __('Bottom Center', 'fluentformpro'), 'Bottom Left' => __('Bottom Left', 'fluentformpro'), 'Bottom Right' => __('Bottom Right', 'fluentformpro'), 'Custom' => __('Custom', 'fluentformpro'), 'Auto' => __('Auto', 'fluentformpro'), 'Cover' => __('Cover', 'fluentformpro'), 'Contain' => __('Contain', 'fluentformpro'), 'Scroll' => __('Scroll', 'fluentformpro'), 'Fixed' => __('Fixed', 'fluentformpro'), 'No-repeat' => __('No-repeat', 'fluentformpro'), 'Repeat-x' => __('Repeat-x', 'fluentformpro'), 'Repeat-y' => __('Repeat-y', 'fluentformpro'), 'yes' => __('yes', 'fluentformpro'), 'no' => __('no', 'fluentformpro'), 'Border Type' => __('Border Type', 'fluentformpro'), 'Border Color' => __('Border Color', 'fluentformpro'), 'Border Width' => __('Border Width', 'fluentformpro'), 'Border Radius' => __('Border Radius', 'fluentformpro'), 'Solid' => __('Solid', 'fluentformpro'), 'Double' => __('Double', 'fluentformpro'), 'Dotted' => __('Dotted', 'fluentformpro'), 'Dashed' => __('Dashed', 'fluentformpro'), 'Groove' => __('Groove', 'fluentformpro'), 'Ridge' => __('Ridge', 'fluentformpro'), 'Color' => __('Color', 'fluentformpro'), 'Horizontal' => __('Horizontal', 'fluentformpro'), 'Vertical' => __('Vertical', 'fluentformpro'), 'Blur' => __('Blur', 'fluentformpro'), 'Spread' => __('Spread', 'fluentformpro'), 'Outline' => __('Outline', 'fluentformpro'), 'Inset' => __('Inset', 'fluentformpro'), 'Box Shadow' => __('Box Shadow', 'fluentformpro'), 'Alignment' => __('Alignment', 'fluentformpro'), 'Padding' => __('Padding', 'fluentformpro'), 'Margin' => __('Margin', 'fluentformpro'), 'Label Styling' => __('Label Styling', 'fluentformpro'), 'Description Styling' => __('Description Styling', 'fluentformpro'), 'Error' => __('Error', 'fluentformpro'), 'Items Color' => __('Items Color', 'fluentformpro'), 'Checked Background Colors' => __('Checked Background Colors', 'fluentformpro'), 'Active Color' => __('Active Color', 'fluentformpro'), 'Inactive Color (opposite color)' => __('Inactive Color (opposite color)', 'fluentformpro'), 'Text color' => __('Text color', 'fluentformpro'), 'Height' => __('Height', 'fluentformpro'), 'Handle Size' => __('Handle Size', 'fluentformpro'), 'Inactive Color' => __('Inactive Color', 'fluentformpro'), 'Odd Color' => __('Odd Color', 'fluentformpro'), 'Radio Border Same as Checkbox' => __('Radio Border Same as Checkbox', 'fluentformpro'), 'Form Border Settings' => __('Form Border Settings', 'fluentformpro'), 'Enable Form Border' => __('Enable Form Border', 'fluentformpro'), 'Use custom Border style' => __('Use custom Border style', 'fluentformpro'), 'Enable Border' => __('Enable Border', 'fluentformpro'), 'Custom Border' => __('Custom Border', 'fluentformpro'), 'Enable Smart UI' => __('Enable Smart UI', 'fluentformpro'), 'Smart UI Margin' => __('Smart UI Margin', 'fluentformpro'), 'Normal' => __('Normal', 'fluentformpro'), 'Focus' => __('Focus', 'fluentformpro'), 'Table Head' => __('Table Head', 'fluentformpro'), 'Table Body' => __('Table Body', 'fluentformpro'), 'Button Height' => __('Button Height', 'fluentformpro'), 'Hover' => __('Hover', 'fluentformpro'), 'Active Background Color' => __('Active Background Color', 'fluentformpro'), 'Inactive Background Color' => __('Inactive Background Color', 'fluentformpro'), 'Line Height' => __('Line Height', 'fluentformpro'), 'Text Position (fixed)' => __('Text Position (fixed)', 'fluentformpro'), 'Table Footer' => __('Table Footer', 'fluentformpro'), 'Button' => __('Button', 'fluentformpro'), 'Typography' => __('Typography', 'fluentformpro'), 'Background Color' => __('Background Color', 'fluentformpro'), 'Background Image' => __('Background Image', 'fluentformpro'), 'Border' => __('Border', 'fluentformpro'), 'Font Size' => __('Font Size', 'fluentformpro'), 'Font Weight' => __('Font Weight', 'fluentformpro'), 'Transform' => __('Transform', 'fluentformpro'), 'Bold' => __('Bold', 'fluentformpro'), 'Uppercase' => __('Uppercase', 'fluentformpro'), 'Lowercase' => __('Lowercase', 'fluentformpro'), 'Capitalize' => __('Capitalize', 'fluentformpro'), 'Italic' => __('Italic', 'fluentformpro'), 'Oblique' => __('Oblique', 'fluentformpro'), 'Font Style' => __('Font Style', 'fluentformpro'), 'Text Decoration' => __('Text Decoration', 'fluentformpro'), 'Underline' => __('Underline', 'fluentformpro'), 'Overline' => __('Overline', 'fluentformpro'), 'Line Through' => __('Line Through', 'fluentformpro'), 'None' => __('None', 'fluentformpro'), 'Letter Spacing' => __('Letter Spacing', 'fluentformpro'), 'Word Spacing' => __('Word Spacing', 'fluentformpro'), ] ]); wp_enqueue_media(); echo '
    '; } public function getStylerSettings() { Acl::verify('fluentform_forms_manager'); $formId = intval($this->request->get('form_id')); $presetStyle = Helper::getFormMeta($formId, '_ff_selected_style', ''); $styles = Helper::getFormMeta($formId, '_ff_form_styles', []); $preSets = $this->getPresets(); $returnData = [ 'has_stripe_inline_element' => ArrayHelper::get(PaymentHelper::getStripeInlineConfig($formId), 'is_inline', false), 'preset_style' => $presetStyle, 'styles' => $styles, 'presets' => $preSets, 'is_multipage' => Helper::isMultiStepForm($formId), 'has_section_break' => Helper::hasFormElement($formId, 'section_break'), 'has_html_input' => Helper::hasFormElement($formId, 'custom_html'), 'has_tabular_grid' => Helper::hasFormElement($formId, 'tabular_grid'), 'has_range_slider' => Helper::hasFormElement($formId, 'rangeslider'), 'has_net_promoter' => Helper::hasFormElement($formId, 'net_promoter_score'), 'has_payment_summary' => Helper::hasFormElement($formId, 'payment_summary_component'), 'has_payment_coupon' => Helper::hasFormElement($formId, 'payment_coupon'), 'has_image_or_file_button' => Helper::hasFormElement($formId, 'input_file') || Helper::hasFormElement($formId, 'input_image'), ]; if (!empty($this->request->get('with_all_form_styles'))) { $returnData['existing_form_styles'] = $this->getOtherFormStyles($formId); } wp_send_json_success($returnData, 200); } public function saveStylerSettings() { Acl::verify('fluentform_forms_manager'); $formId = intval($this->request->get('form_id')); $styles = wp_unslash($this->request->get('form_styles')); if (is_string($styles) && Helper::isJson($styles)) { $styles = json_decode($styles, true); } $theme = sanitize_text_field($this->request->get('style_name')); $theme = $theme ? $theme : 'ffs_default'; Helper::setFormMeta($formId, '_ff_selected_style', $theme); $this->generateStyle($formId, $styles, $theme); wp_send_json_success([ 'message' => __('Styles successfully updated', 'fluentformpro'), ], 200); } public function getPresets() { // to do check css file with current style generated from JSON $presets = [ 'ffs_default' => [ 'label' => __('Default', ''), 'style' => '[]', ], 'ffs_modern_b' => [ 'label' => __('Modern (Bold)', ''), 'style' => '{"container_styles":{"backgroundColor":{"label":"Background Color","element":"ff_color","value":""},"color":{"label":"Color","element":"ff_color","value":""},"margin":{"label":"Form Margin","element":"ff_around_item","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"},"padding":{"label":"Form Padding","element":"ff_around_item","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"},"border":{"label":"Form Border Settings","element":"ff_border_config","status_label":"Enable Form Border","value":{"border_radius":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"border_width":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"border_type":"solid","border_color":"","status":"no"}}},"asterisk_styles":{"color_asterisk":{"label":"Color","element":"ff_color","value":""}},"inline_error_msg_style":{"color":{"label":"Color","element":"ff_color","value":""},"typography":{"label":"Typography","element":"ff_typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}}},"success_msg_style":{"color":{"label":"Color","element":"ff_color","value":""},"backgroundColor":{"label":"Background Color","element":"ff_color","value":""},"typography":{"label":"Typography","element":"ff_typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"boxshadow":{"label":"Box Shadow","element":"ff_boxshadow_config","value":{"horizontal":{"value":"0","type":"px"},"vertical":{"value":"0","type":"px"},"blur":{"value":"0","type":"px"},"spread":{"value":"0","type":"px"},"color":"","position":""}}},"error_msg_style":{"color":{"label":"Color","element":"ff_color","value":""},"backgroundColor":{"label":"Background Color","element":"ff_color","value":""},"typography":{"label":"Typography","element":"ff_typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"boxshadow":{"label":"Box Shadow","element":"ff_boxshadow_config","value":{"horizontal":{"value":"0","type":"px"},"vertical":{"value":"0","type":"px"},"blur":{"value":"0","type":"px"},"spread":{"value":"0","type":"px"},"color":"","position":""}}},"label_styles":{"color":{"label":"Color","element":"ff_color","value":"rgba(66, 67, 68, 1)"},"typography":{"label":"Typography","element":"ff_typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}}},"input_styles":{"all_tabs":{"label":"","element":"ff_tabs","tabs":{"normal":{"key":"normal","label":"Normal","value":{"backgroundColor":{"label":"Background Color","key":"backgroundcolor","value":""},"color":{"label":"Color","key":"color","value":""},"typography":{"label":"Typography","key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"boxshadow":{"label":"Box Shadow","key":"boxshadow","value":{"horizontal":{"value":"0","type":"px"},"vertical":{"value":"0","type":"px"},"blur":{"value":"0","type":"px"},"spread":{"value":"0","type":"px"},"color":"","position":""}},"border":{"label":"","status_label":"Use custom Border style","key":"border","value":{"border_radius":{"top":"5","left":"5","right":"5","bottom":"5","linked":"yes"},"border_width":{"top":"2","left":"2","right":"2","bottom":"2","linked":"yes"},"border_type":"solid","border_color":"rgba(117, 117, 117, 1)","status":"yes"}}}},"focus":{"key":"focus","label":"Focus","value":{"backgroundColor":{"label":"Background Color","key":"backgroundcolor","value":""},"color":{"label":"Color","key":"color","value":""},"typography":{"label":"Typography","key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"boxshadow":{"label":"Box Shadow","key":"boxshadow","value":{"horizontal":{"value":"0","type":"px"},"vertical":{"value":"0","type":"px"},"blur":{"value":"0","type":"px"},"spread":{"value":"0","type":"px"},"color":"","position":""}},"border":{"label":"","status_label":"Use custom Border style","key":"border","value":{"border_radius":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"border_width":{"top":"1","left":"1","right":"1","bottom":"1","linked":"yes"},"border_type":"solid","border_color":"rgba(79, 75, 75, 1)","status":"no"}}}}}}},"placeholder_styles":{"color":{"label":"Color","element":"ff_color","value":""},"typography":{"label":"Typography","element":"ff_typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}}},"submit_button_style":{"allignment":{"label":"Allignment","element":"ff_allignment_item","value":""},"all_tabs":{"label":"","element":"ff_tabs","tabs":{"normal":{"key":"normal","label":"Normal","value":{"backgroundColor":{"label":"Background Color","key":"backgroundcolor","value":""},"color":{"label":"Color","key":"color","value":""},"width":{"label":"Button Width","key":"width","value":""},"padding":{"label":"Form Padding","key":"padding","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"},"margin":{"label":"","key":"margin","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"},"typography":{"key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"boxshadow":{"key":"boxshadow","label":"Box Shadow","value":{"horizontal":{"value":"0","type":"px"},"vertical":{"value":"0","type":"px"},"blur":{"value":"0","type":"px"},"spread":{"value":"0","type":"px"},"color":"","position":""}},"border":{"label":"","key":"border","status_label":"Use custom Border style","value":{"border_radius":{"top":"4","left":"4","right":"4","bottom":"4","linked":"yes"},"border_width":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"border_type":"solid","border_color":"","status":"yes"}}}},"hover":{"key":"hover","label":"Hover","value":{"backgroundColor":{"label":"Background Color","key":"backgroundcolor","value":""},"color":{"label":"Color","key":"color","value":""},"typography":{"key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"boxshadow":{"key":"boxshadow","label":"Box Shadow","value":{"horizontal":{"value":"0","type":"px"},"vertical":{"value":"0","type":"px"},"blur":{"value":"0","type":"px"},"spread":{"value":"0","type":"px"},"color":"","position":""}},"border":{"label":"","key":"border","status_label":"Use custom Border style","value":{"border_radius":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"border_width":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"border_type":"solid","border_color":"","status":""}}}}},"status":"yes"}},"radio_checkbox_style":{"radio_checkbox":{"label":"","element":"ff_radio_checkbox","status_label":"Enable Smart UI","value":{"color":{"label":"Border Color","value":""},"active_color":{"label":"Checked Background Color","value":""},"border":{"label":"","key":"border","status_label":"Use custom Border style","value":{"border_radius":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"border_width":{"top":"2","left":"2","right":"2","bottom":"2","linked":"yes"},"border_type":"solid","border_color":"rgba(117, 117, 117, 1)","status":"yes"}}},"status":"yes"},"color":{"label":"Items Color","element":"ff_color","value":""}},"sectionbreak_styles":{"all_tabs":{"label":"","element":"ff_tabs","tabs":{"LabelStyling":{"key":"LabelStyling","label":"Label Styling","value":{"color":{"label":"Color","key":"color","value":""},"typography":{"label":"Typography","key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"padding":{"label":"Section Break Padding","key":"padding","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"},"margin":{"label":"Section Break Margin","key":"margin","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"}}},"DescriptionStyling":{"key":"DescriptionStyling","label":"Description Styling","value":{"color":{"label":"Color","key":"color","value":""},"typography":{"label":"Typography","key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"padding":{"label":"Section Break Padding","key":"padding","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"},"margin":{"label":"Section Break Margin","key":"margin","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"}}}}}},"gridtable_style":{"all_tabs":{"label":"","element":"ff_tabs","tabs":{"TableHead":{"key":"tableHead","label":"Table Head","value":{"color":{"label":"Color","key":"color","value":""},"backgroundColor":{"label":"Background Color","key":"backgroundcolor","value":""},"typography":{"label":"Typography","key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}}}},"TableBody":{"key":"tableBody","label":"Table Body","value":{"color":{"label":"Color","key":"color","value":""},"backgroundColor":{"label":"Background Color","key":"backgroundcolor","value":""},"typography":{"label":"Typography","key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}}}}}}}}', ], 'ffs_modern_l' => [ 'label' => __('Modern (Light)', ''), 'style' => '{"container_styles":{"backgroundColor":{"label":"Background Color","element":"ff_color","value":""},"color":{"label":"Color","element":"ff_color","value":""},"margin":{"label":"Form Margin","element":"ff_around_item","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"},"padding":{"label":"Form Padding","element":"ff_around_item","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"},"border":{"label":"Form Border Settings","element":"ff_border_config","status_label":"Enable Form Border","value":{"border_radius":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"border_width":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"border_type":"solid","border_color":"","status":"no"}}},"asterisk_styles":{"color_asterisk":{"label":"Color","element":"ff_color","value":""}},"inline_error_msg_style":{"color":{"label":"Color","element":"ff_color","value":""},"typography":{"label":"Typography","element":"ff_typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}}},"success_msg_style":{"color":{"label":"Color","element":"ff_color","value":""},"backgroundColor":{"label":"Background Color","element":"ff_color","value":""},"typography":{"label":"Typography","element":"ff_typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"boxshadow":{"label":"Box Shadow","element":"ff_boxshadow_config","value":{"horizontal":{"value":"0","type":"px"},"vertical":{"value":"0","type":"px"},"blur":{"value":"0","type":"px"},"spread":{"value":"0","type":"px"},"color":"","position":""}}},"error_msg_style":{"color":{"label":"Color","element":"ff_color","value":""},"backgroundColor":{"label":"Background Color","element":"ff_color","value":""},"typography":{"label":"Typography","element":"ff_typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"boxshadow":{"label":"Box Shadow","element":"ff_boxshadow_config","value":{"horizontal":{"value":"0","type":"px"},"vertical":{"value":"0","type":"px"},"blur":{"value":"0","type":"px"},"spread":{"value":"0","type":"px"},"color":"","position":""}}},"label_styles":{"color":{"label":"Color","element":"ff_color","value":"rgba(66, 67, 68, 1)"},"typography":{"label":"Typography","element":"ff_typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}}},"input_styles":{"all_tabs":{"label":"","element":"ff_tabs","tabs":{"normal":{"key":"normal","label":"Normal","value":{"backgroundColor":{"label":"Background Color","key":"backgroundcolor","value":""},"color":{"label":"Color","key":"color","value":""},"typography":{"label":"Typography","key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"boxshadow":{"label":"Box Shadow","key":"boxshadow","value":{"horizontal":{"value":"0","type":"px"},"vertical":{"value":"0","type":"px"},"blur":{"value":"0","type":"px"},"spread":{"value":"0","type":"px"},"color":"","position":""}},"border":{"label":"","status_label":"Use custom Border style","key":"border","value":{"border_radius":{"top":"5","left":"5","right":"5","bottom":"5","linked":"yes"},"border_width":{"top":"1","left":"1","right":"1","bottom":"1","linked":"yes"},"border_type":"solid","border_color":"rgba(116, 108, 108, 1)","status":"yes"}}}},"focus":{"key":"focus","label":"Focus","value":{"backgroundColor":{"label":"Background Color","key":"backgroundcolor","value":""},"color":{"label":"Color","key":"color","value":""},"typography":{"label":"Typography","key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"boxshadow":{"label":"Box Shadow","key":"boxshadow","value":{"horizontal":{"value":"0","type":"px"},"vertical":{"value":"0","type":"px"},"blur":{"value":"0","type":"px"},"spread":{"value":"0","type":"px"},"color":"","position":""}},"border":{"label":"","status_label":"Use custom Border style","key":"border","value":{"border_radius":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"border_width":{"top":"1","left":"1","right":"1","bottom":"1","linked":"yes"},"border_type":"solid","border_color":"rgba(79, 75, 75, 1)","status":"no"}}}}}}},"placeholder_styles":{"color":{"label":"Color","element":"ff_color","value":""},"typography":{"label":"Typography","element":"ff_typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}}},"submit_button_style":{"allignment":{"label":"Allignment","element":"ff_allignment_item","value":""},"all_tabs":{"label":"","element":"ff_tabs","tabs":{"normal":{"key":"normal","label":"Normal","value":{"backgroundColor":{"label":"Background Color","key":"backgroundcolor","value":""},"color":{"label":"Color","key":"color","value":""},"width":{"label":"Button Width","key":"width","value":""},"padding":{"label":"Form Padding","key":"padding","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"},"margin":{"label":"","key":"margin","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"},"typography":{"key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"boxshadow":{"key":"boxshadow","label":"Box Shadow","value":{"horizontal":{"value":"0","type":"px"},"vertical":{"value":"0","type":"px"},"blur":{"value":"0","type":"px"},"spread":{"value":"0","type":"px"},"color":"","position":""}},"border":{"label":"","key":"border","status_label":"Use custom Border style","value":{"border_radius":{"top":"4","left":"4","right":"4","bottom":"4","linked":"yes"},"border_width":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"border_type":"solid","border_color":"","status":"yes"}}}},"hover":{"key":"hover","label":"Hover","value":{"backgroundColor":{"label":"Background Color","key":"backgroundcolor","value":""},"color":{"label":"Color","key":"color","value":""},"typography":{"key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"boxshadow":{"key":"boxshadow","label":"Box Shadow","value":{"horizontal":{"value":"0","type":"px"},"vertical":{"value":"0","type":"px"},"blur":{"value":"0","type":"px"},"spread":{"value":"0","type":"px"},"color":"","position":""}},"border":{"label":"","key":"border","status_label":"Use custom Border style","value":{"border_radius":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"border_width":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"border_type":"solid","border_color":"","status":""}}}}},"status":"yes"}},"radio_checkbox_style":{"radio_checkbox":{"label":"","element":"ff_radio_checkbox","status_label":"Enable Smart UI","value":{"color":{"label":"Border Color","value":""},"active_color":{"label":"Checked Background Color","value":""},"border":{"label":"","key":"border","status_label":"Use custom Border style","value":{"border_radius":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"border_width":{"top":"1","left":"1","right":"1","bottom":"1","linked":"yes"},"border_type":"solid","border_color":"rgba(117, 117, 117, 1)","status":"yes"}}},"status":"yes"},"color":{"label":"Items Color","element":"ff_color","value":""}},"sectionbreak_styles":{"all_tabs":{"label":"","element":"ff_tabs","tabs":{"LabelStyling":{"key":"LabelStyling","label":"Label Styling","value":{"color":{"label":"Color","key":"color","value":""},"typography":{"label":"Typography","key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"padding":{"label":"Section Break Padding","key":"padding","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"},"margin":{"label":"Section Break Margin","key":"margin","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"}}},"DescriptionStyling":{"key":"DescriptionStyling","label":"Description Styling","value":{"color":{"label":"Color","key":"color","value":""},"typography":{"label":"Typography","key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"padding":{"label":"Section Break Padding","key":"padding","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"},"margin":{"label":"Section Break Margin","key":"margin","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"}}}}}},"gridtable_style":{"all_tabs":{"label":"","element":"ff_tabs","tabs":{"TableHead":{"key":"tableHead","label":"Table Head","value":{"color":{"label":"Color","key":"color","value":""},"backgroundColor":{"label":"Background Color","key":"backgroundcolor","value":""},"typography":{"label":"Typography","key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}}}},"TableBody":{"key":"tableBody","label":"Table Body","value":{"color":{"label":"Color","key":"color","value":""},"backgroundColor":{"label":"Background Color","key":"backgroundcolor","value":""},"typography":{"label":"Typography","key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}}}}}}}}', ], 'ffs_classic' => [ 'label' => __('Classic', ''), 'style' => '{"container_styles":{"backgroundColor":{"label":"Background Color","element":"ff_color","value":""},"color":{"label":"Color","element":"ff_color","value":""},"margin":{"label":"Form Margin","element":"ff_around_item","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"},"padding":{"label":"Form Padding","element":"ff_around_item","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"},"border":{"label":"Form Border Settings","element":"ff_border_config","status_label":"Enable Form Border","value":{"border_radius":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"border_width":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"border_type":"solid","border_color":"","status":"no"}}},"asterisk_styles":{"color_asterisk":{"label":"Color","element":"ff_color","value":""}},"inline_error_msg_style":{"color":{"label":"Color","element":"ff_color","value":""},"typography":{"label":"Typography","element":"ff_typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}}},"success_msg_style":{"color":{"label":"Color","element":"ff_color","value":""},"backgroundColor":{"label":"Background Color","element":"ff_color","value":""},"typography":{"label":"Typography","element":"ff_typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"boxshadow":{"label":"Box Shadow","element":"ff_boxshadow_config","value":{"horizontal":{"value":"0","type":"px"},"vertical":{"value":"0","type":"px"},"blur":{"value":"0","type":"px"},"spread":{"value":"0","type":"px"},"color":"","position":""}}},"error_msg_style":{"color":{"label":"Color","element":"ff_color","value":""},"backgroundColor":{"label":"Background Color","element":"ff_color","value":""},"typography":{"label":"Typography","element":"ff_typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"boxshadow":{"label":"Box Shadow","element":"ff_boxshadow_config","value":{"horizontal":{"value":"0","type":"px"},"vertical":{"value":"0","type":"px"},"blur":{"value":"0","type":"px"},"spread":{"value":"0","type":"px"},"color":"","position":""}}},"label_styles":{"color":{"label":"Color","element":"ff_color","value":""},"typography":{"label":"Typography","element":"ff_typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}}},"input_styles":{"all_tabs":{"label":"","element":"ff_tabs","tabs":{"normal":{"key":"normal","label":"Normal","value":{"backgroundColor":{"label":"Background Color","key":"backgroundcolor","value":""},"color":{"label":"Color","key":"color","value":""},"typography":{"label":"Typography","key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"boxshadow":{"label":"Box Shadow","key":"boxshadow","value":{"horizontal":{"value":"0","type":"px"},"vertical":{"value":"0","type":"px"},"blur":{"value":"0","type":"px"},"spread":{"value":"0","type":"px"},"color":"","position":""}},"border":{"label":"","status_label":"Use custom Border style","key":"border","value":{"border_radius":{"top":"0","left":"0","right":"0","bottom":"0","linked":"yes"},"border_width":{"top":"1","left":"1","right":"1","bottom":"1","linked":"yes"},"border_type":"solid","border_color":"rgba(116, 108, 108, 1)","status":"yes"}}}},"focus":{"key":"focus","label":"Focus","value":{"backgroundColor":{"label":"Background Color","key":"backgroundcolor","value":""},"color":{"label":"Color","key":"color","value":""},"typography":{"label":"Typography","key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"boxshadow":{"label":"Box Shadow","key":"boxshadow","value":{"horizontal":{"value":"0","type":"px"},"vertical":{"value":"0","type":"px"},"blur":{"value":"0","type":"px"},"spread":{"value":"0","type":"px"},"color":"","position":""}},"border":{"label":"","status_label":"Use custom Border style","key":"border","value":{"border_radius":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"border_width":{"top":"1","left":"1","right":"1","bottom":"1","linked":"yes"},"border_type":"solid","border_color":"rgba(79, 75, 75, 1)","status":"no"}}}}}}},"placeholder_styles":{"color":{"label":"Color","element":"ff_color","value":""},"typography":{"label":"Typography","element":"ff_typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}}},"submit_button_style":{"allignment":{"label":"Allignment","element":"ff_allignment_item","value":""},"all_tabs":{"label":"","element":"ff_tabs","tabs":{"normal":{"key":"normal","label":"Normal","value":{"backgroundColor":{"label":"Background Color","key":"backgroundcolor","value":""},"color":{"label":"Color","key":"color","value":""},"width":{"label":"Button Width","key":"width","value":""},"padding":{"label":"Form Padding","key":"padding","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"},"margin":{"label":"","key":"margin","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"},"typography":{"key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"boxshadow":{"key":"boxshadow","label":"Box Shadow","value":{"horizontal":{"value":"0","type":"px"},"vertical":{"value":"0","type":"px"},"blur":{"value":"0","type":"px"},"spread":{"value":"0","type":"px"},"color":"","position":""}},"border":{"label":"","key":"border","status_label":"Use custom Border style","value":{"border_radius":{"top":"1","left":"1","right":"1","bottom":"1","linked":"yes"},"border_width":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"border_type":"solid","border_color":"","status":"yes"}}}},"hover":{"key":"hover","label":"Hover","value":{"backgroundColor":{"label":"Background Color","key":"backgroundcolor","value":""},"color":{"label":"Color","key":"color","value":""},"typography":{"key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"boxshadow":{"key":"boxshadow","label":"Box Shadow","value":{"horizontal":{"value":"0","type":"px"},"vertical":{"value":"0","type":"px"},"blur":{"value":"0","type":"px"},"spread":{"value":"0","type":"px"},"color":"","position":""}},"border":{"label":"","key":"border","status_label":"Use custom Border style","value":{"border_radius":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"border_width":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"border_type":"solid","border_color":"","status":""}}}}},"status":"yes"}},"radio_checkbox_style":{"radio_checkbox":{"label":"","element":"ff_radio_checkbox","status_label":"Enable Smart UI","value":{"color":{"label":"Border Color","value":""},"active_color":{"label":"Checked Background Color","value":""},"border":{"label":"","key":"border","status_label":"Use custom Border style","value":{"border_radius":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"border_width":{"top":"1","left":"1","right":"1","bottom":"1","linked":"yes"},"border_type":"solid","border_color":"#212529","status":"yes"}}},"status":"yes"},"color":{"label":"Items Color","element":"ff_color","value":""}},"sectionbreak_styles":{"all_tabs":{"label":"","element":"ff_tabs","tabs":{"LabelStyling":{"key":"LabelStyling","label":"Label Styling","value":{"color":{"label":"Color","key":"color","value":""},"typography":{"label":"Typography","key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"padding":{"label":"Section Break Padding","key":"padding","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"},"margin":{"label":"Section Break Margin","key":"margin","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"}}},"DescriptionStyling":{"key":"DescriptionStyling","label":"Description Styling","value":{"color":{"label":"Color","key":"color","value":""},"typography":{"label":"Typography","key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"padding":{"label":"Section Break Padding","key":"padding","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"},"margin":{"label":"Section Break Margin","key":"margin","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"}}}}}},"gridtable_style":{"all_tabs":{"label":"","element":"ff_tabs","tabs":{"TableHead":{"key":"tableHead","label":"Table Head","value":{"color":{"label":"Color","key":"color","value":""},"backgroundColor":{"label":"Background Color","key":"backgroundcolor","value":""},"typography":{"label":"Typography","key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}}}},"TableBody":{"key":"tableBody","label":"Table Body","value":{"color":{"label":"Color","key":"color","value":""},"backgroundColor":{"label":"Background Color","key":"backgroundcolor","value":""},"typography":{"label":"Typography","key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}}}}}}}}', ], 'ffs_bootstrap' => [ 'label' => __('Bootstrap Style', ''), 'style' => '{"container_styles":{"backgroundColor":{"label":"Background Color","element":"ff_color","value":""},"color":{"label":"Color","element":"ff_color","value":""},"margin":{"label":"Form Margin","element":"ff_around_item","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"},"padding":{"label":"Form Padding","element":"ff_around_item","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"},"border":{"label":"Form Border Settings","element":"ff_border_config","status_label":"Enable Form Border","value":{"border_radius":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"border_width":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"border_type":"solid","border_color":"","status":"no"}}},"asterisk_styles":{"color_asterisk":{"label":"Color","element":"ff_color","value":""}},"inline_error_msg_style":{"color":{"label":"Color","element":"ff_color","value":""},"typography":{"label":"Typography","element":"ff_typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}}},"success_msg_style":{"color":{"label":"Color","element":"ff_color","value":""},"backgroundColor":{"label":"Background Color","element":"ff_color","value":""},"typography":{"label":"Typography","element":"ff_typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"boxshadow":{"label":"Box Shadow","element":"ff_boxshadow_config","value":{"horizontal":{"value":"0","type":"px"},"vertical":{"value":"0","type":"px"},"blur":{"value":"0","type":"px"},"spread":{"value":"0","type":"px"},"color":"","position":""}}},"error_msg_style":{"color":{"label":"Color","element":"ff_color","value":""},"backgroundColor":{"label":"Background Color","element":"ff_color","value":""},"typography":{"label":"Typography","element":"ff_typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"boxshadow":{"label":"Box Shadow","element":"ff_boxshadow_config","value":{"horizontal":{"value":"0","type":"px"},"vertical":{"value":"0","type":"px"},"blur":{"value":"0","type":"px"},"spread":{"value":"0","type":"px"},"color":"","position":""}}},"label_styles":{"color":{"label":"Color","element":"ff_color","value":""},"typography":{"label":"Typography","element":"ff_typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}}},"input_styles":{"all_tabs":{"label":"","element":"ff_tabs","tabs":{"normal":{"key":"normal","label":"Normal","value":{"backgroundColor":{"label":"Background Color","key":"backgroundcolor","value":""},"color":{"label":"Color","key":"color","value":""},"typography":{"label":"Typography","key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"boxshadow":{"label":"Box Shadow","key":"boxshadow","value":{"horizontal":{"value":"0","type":"px"},"vertical":{"value":"0","type":"px"},"blur":{"value":"0","type":"px"},"spread":{"value":"0","type":"px"},"color":"","position":""}},"border":{"label":"","status_label":"Use custom Border style","key":"border","value":{"border_radius":{"top":"4","left":"4","right":"4","bottom":"4","linked":"yes"},"border_width":{"top":"1","left":"1","right":"1","bottom":"1","linked":"yes"},"border_type":"solid","border_color":"rgba(206, 212, 218, 1)","status":"yes"}}}},"focus":{"key":"focus","label":"Focus","value":{"backgroundColor":{"label":"Background Color","key":"backgroundcolor","value":""},"color":{"label":"Color","key":"color","value":""},"typography":{"label":"Typography","key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"boxshadow":{"label":"Box Shadow","key":"boxshadow","value":{"horizontal":{"value":"0","type":"px"},"vertical":{"value":"0","type":"px"},"blur":{"value":"0","type":"px"},"spread":{"value":"0","type":"px"},"color":"","position":""}},"border":{"label":"","status_label":"Use custom Border style","key":"border","value":{"border_radius":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"border_width":{"top":"1","left":"1","right":"1","bottom":"1","linked":"yes"},"border_type":"solid","border_color":"rgba(79, 75, 75, 1)","status":"no"}}}}}}},"placeholder_styles":{"color":{"label":"Color","element":"ff_color","value":""},"typography":{"label":"Typography","element":"ff_typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}}},"submit_button_style":{"allignment":{"label":"Allignment","element":"ff_allignment_item","value":""},"all_tabs":{"label":"","element":"ff_tabs","tabs":{"normal":{"key":"normal","label":"Normal","value":{"backgroundColor":{"label":"Background Color","key":"backgroundcolor","value":""},"color":{"label":"Color","key":"color","value":""},"width":{"label":"Button Width","key":"width","value":""},"padding":{"label":"Form Padding","key":"padding","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"},"margin":{"label":"","key":"margin","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"},"typography":{"key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"boxshadow":{"key":"boxshadow","label":"Box Shadow","value":{"horizontal":{"value":"0","type":"px"},"vertical":{"value":"0","type":"px"},"blur":{"value":"0","type":"px"},"spread":{"value":"0","type":"px"},"color":"","position":""}},"border":{"label":"","key":"border","status_label":"Use custom Border style","value":{"border_radius":{"top":"4","left":"4","right":"4","bottom":"4","linked":"yes"},"border_width":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"border_type":"solid","border_color":"","status":"yes"}}}},"hover":{"key":"hover","label":"Hover","value":{"backgroundColor":{"label":"Background Color","key":"backgroundcolor","value":""},"color":{"label":"Color","key":"color","value":""},"typography":{"key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"boxshadow":{"key":"boxshadow","label":"Box Shadow","value":{"horizontal":{"value":"0","type":"px"},"vertical":{"value":"0","type":"px"},"blur":{"value":"0","type":"px"},"spread":{"value":"0","type":"px"},"color":"","position":""}},"border":{"label":"","key":"border","status_label":"Use custom Border style","value":{"border_radius":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"border_width":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"border_type":"solid","border_color":"","status":""}}}}},"status":"yes"}},"radio_checkbox_style":{"radio_checkbox":{"label":"","element":"ff_radio_checkbox","status_label":"Enable Smart UI","value":{"color":{"label":"Border Color","value":""},"active_color":{"label":"Checked Background Color","value":""},"border":{"label":"","key":"border","status_label":"Use custom Border style","value":{"border_radius":{"top":"4","left":"4","right":"4","bottom":"4","linked":"yes"},"border_width":{"top":"1","left":"1","right":"1","bottom":"1","linked":"yes"},"border_type":"solid","border_color":"rgba(33, 37, 41, 1)","status":"yes"}}},"status":"yes"},"color":{"label":"Items Color","element":"ff_color","value":""}},"sectionbreak_styles":{"all_tabs":{"label":"","element":"ff_tabs","tabs":{"LabelStyling":{"key":"LabelStyling","label":"Label Styling","value":{"color":{"label":"Color","key":"color","value":""},"typography":{"label":"Typography","key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"padding":{"label":"Section Break Padding","key":"padding","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"},"margin":{"label":"Section Break Margin","key":"margin","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"}}},"DescriptionStyling":{"key":"DescriptionStyling","label":"Description Styling","value":{"color":{"label":"Color","key":"color","value":""},"typography":{"label":"Typography","key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}},"padding":{"label":"Section Break Padding","key":"padding","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"},"margin":{"label":"Section Break Margin","key":"margin","value":{"top":"","left":"","right":"","bottom":"","linked":"yes"},"type":"px"}}}}}},"gridtable_style":{"all_tabs":{"label":"","element":"ff_tabs","tabs":{"TableHead":{"key":"tableHead","label":"Table Head","value":{"color":{"label":"Color","key":"color","value":""},"backgroundColor":{"label":"Background Color","key":"backgroundcolor","value":""},"typography":{"label":"Typography","key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}}}},"TableBody":{"key":"tableBody","label":"Table Body","value":{"color":{"label":"Color","key":"color","value":""},"backgroundColor":{"label":"Background Color","key":"backgroundcolor","value":""},"typography":{"label":"Typography","key":"typography","value":{"fontSize":{"value":"","type":"px"},"fontWeight":"","transform":"","fontStyle":"","textDecoration":"","lineHeight":{"value":"","type":"px"},"letterSpacing":{"value":"","type":"px"}}}}}}}}}', ], 'ffs_inherit_theme' => [ 'label' => __('Inherit Theme Style', 'fluentform'), 'style' => '{}', ], ]; $presets = apply_filters_deprecated( 'fluentform_style_preses', [ $presets, ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/style_presets', 'Use fluentform/style_presets instead of fluentform_style_preses.' ); $presets = apply_filters('fluentform/style_presets', $presets); $presets['ffs_custom'] = [ 'label' => __('Custom (Advanced Customization)', 'fluentformpro'), 'src' => '', ]; return $presets; } public function maybeGenerateStyle($formId) { $styles = Helper::getFormMeta($formId, '_ff_form_styles'); if ($styles) { $theme = Helper::getFormMeta($formId, '_ff_selected_style'); $this->generateStyle($formId, $styles, $theme); } } private function getOtherFormStyles($callerFormId) { $customStyles = wpFluent()->table('fluentform_form_meta') ->select([ 'fluentform_form_meta.value', 'fluentform_form_meta.form_id', 'fluentform_forms.title', ]) ->where('fluentform_form_meta.form_id', '!=', $callerFormId) ->where('fluentform_form_meta.meta_key', '_ff_form_styles') ->join('fluentform_forms', 'fluentform_forms.id', '=', 'fluentform_form_meta.form_id') ->get(); $validFormSelectors = wpFluent()->table('fluentform_form_meta') ->select([ 'value', 'form_id', 'value', ]) ->where('fluentform_form_meta.form_id', '!=', $callerFormId) ->where('fluentform_form_meta.meta_key', '_ff_selected_style') ->where('fluentform_form_meta.meta_key', '!=', '') ->get(); $styles = []; foreach ($validFormSelectors as $formSelector) { if (!$formSelector->value || '""' == $formSelector->value) { continue; } $selectorType = str_replace('"', '', $formSelector->value); $styles[$formSelector->form_id] = [ 'type' => $selectorType, 'is_custom' => 'ffs_custom' == $selectorType, 'form_id' => $formSelector->form_id, ]; } $formattedStyles = [ 'custom' => [], 'predefined' => [], ]; foreach ($customStyles as $style) { if (!isset($styles[$style->form_id])) { continue; } $existingStyle = $styles[$style->form_id]; $existingStyle['form_title'] = $style->title; $existingStyle['styles'] = json_decode($style->value, true); if ($existingStyle['is_custom']) { $formattedStyles['custom'][$style->form_id] = $existingStyle; } else { $formattedStyles['predefined'][$style->form_id] = $existingStyle; } } return $formattedStyles; } public function export() { try { $formId = intval($this->request->get('form_id')); $name = sanitize_title($this->request->get('style_name')); $styles = Helper::getFormMeta($formId, '_ff_form_styles'); if (!$styles || !$formId) { throw new \Exception('Required Parameter missing!'); } $fileName = 'fluentform_style_' . $name . '.json'; header('Content-disposition: attachment; filename=' . $fileName); header('Content-type: application/json'); echo json_encode($styles); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $forms is escaped before being passed in. exit(); } catch (Exception $exception) { wp_send_json([ 'message' => $exception->getMessage(), ], 424); } } public function import() { $styles = $this->request->file('file'); if ($styles instanceof File) { $formId = intval($this->request->get('form_id')); $styles = \json_decode($styles->getContents(), true); $theme = Helper::getFormMeta($formId, '_ff_selected_style'); $this->generateStyle($formId, $styles, $theme); wp_send_json([ 'success' => true, ]); } } private function generateStyle($formId, $styles, $theme = '_ff_form_styler_css') { $stylerGenerator = new FormStylerGenerator(); $css = $stylerGenerator->generateFormCss( '.fluentform_wrapper_' . $formId . '.' . $theme . '_wrap', $styles ); $css = trim($css); Helper::setFormMeta($formId, $theme, $css); Helper::setFormMeta($formId, '_ff_form_styles', $styles); do_action('fluentform/after_style_generated', $formId); return $css; } public function buildStyleFromTheme($css, $formId, $theme = '') { $presets = $this->getPresets(); if (isset($presets[$theme])) { $selectedPreset = $presets[$theme]; $styles = ArrayHelper::get($selectedPreset, 'style'); if (is_string($styles) && Helper::isJson($styles)) { $styles = json_decode($styles, true); } if ('ffs_custom' == $theme) { $styles = Helper::getFormMeta($formId, '_ff_form_styles', []); } $css = $this->generateStyle($formId, $styles, $theme); } return $css; } public function getBlockPresets() { $presets = $this->getPresets(); $formattedPresets = []; foreach ($presets as $preset => $presetData) { $label = $presetData['label']; if ($preset == 'ffs_default') { $label = __('Default (Form Styler)', 'fluentformpro'); $preset = ''; } $formattedPresets[] = [ 'label' => $label, 'value' => $preset, ]; } return $formattedPresets; } } PK!_<src/classes/FormModal.phpnu[ '; } }PK!䳯V  #src/classes/AddressAutoComplete.phpnu[optionKey, array($this, 'getSettings'), 10); add_filter('fluentform/global_integration_fields_' . $this->optionKey, array($this, 'getSettingsFields'), 10, 1); add_action('fluentform/save_global_integration_settings_' . $this->optionKey, array($this, 'saveSettings'), 10, 1); add_filter('fluentform/editor_vars', function ($vars) { if ($this->isEnabled()) { $vars['has_address_gmap_api'] = true; } return $vars; }); add_action('fluentform/address_map_autocomplete', array($this, 'addGmapJs'), 10, 2); add_filter('fluentform/conversational_form_address_gmap_api_key', array($this, 'convJsGmapApiKey'), 10, 1); add_filter('fluentform/editor_init_element_address', function ($element) { if (!isset($element['settings']['enable_g_autocomplete'])) { $element['settings']['enable_g_autocomplete'] = ''; } if (!isset($element['settings']['enable_g_map'])) { $element['settings']['enable_g_map'] = ''; } if (!isset($element['settings']['enable_auto_locate'])) { $element['settings']['enable_auto_locate'] = 'no'; } return $element; }); add_filter('fluentform/rendering_field_data_address' , function ($data, $form){ if ($this->ifShowLocateButton($data)){ $inputName = ArrayHelper::get(current($data['fields']),'attributes.name'); $locateIcon = $this->getLocateIcon(); ArrayHelper::set($data, 'fields.'.$inputName.'.settings.suffix_label',$locateIcon); } return $data; },10,2); } public function addGlobalMenu($setting) { $setting['google_maps_autocomplete'] = [ 'hash' => $this->integrationKey, 'component' => 'general-integration-settings', 'settings_key' => $this->optionKey, 'title' => 'Google Maps Integration' ]; return $setting; } public function getSettings($settings) { $globalSettings = get_option($this->optionKey); if (!$globalSettings) { $globalSettings = []; } $defaults = [ 'api_key' => '', 'status' => '' ]; return wp_parse_args($globalSettings, $defaults); } public function getSettingsFields($fields) { return [ 'logo' => FLUENTFORMPRO_DIR_URL . 'public/images/google_map.png', 'menu_title' => __('Google Map Integration Settings', 'fluentformpro'), 'menu_description' => __('For address autocomplete feature you may setup google map API details', 'fluentformpro'), 'valid_message' => __('Google Map API is set.', 'fluentformpro'), 'invalid_message' => __('Google Map API key is not valid', 'fluentformpro'), 'save_button_text' => __('Save Settings', 'fluentformpro'), 'fields' => [ 'api_key' => [ 'type' => 'password', 'placeholder' => '', 'label_tips' => __("Enter your Google Map API Key", 'fluentformpro'), 'label' => __('Google Map API Key', 'fluentformpro'), ], ], 'hide_on_valid' => true, 'discard_settings' => [ 'section_description' => 'Google Map API is set. You can now enable google map autocomplete feature for Address Field', 'button_text' => 'Disconnect Google Map API', 'data' => [ 'api_key' => '' ] ] ]; } public function saveSettings($settings) { $key = $settings['api_key']; if (!$key) { $defaults = [ 'api_key' => '', 'status' => '' ]; update_option($this->optionKey, $defaults, 'no'); wp_send_json_success([ 'message' => __('Your settings has been updated and discarded', 'fluentformpro'), 'status' => false ], 200); } update_option($this->optionKey, [ 'api_key' => sanitize_text_field($settings['api_key']), 'status' => true ], 'no'); wp_send_json_success([ 'message' => __('Google Map Api key has been saved', 'fluentformpro'), 'status' => true ], 200); } public function isEnabled() { $settings = $this->getSettings([]); return !empty($settings['api_key']) && $settings['status']; } public function addGmapJs($data, $form) { $settings = $this->getSettings([]); if (empty($settings['api_key'])) { return; } $apiKey = $settings['api_key']; wp_enqueue_script('ff_gmap', FLUENTFORMPRO_DIR_URL.'public/js/ff_gmap.js', ['jquery'], FLUENTFORM_VERSION, true); wp_enqueue_script('google-maps', 'https://maps.googleapis.com/maps/api/js?key=' . $apiKey . '&libraries=places&callback=fluentform_gmap_callback', [], FLUENTFORM_VERSION, true); } public function convJsGmapApiKey($apiKey) { $settings = $this->getSettings([]); if (!empty($settings['api_key'])) { $apiKey = $settings['api_key']; } return $apiKey; } /** * @param $data * @return bool */ private function ifShowLocateButton($data) { if ($this->isEnabled() && ArrayHelper::get($data, 'settings.enable_g_autocomplete') == 'yes' && (ArrayHelper::get($data, 'settings.enable_auto_locate') == 'on_load' || ArrayHelper::get($data, 'settings.enable_auto_locate') == 'on_click') ) { return true; } return false; } /** * @return string */ private function getLocateIcon() { return ''; } } PK!)zoosrc/classes/Calculation.phpnu[app = $app; $this->registerAjaxHandlers(); $this->app->addFilter('fluentform/form_admin_menu', [$this, 'addAdminMenu'], 10, 2); $app->addAction('fluentform/form_application_view_msformentries', [$this, 'renderEntries']); add_filter('fluentform/form_inner_route_permission_set', array($this, 'setRoutePermission')); } protected function registerAjaxHandlers() { $this->app->addAdminAjaxAction('fluentform-step-form-entry-count', function () { Acl::verify('fluentform_entries_viewer'); $this->getCountOfEntries(); }); $this->app->addAdminAjaxAction('fluentform-step-form-entries', function () { Acl::verify('fluentform_entries_viewer'); $this->getEntries(); }); $this->app->addAdminAjaxAction('fluentform-step-form-delete-entry', function () { Acl::verify('fluentform_forms_manager'); $this->deleteEntry(); }); $this->app->addAdminAjaxAction('fluentform-do_step_form_entry_bulk_actions', function () { Acl::verify('fluentform_entries_viewer'); $this->handleBulkAction(); }); $this->app->addAdminAjaxAction('fluentform-step-form-entries-export', function () { Acl::verify('fluentform_entries_viewer'); (new Export($this->app, 'fluentform_draft_submissions'))->index(); }); $this->app->addAdminAjaxAction('fluentform-step-form-get-entry', function () { Acl::verify('fluentform_entries_viewer'); $this->getEntry(); }); } public function addAdminMenu($formAdminMenus, $form_id) { $hasPartialEntry = Helper::getFormMeta($form_id, 'step_data_persistency_status') == 'yes' || Helper::getFormMeta($form_id, 'form_save_state_status') == 'yes' || Helper::getFormMeta($form_id, 'conv_form_per_step_save'); if ($hasPartialEntry) { $formAdminMenus['msformentries'] = [ 'hash' => '/', 'slug' => 'msformentries', 'title' => __('Partial Entries', 'fluentformpro'), 'url' => admin_url( 'admin.php?page=fluent_forms&form_id=' . $form_id . '&route=msformentries' ) ]; } return $formAdminMenus; } public function renderEntries($form_id) { $this->enqueueScript(); $form = wpFluent()->table($this->formTable)->find($form_id); $entryVars = [ 'form_id' => $form->id, 'current_form_title' => $form->title, 'has_pro' => defined('FLUENTFORMPRO'), 'all_forms_url' => admin_url('admin.php?page=fluent_forms'), 'printStyles' => [fluentformMix('css/settings_global.css')], 'entries_url_base' => admin_url('admin.php?page=fluent_forms&route=msformentries&form_id='), 'available_countries' => getFluentFormCountryList(), 'no_found_text' => __('Sorry! No entries found. All your entries will be shown here once you start getting form submissions', 'fluentformpro') ]; $entryVars = apply_filters_deprecated( 'fluentform_step_form_entry_vars', [ $entryVars, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/step_form_entry_vars', 'Use fluentform/step_form_entry_vars instead of fluentform_step_form_entry_vars.' ); $fluentformStepFormEntryVars = apply_filters('fluentform/step_form_entry_vars', $entryVars, $form); wp_localize_script( 'fluentform_step_form_entries', 'fluentform_step_form_entry_vars', $fluentformStepFormEntryVars ); ob_start(); require(FLUENTFORMPRO_DIR_PATH . 'src/views/step_form_entries.php'); echo ob_get_clean(); } protected function enqueueScript() { wp_enqueue_script( 'fluentform_step_form_entries', FLUENTFORMPRO_DIR_URL . 'public/js/step-form-entries.js', ['jquery'], FLUENTFORM_VERSION, true ); } public function getCountOfEntries() { $formId = intval($this->app->request->get('form_id')); $count = wpFluent()->table($this->entryTable) ->select(wpFluent()->table($this->entryTable)->raw('COUNT(*) as count')) ->where('form_id', $formId) ->count(); wp_send_json_success([ 'count' => $count ], 200); } public function getEntries() { if (!defined('FLUENTFORM_RENDERING_ENTRIES')) { define('FLUENTFORM_RENDERING_ENTRIES', true); } $entries = $this->getStepFormEntries( intval($this->app->request->get('form_id')), intval($this->app->request->get('current_page', 1)), intval($this->app->request->get('per_page', 10)), Helper::sanitizeOrderValue($this->app->request->get('sort_by', 'DESC')), sanitize_text_field($this->app->request->get('entry_type', 'all')), sanitize_text_field($this->app->request->get('search')) ); $entries['formLabels'] = apply_filters_deprecated( 'fluentform_all_entry_labels', [ $entries['formLabels'], $this->app->request->get('form_id') ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/all_entry_labels', 'Use fluentform/all_entry_labels instead of fluentform_all_entry_labels.' ); $labels = apply_filters( 'fluentform/all_entry_labels', $entries['formLabels'], $this->app->request->get('form_id') ); $form = wpFluent()->table($this->formTable)->find($this->app->request->get('form_id')); $entries['submissions'] = apply_filters_deprecated( 'fluentform_all_entries', [ $entries['submissions'] ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/all_entries', 'Use fluentform/all_entries instead of fluentform_all_entries.' ); wp_send_json_success([ 'submissions' => apply_filters('fluentform/all_entries', $entries['submissions']), 'labels' => $labels ], 200); } public function getStepFormEntries( $formId, $currentPage, $perPage, $sortBy, $entryType, $search, $wheres = [] ) { $form = wpFluent()->table($this->formTable)->find($formId); $formMeta = $this->getFormInputsAndLabels($form); $formLabels = $formMeta['labels']; $formLabels = apply_filters_deprecated( 'fluentfoform_entry_lists_labels', [ $formLabels, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/entry_lists_labels', 'Use fluentform/entry_lists_labels instead of fluentfoform_entry_lists_labels.' ); $formLabels = apply_filters_deprecated( 'fluentform_entry_lists_labels', [ $formLabels, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/entry_lists_labels', 'Use fluentform/entry_lists_labels instead of fluentform_entry_lists_labels.' ); $formLabels = apply_filters('fluentform/entry_lists_labels', $formLabels, $form); $submissions = $this->getResponses($formId, $perPage, $sortBy, $currentPage, $search, $wheres); $submissions['data'] = FormDataParser::parseFormEntries($submissions['data'], $form); return compact('submissions', 'formLabels'); } public function getResponses($formId, $perPage, $sortBy, $currentPage, $search = '', $wheres = []) { $query = wpFluent()->table($this->entryTable)->where('form_id', $formId)->orderBy('id', $sortBy); if ($perPage > 0) { $query = $query->limit($perPage); } if ($currentPage > 0) { $query = $query->offset(($currentPage - 1) * $perPage); } if ($search) { $searchString = $search; $query->where(function ($q) use ($searchString) { $q->where('id', 'LIKE', "%{$searchString}%") ->orWhere('response', 'LIKE', "%{$searchString}%"); }); } if ($wheres) { foreach ($wheres as $where) { if (is_array($where) && count($where) > 1) { if (count($where) > 2) { $column = $where[0]; $operator = $where[1]; $value = $where[2]; } else { $column = $where[0]; $operator = '='; $value = $where[1]; } $query->where($column, $operator, $value); } } } $total = $query->count(); $responses = $query->get(); $responses = apply_filters_deprecated( 'fluentform/get_raw_responses', [ $responses, $formId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/get_raw_responses', 'Use fluentform/get_raw_responses instead of fluentform_get_raw_responses.' ); $responses = apply_filters('fluentform/get_raw_responses', $responses, $formId); return [ 'data' => $responses, 'paginate' => [ 'total' => $total, 'per_page' => $perPage, 'current_page' => $currentPage, 'last_page' => ceil($total / $perPage) ] ]; } public function getEntry() { if (!defined('FLUENTFORM_RENDERING_ENTRY')) { define('FLUENTFORM_RENDERING_ENTRY', true); } $entryData = $this->getstepFormEntry(); $entryData['widgets'] = apply_filters( 'fluentform/submissions_widgets', [], $entryData, $entryData['submission'] ); wp_send_json_success($entryData, 200); } public function getstepFormEntry() { $this->formId = intval($this->app->request->get('form_id')); $entryId = intval($this->app->request->get('entry_id')); $this->sort_by = \FluentForm\App\Helpers\Helper::sanitizeOrderValue($this->app->request->get('sort_by', 'ASC')); $this->search = sanitize_text_field($this->app->request->get('search')); $submission = $this->getResponse($entryId); if (!$submission) { wp_send_json_error([ 'message' => __('No Entry found.', 'fluentformpro') ], 422); } $form = wpFluent()->table($this->formTable)->find($this->formId); $formMeta = $this->getFormInputsAndLabels($form); $submission = FormDataParser::parseFormEntry($submission, $form, $formMeta['inputs'], true); if ($fields = FormFieldsParser::getInputsByElementTypes($form, ['input_file', 'input_image'])) { $response = \json_decode($submission->response, true); foreach ($fields as $name => $field) { if ($files = Arr::get($response, $name)) { foreach ($files as $index => $file) { $response[$name][$index] = Helper::maybeDecryptUrl($file); } } } $submission->response = \json_encode($response); } if ($submission->user_id) { $user = get_user_by('ID', $submission->user_id); $user_data = [ 'name' => $user->display_name, 'email' => $user->user_email, 'ID' => $user->ID, 'permalink' => get_edit_user_link($user->ID) ]; $submission->user = $user_data; } $submission = apply_filters_deprecated( 'fluentform_single_response_data', [ $submission, $this->formId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/single_response_data', 'Use fluentform/single_response_data instead of fluentform_single_response_data.' ); $submission = apply_filters('fluentform/single_response_data', $submission, $this->formId); $formMeta['inputs'] = apply_filters_deprecated( 'fluentform_single_response_input_fields', [ $formMeta['inputs'], $this->formId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/single_response_input_fields', 'Use fluentform/single_response_input_fields instead of fluentform_single_response_input_fields.' ); $fields = apply_filters( 'fluentform/single_response_input_fields', $formMeta['inputs'], $this->formId ); $formMeta['labels'] = apply_filters_deprecated( 'fluentform_single_response_input_labels', [ $formMeta['labels'], $this->formId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/single_response_input_labels', 'Use fluentform/single_response_input_labels instead of fluentform_single_response_input_labels.' ); $labels = apply_filters( 'fluentform/single_response_input_labels', $formMeta['labels'], $this->formId ); $order_data = false; $nextSubmissionId = $this->getNextResponse($entryId); $previousSubmissionId = $this->getPrevResponse($entryId); return [ 'submission' => $submission, 'next' => $nextSubmissionId, 'prev' => $previousSubmissionId, 'labels' => $labels, 'fields' => $fields, 'order_data' => $order_data ]; } protected function getResponse($entryId) { return wpFluent()->table($this->entryTable)->find($entryId); } protected function getFormInputsAndLabels($form, $with = ['admin_label', 'raw']) { $formInputs = FormFieldsParser::getEntryInputs($form, $with); $inputLabels = FormFieldsParser::getAdminLabels($form, $formInputs); return [ 'inputs' => $formInputs, 'labels' => $inputLabels ]; } protected function getNextResponse($entryId) { $query = $this->getNextPrevEntryQuery(); $operator = $this->sort_by == 'ASC' ? '>' : '<'; return $query->select('id') ->where('id', $operator, $entryId) ->orderBy('id', $this->sort_by) ->first(); } protected function getPrevResponse($entryId) { $query = $this->getNextPrevEntryQuery(); $operator = $this->sort_by == 'ASC' ? '<' : '>'; $orderBy = $this->sort_by == 'ASC' ? 'DESC' : 'ASC'; return $query->select('id') ->where('id', $operator, $entryId) ->orderBy('id', $orderBy) ->first(); } protected function getNextPrevEntryQuery() { $query = wpFluent()->table($this->entryTable)->limit(1); if ($this->search) { $query->where('response', 'LIKE', "%{$this->search}%"); } return $query->where('form_id', $this->formId); } public function deleteEntry() { $formId = intval($this->app->request->get('form_id')); $entryId = intval($this->app->request->get('entry_id')); $newStatus = sanitize_text_field($this->app->request->get('status')); $this->deleteEntryById($entryId, $formId); wp_send_json_success([ 'message' => __('Item Successfully deleted', 'fluentformpro'), 'status' => $newStatus ], 200); } public function deleteEntryById($entryId, $formId = false) { do_action_deprecated( 'fluentform_before_partial_entry_deleted', [ $entryId, $formId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/before_partial_entry_deleted', 'Use fluentform/before_partial_entry_deleted instead of fluentform_before_partial_entry_deleted.' ); do_action('fluentform/before_partial_entry_deleted', $entryId, $formId); ob_start(); wpFluent()->table($this->entryTable)->where('id', $entryId)->delete(); $errors = ob_get_clean(); do_action_deprecated( 'fluentform_after_partial_entry_deleted', [ $entryId, $formId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/after_partial_entry_deleted', 'Use fluentform/after_partial_entry_deleted instead of fluentform_after_partial_entry_deleted.' ); do_action('fluentform/after_partial_entry_deleted', $entryId, $formId); return true; } public function handleBulkAction() { $request = $this->app->request; $formId = intval($request->get('form_id')); $entries = fluentFormSanitizer($request->get('entries', [])); $actionType = sanitize_text_field($request->get('action_type')); if (!$formId || !count($entries)) { wp_send_json_error([ 'message' => __('Please select entries first', 'fluentformpro') ], 400); } if ($actionType == 'delete_permanently') { foreach ($entries as $entryId) { if(!$this->deleteEntryById($entryId, $formId)){ continue; }; } wp_send_json_success([ 'message' => __('Selected entries successfully deleted', 'fluentformpro') ], 200); } } protected function getSubmissionAttachments($submissionId, $form) { $fields = FormFieldsParser::getAttachmentInputFields($form, ['element', 'attributes']); $deletableFiles = []; if ($fields) { $submission = wpFluent()->table($this->entryTable) ->where('id', $submissionId) ->first(); $data = json_decode($submission->response, true); foreach ($fields as $field) { if (!empty($data[$field['attributes']['name']])) { $files = $data[$field['attributes']['name']]; if (is_array($files)) { $deletableFiles = array_merge($deletableFiles, $files); } else { $deletableFiles = $files; } } } } return $deletableFiles; } public function setRoutePermission($permissions) { $permissions['conversational_design'] = 'fluentform_forms_manager'; return $permissions; } } PK!^&src/classes/AdvancedFormValidation.phpnu[getAdvancedCondition($form->id); if(!ArrayHelper::get($conditionals, 'status')) { return $errors; } $isMatched = $this->checkCondition([ 'conditionals' => $conditionals ], $data); $validationType = ArrayHelper::get($conditionals, 'validation_type', 'fail_on_condition_met'); $ifFailedOnTrue = $validationType == 'fail_on_condition_met'; if( ($ifFailedOnTrue && $isMatched) || (!$ifFailedOnTrue && !$isMatched)) { $errorMessage = $conditionals['error_message']; if(!$errorMessage) { $errorMessage = __('Form validation has been failed', 'fluentformpro'); } $errors['advanced_validation_error'] = $errorMessage; } return $errors; } private function getAdvancedCondition($formId) { $settingsMeta = wpFluent()->table('fluentform_form_meta') ->where('form_id', $formId) ->where('meta_key', 'advancedValidationSettings') ->first(); if(!$settingsMeta || !$settingsMeta->value) { return false; } return \json_decode($settingsMeta->value, true); } private function checkCondition($settings, $formData) { $conditionSettings = ArrayHelper::get($settings, 'conditionals'); if ( !$conditionSettings || !count(ArrayHelper::get($conditionSettings, 'conditions')) ) { return true; } return ConditionAssesor::evaluate($settings, $formData); } }PK!:`or>r>)src/classes/ResendNotificationHandler.phpnu[verify($formId); $entryIds = []; if (ArrayHelper::get($_REQUEST, 'entry_ids')) { $entryIds = array_filter(ArrayHelper::get($_REQUEST, 'entry_ids', []), 'intval'); } $sendToType = sanitize_text_field(ArrayHelper::get($_REQUEST, 'send_to_type')); $customRecipient = sanitize_text_field(ArrayHelper::get($_REQUEST, 'send_to_custom_email')); $feed = wpFluent()->table('fluentform_form_meta') ->where('id', $notificationId) ->where('meta_key', 'notifications') ->where('form_id', $formId) ->first(); if (!$feed) { wp_send_json_error([ 'message' => __('Sorry, No notification found!') ], 423); } $feed->value = \json_decode($feed->value, true); $form = wpFluent()->table('fluentform_forms') ->where('id', $formId) ->first(); if ($entryId) { $this->resendEntryEmail($entryId, $feed, $sendToType, $customRecipient, $form); } else if ($entryIds) { foreach ($entryIds as $entry_id) { $this->resendEntryEmail($entry_id, $feed, $sendToType, $customRecipient, $form); } } wp_send_json_success([ 'message' => __('Notification successfully resent', 'fluentformpro') ], 200); } public function getFeeds() { $formId = intval(ArrayHelper::get($_REQUEST, 'form_id')); $entryId = intval(ArrayHelper::get($_REQUEST, 'entry_id')); $this->verify($formId); wp_send_json_success([ 'feeds' => $this->getFormattedFeeds($formId, $entryId) ], 200); } public function replayFeed() { $requestLogIds = ArrayHelper::get($_REQUEST, 'logIds'); $this->handleReplayFeed($requestLogIds); } private function handleReplayFeed($requestLogIds) { $isMultipleActions = rest_sanitize_boolean(ArrayHelper::get($_REQUEST, 'multiple_actions', false)); add_action( 'fluentform/integration_action_result', function($feed, $status, $message) use ($requestLogIds, $isMultipleActions) { foreach ($requestLogIds as $logIds) { $feedId = intval(ArrayHelper::get($feed, 'id')); $requestFeedId = intval(ArrayHelper::get($logIds, 'feed_id')); if ($feedId != $requestFeedId) { continue; } $actionId = intval(ArrayHelper::get($logIds, 'action_id')); $feed = FormMeta::where('id', $requestFeedId)->first(); if ($feed && $feed->value) { $feedValue = json_decode($feed->value, true); $isDisabled = ArrayHelper::get($feedValue, 'enabled') == 0; if ($isDisabled && !$isMultipleActions) { $message = __('Feed is disabled', 'fluentformpro'); wp_send_json_error(['message' => $message], 423); return; } } // Handle status if ($status == 'failed') { $message = empty($message) ? __('Something is wrong when processing the feed', 'fluentformpro') : $message; } elseif ($status == 'success') { $message = empty($message) ? __('The selected feed has been successfully fired', 'fluentformpro') : $message; } // Update scheduled actions wpFluent()->table('ff_scheduled_actions') ->where('id', $actionId) ->update([ 'status' => $status, 'note' => $message, 'updated_at' => current_time('mysql') ]); // Send JSON response if ($isMultipleActions) { wp_send_json_success([ 'message' => __('Multiple actions have been fired', 'fluentformpro') ], 200); } if ($status == 'failed') { wp_send_json_error(['message' => $message], 423); } else { wp_send_json_success(['message' => $message], 200); } } }, 1, 3 ); foreach ($requestLogIds as $logIds) { if (ArrayHelper::get($logIds, 'integration_enabled') == 'false') { wp_send_json_error([ 'message' => __('Please enable the integration', 'fluentformpro') ], 423); } $entryId = intval(ArrayHelper::get($logIds, 'entry_id')); $formId = intval(ArrayHelper::get($logIds, 'form_id')); $feedId = intval(ArrayHelper::get($logIds, 'feed_id')); $verifyCondition = sanitize_text_field(ArrayHelper::get($_REQUEST, 'verify_condition')) == 'yes'; $this->verify($formId); $form = wpFluent()->table('fluentform_forms') ->where('id', $formId) ->first(); $feed = wpFluent()->table('fluentform_form_meta') ->where('form_id', $formId) ->where('id', $feedId) ->first(); if (!$feed) { $message = __('Invalid Feed ID', 'fluentformpro'); if (!$isMultipleActions) { wp_send_json_error([ 'message' => $message ], 423); } } $entry = $this->getEntry($entryId, $form); $formData = json_decode($entry->response, true); $parsedValue = json_decode($feed->value, true); $originalParsedValue = $parsedValue; $processedValues = $parsedValue; unset($processedValues['conditionals']); $processedValues = ShortCodeParser::parse($processedValues, $entryId, $formData); if ($verifyCondition) { $isMatched = (new GlobalNotificationManager(wpFluentForm()))->checkCondition($originalParsedValue, $formData, $entryId); if (!$isMatched) { $message = __('Conditions did not satisfy for this feed', 'fluentformpro'); if (!$isMultipleActions) { wp_send_json_error([ 'message' => $message ], 423); } } } $item = [ 'id' => $feed->id, 'meta_key' => $feed->meta_key, 'settings' => $parsedValue, 'processedValues' => $processedValues ]; $action = 'fluentform/integration_notify_' . $item['meta_key']; add_filter('fluentform/integration_notify_throw_error', '__return_true'); if ($item['meta_key'] == 'postFeeds') { (new PostFormHandler())->createPostFromFeed($processedValues, $entryId, $formData, $form); } else { do_action($action, $item, $formData, $entry, $form); } } wp_send_json_success([ 'message' => __('The selected feeds has been successfully fired.', 'fluentformpro') ], 200); } private function resendEntryEmail($entryId, $feed, $sendToType, $customRecipient, $form) { $parsedValue = $feed->value; $entry = wpFluent()->table('fluentform_submissions') ->where('id', $entryId) ->first(); $formData = \json_decode($entry->response, true); ShortCodeParser::resetData(); $processedValues = ShortCodeParser::parse($parsedValue, $entry, $formData, $form, false, $feed->meta_key); if ($sendToType == 'custom') { $processedValues['bcc'] = ''; $processedValues['sendTo']['email'] = $customRecipient; $processedValues['sendTo']['type'] = 'custom'; } $attachments = []; if (!empty($processedValues['attachments']) && is_array($processedValues['attachments'])) { foreach ($processedValues['attachments'] as $name) { $fileUrls = ArrayHelper::get($formData, $name); if ($fileUrls && is_array($fileUrls)) { foreach ($fileUrls as $url) { $filePath = str_replace( site_url(''), wp_normalize_path(untrailingslashit(ABSPATH)), $url ); if (file_exists($filePath)) { $attachments[] = $filePath; } } } } } $attachments = apply_filters_deprecated( 'fluentform_email_attachments', [ $attachments, $processedValues, $formData, $entry, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/email_attachments', 'Use fluentform/email_attachments instead of fluentform_email_attachments.' ); // let others to apply attachments $attachments = apply_filters('fluentform/email_attachments', $attachments, $processedValues, $formData, $entry, $form); $processedValues['attachments'] = $attachments; $enabledFeed = [ 'id' => $feed->id, 'meta_key' => $feed->meta_key, 'settings' => $parsedValue, 'processedValues' => $processedValues ]; add_action('wp_mail_failed', function ($error) { $reason = $error->get_error_message(); wp_send_json_error([ 'message' => __("Email Notification failed to sent. Reason: ", 'fluentformpro') . $reason ], 423); }, 10, 1); $notifier = wpFluentForm()->make( 'FluentForm\App\Services\FormBuilder\Notifications\EmailNotification' ); $notifier->notify($enabledFeed['processedValues'], $formData, $form, $entry->id); } private function verify($formId = false) { if (!$formId) { $formId = intval(ArrayHelper::get($_REQUEST,'form_id')); } \FluentForm\App\Modules\Acl\Acl::verify('fluentform_entries_viewer', $formId); } private function getFormattedFeeds($formId, $entryId) { $activeFeeds = apply_filters_deprecated( 'fluentform_global_notification_active_types', [ [], $formId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/global_notification_active_types', 'Use fluentform/global_notification_active_types instead of fluentform_global_notification_active_types.' ); // Let's find the feeds that are available for this form $feedKeys = apply_filters('fluentform/global_notification_active_types', $activeFeeds, $formId); if (!$feedKeys) { return []; } unset($feedKeys['user_registration_feeds']); unset($feedKeys['notifications']); $feedMetaKeys = array_keys($feedKeys); $feedMetaKeys[] = 'postFeeds'; $feeds = wpFluent()->table('fluentform_form_meta') ->where('form_id', $formId) ->whereIn('meta_key', $feedMetaKeys) ->orderBy('id', 'ASC') ->get(); if (!$feeds) { return []; } $formattedFeeds = []; foreach ($feeds as $feed) { $parsedValue = json_decode($feed->value, true); if (!$parsedValue) { continue; } $conditionSettings = ArrayHelper::get($parsedValue, 'conditionals'); if ( !$conditionSettings || !ArrayHelper::isTrue($conditionSettings, 'status') || !count(ArrayHelper::get($conditionSettings, 'conditions')) ) { $hasCondition = false; } else { $hasCondition = true; } $feedName = ArrayHelper::get($parsedValue, 'name'); if (!$feedName) { $feedName = ArrayHelper::get($parsedValue, 'feed_name'); } $status = ArrayHelper::isTrue($parsedValue, 'enabled'); if (!isset($parsedValue['enabled'])) { $status = ArrayHelper::isTrue($parsedValue, 'feed_status'); } $feedData = [ 'id' => $feed->id, 'has_condition' => $hasCondition, 'name' => $feedName, 'enabled' => $status, 'provider' => $feed->meta_key, 'feed' => $parsedValue ]; $scheduledActions = wpFluent()->table('ff_scheduled_actions') ->where('origin_id', $entryId) ->where('feed_id', $feed->id) ->get(); if ($scheduledActions) { foreach ($scheduledActions as $action) { $feedData['action_id'] = $action->id; } } $feedData = apply_filters_deprecated( 'fluentform_global_notification_feed_' . $feed->meta_key, [ $feedData, $formId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/global_notification_feed_' . $feed->meta_key, 'Use fluentform/global_notification_feed_' . $feed->meta_key . ' instead of fluentform_global_notification_feed_' . $feed->meta_key ); $formattedFeeds[] = apply_filters('fluentform/global_notification_feed_' . $feed->meta_key, $feedData, $formId); } return $formattedFeeds; } private function getEntry($id, $form) { $submission = wpFluent()->table('fluentform_submissions')->find($id); $formInputs = FormFieldsParser::getEntryInputs($form, ['admin_label', 'raw']); return FormDataParser::parseFormEntry($submission, $form, $formInputs); } } PK!~src/classes/ProSmartCodes.phpnu['; foreach ($rows as $rowImages) { $html .= ''; foreach ($rowImages as $image) { $parts = explode('.', $image); $extension = array_pop($parts); if(in_array($extension, ['png', 'jpg', 'jpeg', 'gif'])) { $html .= ''; } else { $parts = explode('/', $image); $extension = array_pop($parts); $html .= ''.$extension.''; } } $html .= ''; } $html .= ''; return $html; } }PK!Ae-src/classes/FailedIntegrationNotification.phpnu[getEmailConfig(); return $settings['status'] == 'yes'; } public function getEmailConfig() { $settings = [ 'status' => 'yes', 'send_to_type' => 'admin_email', 'custom_recipients' => '', ]; if (get_option($this->key)) { $settings = get_option($this->key); } return $settings; } public function saveEmailConfig($request) { if (ArrayHelper::get($request, 'key') != 'failedIntegrationNotification') { return; } $defaults = [ 'status' => 'yes', 'send_to_type' => 'admin_email', 'custom_recipients' => '', ]; $settings = ArrayHelper::get($request, 'value'); $settings = json_decode($settings, true); $settings = wp_parse_args($settings, $defaults); update_option($this->key, $settings, false); wp_send_json_success(true); } /** * Get Send Email Addresses * * @param $email * @return array */ private function getSendAddresses($email) { $sendEmail = explode(',', $email); if (count($sendEmail) > 1) { $email = $sendEmail; } else { $email = [$email]; } return array_filter($email, 'is_email'); } public function maybeSendEmail() { if (!$this->isEnabled() || !$this->timeMatched()) { return; } $settings = $this->getEmailConfig(); $currentTime = current_time('mysql'); $lastHour = date('Y-m-d H:i:s', strtotime('-1 hour', strtotime($currentTime))); $failedFeeds = Scheduler::whereIn('status', ['failed', 'error']) ->where('retry_count', '>=', 3) ->with(['form' => function ($query) { $query->select('title', 'id'); }]) ->whereBetween('ff_scheduled_actions.updated_at', [$lastHour, $currentTime]) ->limit(11) ->get(); if (!$failedFeeds || $failedFeeds->isEmpty()) { return; } foreach ($failedFeeds as $index => $feed) { $feedData = maybe_unserialize($feed->data); $failedFeeds[$index]->integration_name = $this->getFeedName($feedData); $failedFeeds[$index]->submission_link = admin_url('admin.php?page=fluent_forms&form_id=' . $feed->form_id . '&route=entries#/entries/' . $feed->origin_id); } if ($settings['send_to_type'] == 'admin_email') { $email = get_option('admin_email'); } else { $email = $settings['custom_recipients']; } $recipients = $this->getSendAddresses($email); if (!$recipients) { return; } $this->broadCast($recipients, $failedFeeds); } private function broadCast($recipients, $failedFeeds) { $currentTime = current_time('mysql'); $lastHour = date('Y-m-d H:i:s', strtotime('-1 hour', strtotime($currentTime))); $data = [ 'failed_feeds' => $failedFeeds, 'first_item_time' => $lastHour, 'last_item_time' => $currentTime, ]; $emailBody = wpFluentForm('view')->make('email.failedIntegration.body', $data); $emailBody = apply_filters('fluentform/failed_integration_email_body', $emailBody, $data); $originalEmailBody = $emailBody; ob_start(); // apply CSS styles inline for picky email clients try { $emogrifier = new Emogrifier($emailBody); $emailBody = $emogrifier->emogrify(); } catch (\Exception $e) { } $maybeError = ob_get_clean(); if ($maybeError) { $emailBody = $originalEmailBody; } $headers = ['Content-Type: text/html; charset=utf-8']; $emailSubject = esc_html__('Failed Integration Notification', 'fluentform'); $emailSubject = apply_filters('fluentform/failed_integration_email_subject', $emailSubject); update_option('_ff_last_sent_failed_integration_mail', current_time('timestamp'), 'no'); return wp_mail($recipients, $emailSubject, $emailBody, $headers); } public function timeMatched() { $prevValue = get_option('_ff_last_sent_failed_integration_mail'); if (!$prevValue) { return true; } $time = apply_filters('fluentform/failed_integration_notification_time_gap', 3600);// set time by default 1 hour gap return (current_time('timestamp') - $prevValue) > $time; } private function getFeedName($feedData) { return !empty(ArrayHelper::get($feedData, 'settings.name')) ? ArrayHelper::get($feedData, 'settings.name') : ArrayHelper::get($feedData, 'settings.textTitle'); } } PK!+JD~~#src/classes/FormStylerGenerator.phpnu[ $parentSelector, 'label_styles' => $parentSelector . ' .ff-el-input--label label', 'placeholder_styles' => $parentSelector . ' .ff-el-input--content input::placeholder, ' . $parentSelector . ' .ff-el-input--content textarea::placeholder', 'asterisk_styles' => $parentSelector . ' .asterisk-right label:after, ' . $parentSelector . ' .asterisk-left label:before', 'inline_error_msg_style' => $parentSelector . ' .ff-el-input--content .error , ' . $parentSelector . ' .error-text', 'success_msg_style' => $parentSelector . ' .ff-message-success', 'error_msg_style' => $parentSelector . ' .ff-errors-in-stack ' ]; $cssCodes = ''; if (empty($styles)) { return $cssCodes; } //pass input label border styke to net promoter foreach ($styles as $styleKey => $style) { if (isset($normalTypes[$styleKey])) { $cssCodes .= $this->generateNormal($style, $normalTypes[$styleKey]); } else if ($styleKey == 'input_styles') { $cssCodes .= $this->generateInputStyles($style, $parentSelector); } else if ($styleKey == 'sectionbreak_styles') { $cssCodes .= $this->generateSectionBreak($style, $parentSelector); } else if ($styleKey == 'gridtable_style') { $cssCodes .= $this->generateGridTable($style, $parentSelector); } else if ($styleKey == 'payment_summary_style') { $cssCodes .= $this->generatePaymentSummary($style, $parentSelector); } else if ($styleKey == 'payment_coupon_style') { $cssCodes .= $this->generatePaymentCoupon($style, $parentSelector); } else if ($styleKey == 'image_or_file_button_style') { $cssCodes .= $this->generateImageOrFileButtonStyle($style, $parentSelector); } else if ($styleKey == 'submit_button_style') { $cssCodes .= $this->generateSubmitButton($style, $parentSelector); } else if ($styleKey == 'radio_checkbox_style') { $cssCodes .= $this->generateSmartCheckable($style, $parentSelector); } else if ($styleKey == 'next_button_style') { $cssCodes .= $this->generateNextButton($style, $parentSelector); } else if ($styleKey == 'prev_button_style') { $cssCodes .= $this->generatePrevButton($style, $parentSelector); } else if ($styleKey == 'step_header_style') { $cssCodes .= $this->generateStepHeader($style, $parentSelector); } else if ($styleKey == 'net_promoter_style') { $cssCodes .= $this->generateNetPromoter($style, $parentSelector); } else if ($styleKey == 'range_slider_style') { $cssCodes .= $this->generateRangeSliderStyle($style, $parentSelector); } } return $cssCodes; } /* * For the following * - container_styles * - label_styles * - placeholder_styles * - asterisk_styles * - help_msg_style * - success_msg_style * - error_msg_style */ public function generateNormal($styles, $selector) { $css = ''; foreach ($styles as $styleKey => $style) { $css .= $this->extrachStyle($style, $styleKey, ''); } if ($css && $selector) { return $selector . '{ ' . $css . ' } '; } return $css; } public function generateSectionBreak($item, $selector) { $titleStyles = Arr::get($item, 'all_tabs.tabs.LabelStyling.value'); $titleCss = $this->generateNormal($titleStyles, ''); if ($titleCss) { $titleCss = "{$selector} .ff-el-section-break .ff-el-section-title { {$titleCss} }"; } $focusStyles = Arr::get($item, 'all_tabs.tabs.DescriptionStyling.value'); $descCss = $this->generateNormal($focusStyles, ''); $customHTMLCss = $descCss; if ($descCss) { $descCss = "{$selector} .ff-el-section-break div.ff-section_break_desk { {$descCss} }"; $customHTMLCss = "{$selector} .ff-custom_html { {$customHTMLCss} }"; } return $titleCss . ' ' . $descCss . ' ' . $customHTMLCss; } public function generateGridTable($item, $selector) { $styleSelector = $selector . ' .ff-el-input--content table.ff-table.ff-checkable-grids thead tr th'; $theadStyles = Arr::get($item, 'all_tabs.tabs.TableHead.value'); $normalCss = $this->generateNormal($theadStyles, ''); if ($normalCss) { $normalCss = "{$styleSelector} { {$normalCss} }"; } $tbodyStyles = Arr::get($item, 'all_tabs.tabs.TableBody.value'); $tbodyCss = $this->generateNormal($tbodyStyles, ''); if ($tbodyCss) { $styleDescSelector = $selector . ' .ff-el-input--content table.ff-table.ff-checkable-grids tbody tr td'; $tbodyCss = "$styleDescSelector { {$tbodyCss} }"; } if ($oddColor = Arr::get($tbodyStyles, 'oddColor')) { if ($value = Arr::get($oddColor, 'value')) { $tbodyCss .= "{$selector} .ff-checkable-grids tbody > tr:nth-child(2n) > td{background-color:{$value}!important}"; } } return $normalCss . ' ' . $tbodyCss; } public function generatePaymentSummary($item, $selector) { $styleSelector = $selector . ' .ff-el-group .ff_payment_summary table thead tr th'; $theadStyles = Arr::get($item, 'all_tabs.tabs.TableHead.value'); $normalCss = $this->generateNormal($theadStyles, ''); if ($normalCss) { $normalCss = "{$styleSelector} { {$normalCss} }"; } $tbodyStyles = Arr::get($item, 'all_tabs.tabs.TableBody.value'); $tbodyCss = $this->generateNormal($tbodyStyles, ''); if ($tbodyCss) { $styleDescSelector = $selector . ' .ff-el-group .ff_payment_summary table tbody tr td'; $tbodyCss = "$styleDescSelector { {$tbodyCss} }"; } $tfootStyles = Arr::get($item, 'all_tabs.tabs.TableFooter.value'); $tfootCss = $this->generateNormal($tfootStyles, ''); if ($tfootCss) { $styleDescSelector = $selector . ' .ff-el-group .ff_payment_summary table tfoot tr th'; $tfootCss = "$styleDescSelector { {$tfootCss} }"; } return $normalCss . ' ' . $tbodyCss . ' ' . $tfootCss; } public function generatePaymentCoupon($item, $selector) { $styleSelector = $selector . ' .ff-el-group .ff-el-input--content .ff_input-group'; $buttonStyles = $this->generateNormal(Arr::get($item, 'all_tabs.tabs.button.value'),''); $hoverStyles = $this->generateNormal(Arr::get($item, 'all_tabs.tabs.buttonHover.value'), ''); if ($buttonStyles) { $buttonStyles = "{$styleSelector} .ff_input-group-append span { {$buttonStyles} }"; } if ($hoverStyles) { $hoverStyles = "{$styleSelector} .ff_input-group-append span:hover { {$hoverStyles} }"; } return $buttonStyles . ' ' . $hoverStyles; } public function generateImageOrFileButtonStyle($item, $selector) { $styleSelector = $selector . ' .ff-el-group .ff-el-input--content .ff_file_upload_holder'; $buttonStyles = $this->generateNormal(Arr::get($item, 'all_tabs.tabs.button.value'),''); $hoverStyles = $this->generateNormal(Arr::get($item, 'all_tabs.tabs.buttonHover.value'), ''); if ($buttonStyles) { $buttonStyles = "{$styleSelector} span.ff_upload_btn { {$buttonStyles} }"; } if ($hoverStyles) { $hoverStyles = "{$styleSelector} span.ff_upload_btn:hover { {$hoverStyles} }"; } return $buttonStyles . ' ' . $hoverStyles; } public function generateSubmitButton($style, $selector) { $stylesAllignment = $this->generateAllignment(Arr::get($style, 'allignment.value')); if ($stylesAllignment) { $stylesAllignment = "{$selector} .ff-el-group.ff_submit_btn_wrapper { {$stylesAllignment} }"; } $normalStyles = Arr::get($style, 'all_tabs.tabs.normal.value', []); $normalCss = $this->generateNormal($normalStyles, ''); if ($normalCss) { $normalCss = "{$selector} .ff_submit_btn_wrapper .ff-btn-submit:not(.ff_btn_no_style) { {$normalCss} }"; } $hoverStyles = Arr::get($style, 'all_tabs.tabs.hover.value', []); $hoverCss = $this->generateNormal($hoverStyles, ''); if ($hoverCss) { $hoverCss = "{$selector} .ff_submit_btn_wrapper .ff-btn-submit:not(.ff_btn_no_style):hover { {$hoverCss} }"; } return $stylesAllignment . $normalCss . $hoverCss; } public function generateNextButton($style, $selector) { $normalStyles = Arr::get($style, 'all_tabs.tabs.normal.value', []); $normalCss = $this->generateNormal($normalStyles, ''); if ($normalCss) { $normalCss = "{$selector} .step-nav .ff-btn-next { {$normalCss} }"; } $hoverStyles = Arr::get($style, 'all_tabs.tabs.hover.value', []); $hoverCss = $this->generateNormal($hoverStyles, ''); if ($hoverCss) { $hoverCss = "{$selector} .step-nav .ff-btn-next:hover { {$hoverCss} }"; } return $normalCss . $hoverCss; } public function generatePrevButton($style, $selector) { $normalStyles = Arr::get($style, 'all_tabs.tabs.normal.value', []); $normalCss = $this->generateNormal($normalStyles, ''); if ($normalCss) { $normalCss = "{$selector} .step-nav .ff-btn-prev { {$normalCss} }"; } $hoverStyles = Arr::get($style, 'all_tabs.tabs.hover.value', []); $hoverCss = $this->generateNormal($hoverStyles, ''); if ($hoverCss) { $hoverCss = "{$selector} .step-nav .ff-btn-prev:hover { {$hoverCss} }"; } return $normalCss . $hoverCss; } public function generateInputStyles($item, $selector) { $normalStyles = Arr::get($item, 'all_tabs.tabs.normal.value'); $normalCss = $this->generateNormal($normalStyles, ''); if ($normalCss) { $normalCss = "{$selector} .ff-el-input--content input, {$selector} .ff-el-input--content .ff-el-form-control.ff_stripe_card_element, {$selector} .ff-el-input--content textarea, {$selector} .ff-el-input--content select, {$selector} .choices__list--single, {$selector} .choices[data-type*='select-multiple'] { {$normalCss} }"; $borderCss = $this->extrachStyle($normalStyles['border'], 'border', ''); if($borderCss) { $normalCss .= " {$selector} .frm-fluent-form .choices__list--dropdown { {$borderCss} }"; } } $focusStyles = Arr::get($item, 'all_tabs.tabs.focus.value'); $focusCss = $this->generateNormal($focusStyles, ''); if ($focusCss) { $focusCss = "{$selector} .ff-el-input--content input:focus, {$selector} .ff-el-input--content .ff-el-form-control.ff_stripe_card_element:focus, {$selector} .ff-el-input--content textarea:focus, {$selector} .ff-el-input--content select:focus { {$focusCss} }"; } return $normalCss . ' ' . $focusCss; } public function generateSmartCheckable($item, $selector) { $itemColor = Arr::get($item, 'color.value'); $itemSize = Arr::get($item, 'size.value.value'); if ($itemSize) { $itemSize = $this->getResolveValue($itemSize, Arr::get($item, 'size.value.type')); } ob_start(); if ($itemColor) { ?> .ff-el-form-check { color: } .ff-el-group input[type=checkbox], .ff-el-group input[type=radio], { height: width: } generateAroundDimention('margin', $smartUIMargin)) { $smartUiMarginStyle = $marginStyle; } } $normalColor = Arr::get($item, 'radio_checkbox.value.color.value'); $checkedColor = Arr::get($item, 'radio_checkbox.value.active_color.value'); $customBorderOn = Arr::get($item, 'radio_checkbox.value.border.value.status') == 'yes'; $borderColor = $normalColor; $borderWidthStyle = 'border-width:1px;'; $borderRadiusStyle = 'border-radius:2px;'; $borderType = 'solid'; $radioBorderSameAsCheckbox = false; if ($customBorderOn == 'yes') { $borderColor = Arr::get($item, 'radio_checkbox.value.border.value.border_color'); $borderWidthStyle = $this->generateAroundDimentionBorder(Arr::get($item, 'radio_checkbox.value.border.value.border_width')); $borderRadiusStyle = $this->generateAroundDimentionBorderRadius('border', Arr::get($item, 'radio_checkbox.value.border.value.border_radius')); $borderType = Arr::get($item, 'radio_checkbox.value.border.value.border_type'); if ("yes" === Arr::get($item, 'radio_checkbox.value.border.value.radio_border_status')) { $radioBorderSameAsCheckbox = true; } } if (!$checkedColor) { $checkedColor = 'black'; } if (!$normalColor) { $normalColor = 'black'; } ?> input[type=checkbox] { -webkit-appearance: checkbox; } input[type=radio] { -webkit-appearance: radio; } .ff-el-group input[type=checkbox], .ff-el-group input[type=radio] { -webkit-transform: scale(1); transform: scale(1); width: 21px; height: 15px; margin-right: 0px; cursor: pointer; font-size: 12px; position: relative; text-align: left; border: none; box-shadow: none; -moz-appearance: initial; } .ff-el-group input[type=checkbox]:before, .ff-el-group input[type=radio]:before { content: none; } .ff-el-group input[type=checkbox]:after, .ff-el-group input[type=radio]:after { content: " "; background-color: #fff; display: inline-block; padding-bottom: 3px; color: #212529; width: ; height: ; border-color: ; border-style: ; padding-left: 1px; padding-top: 1px; -webkit-transition: all .1s ease; transition: all .1s ease; background-size: 9px; background-repeat: no-repeat; background-position: center center; position: absolute; box-sizing: border-box; } .ff-el-group input[type=checkbox]:checked:after, .ff-el-group input[type=radio]:checked:after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); background-color: ; -webkit-transition: all 0.3s ease-out; transition: all 0.3s ease-out; color: #fff; border-color: ; } .ff-el-group input[type=radio]:after { font-size: 10px; padding-top: 1px; padding-left: 2px; } .ff-el-group input[type=radio]:checked:after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E"); } $styleSetting) { if (in_array($styleKey, ['height', 'width', 'margin', 'boxshadow', 'border'])) { $otherStyles .= $this->extrachStyle($styleSetting, $styleKey, ''); } elseif ( 'textPosition' == $styleKey && $textPositionStyle = $this->generateAroundProperty('{replace}', $styleSetting) ) { $otherStyles .= 'position:relative;'; $styles .= "{$selector} .ff-el-progress .ff-el-progress-bar span {position:absolute;{$textPositionStyle}}"; } } if ($otherStyles) { if (strpos($otherStyles, 'height') !== false) { $styles .= "{$selector} .ff-el-progress .ff-el-progress-bar {display:flex;align-items:center;justify-content:end;}"; } $styles .= "{$selector} .ff-el-progress {{$otherStyles}}`"; } return $styles; } public function generateNetPromoter($item, $selector) { $styles = ''; $activeStyle = ''; $normalStyle = ''; if ($activeColor = Arr::get($item, 'activeColor.value')) { $activeStyle .= "background-color: {$activeColor};"; $styles .= "{$selector} .ff_net_table tbody tr td label:hover:after { border-color: transparent; }"; } if ($color = Arr::get($item, 'color.value')) { $activeStyle .= "color: {$color};"; } if ($activeStyle) { $styles .= "{$selector} .ff_net_table tbody tr td input[type=radio]:checked + label { {$activeStyle} }"; $styles .= "{$selector} .ff_net_table tbody tr td input[type=radio] + label:hover { {$activeStyle} }"; } $styles .= "{$selector} .ff_net_table tbody tr td input[type=radio]:checked + label { background-color: {$activeColor}; } {$selector} .ff_net_table tbody tr td label:hover:after { border-color: {$activeColor}; }"; if ($inActiveColor = Arr::get($item, 'inActiveColor.value')) { $normalStyle .= "color: {$inActiveColor};"; } if ($inActiveBgColor = Arr::get($item, 'inActiveBgColor.value')) { $normalStyle .= "background-color: {$inActiveBgColor};"; } if ($height = Arr::get($item, 'height.value.value')) { $height = $this->getResolveValue($height, Arr::get($item, 'height.value.type')); $normalStyle .= "height: {$height};"; } if ($lineHeight = Arr::get($item, 'lineHeight.value.value')) { $lineHeight = $this->getResolveValue($lineHeight, Arr::get($item, 'lineHeight.value.type')); $normalStyle .= "line-height: {$lineHeight};"; } if ($normalStyle) { $styles .= "{$selector} .ff_net_table tbody tr td input[type=radio] + label { {$normalStyle} }"; } if (Arr::get($item,'border.value.status') == 'yes') { $border = Arr::get($item,'border'); if ($borderStyle = $this->extrachStyle($border, 'border', '')) { $borderStyle .= "border-left: 0;border-radius: 0;"; $styles .= "{$selector} .ff_net_table tbody tr td {{$borderStyle}}"; $firstTdStyle = ''; $lastTdStyle = ''; if ($borderColor = Arr::get($border, 'value.border_color')) { $firstTdStyle .= "border-color: {$borderColor};"; } if ($borderType = Arr::get($border, 'value.border_type')) { $firstTdStyle .= "border-style: {$borderType};"; } $borderWidth = Arr::get($border, 'value.border_width'); if ($borderRight = Arr::get($borderWidth, 'right')) { $borderRight = $this->getResolveValue($borderRight, Arr::get($borderWidth, 'type')); $styles .= "{$selector} .ff_net_table tbody tr td:last-of-type { border-right-width : $borderRight; }"; } if ($borderLeft = Arr::get($borderWidth, 'left')) { $borderLeft = $this->getResolveValue($borderLeft, Arr::get($borderWidth, 'type')); $firstTdStyle .= "border-left-width: {$borderLeft};"; } $borderRadius = Arr::get($border, 'value.border_radius'); if ($topRadius = Arr::get($borderRadius, 'top')) { $topRadius = $this->getResolveValue($topRadius, Arr::get($borderRadius, 'type')); $firstTdStyle .= "border-top-left-radius: {$topRadius};"; } if ($bottomRadius = Arr::get($borderRadius, 'bottom')) { $bottomRadius = $this->getResolveValue($bottomRadius, Arr::get($borderRadius, 'type')); $firstTdStyle .= "border-bottom-left-radius: {$bottomRadius};"; } if ($rightRadius = Arr::get($borderRadius, 'right')) { $rightRadius = $this->getResolveValue($rightRadius, Arr::get($borderRadius, 'type')); $lastTdStyle .= "border-top-right-radius: {$rightRadius};"; } if ($leftRadius = Arr::get($borderRadius, 'left')) { $leftRadius = $this->getResolveValue($leftRadius, Arr::get($borderRadius, 'type')); $lastTdStyle .= "border-bottom-right-radius: {$leftRadius};"; } if ($firstTdStyle) { $styles .= "{$selector} .ff_net_table tbody tr td:first-of-type { overflow:hidden; {$firstTdStyle}}"; } if ($lastTdStyle) { $styles .= "{$selector} .ff_net_table tbody tr td:last-child{overflow:hidden; {$lastTdStyle}}"; } } } return $styles; } public function generateRangeSliderStyle($item, $selector) { $styles = ''; if ($activeColor = Arr::get($item, 'activeColor.value')) { $inactiveColor = Arr::get($item, 'inActiveColor.value'); $textColor = Arr::get($item, 'textColor.value'); if (!$inactiveColor) { $inactiveColor = '#e6e6e6'; } if (!$textColor) { $textColor = '#3a3a3a'; } $styles = "{$selector} .rangeslider__fill { background: {$activeColor}; } {$selector} .rangeslider { background: {$inactiveColor}; } {$selector} .rangeslider__handle { color: {$textColor}; }"; } if ($height = Arr::get($item, 'height.value.value')) { $height = $this->getResolveValue($height, Arr::get($item, 'height.value.type')); $styles .= "{$selector} .rangeslider--horizontal { height: {$height};}"; } if ($size = Arr::get($item, 'handleSize.value.value')) { $size = $this->getResolveValue($size, Arr::get($item, 'handleSize.value.type')); $styles .= "{$selector} .rangeslider__handle { height:{$size};width:{$size};}"; } return $styles; } public function extrachStyle($style, $styleKey, $selector) { $cssStyle = ''; if ($styleKey == 'backgroundColor' || $styleKey == 'des_backgroundColor' || $styleKey == 'hover_backgroundColor') { if ($value = Arr::get($style, 'value')) { $cssStyle .= "background-color: {$value};"; } else { return ''; } } else if ($styleKey == 'backgroundImage') { $cssStyle .= $this->generateBackgroundImage(Arr::get($style, 'value')); } else if ($styleKey == 'color' || $styleKey == 'des_color') { if ($value = Arr::get($style, 'value')) { $cssStyle .= "color: {$value};"; } else { return ''; } } else if ($styleKey == 'width') { $value = Arr::get($style, 'value'); $unit = Arr::get($style, 'type', 'custom'); if (is_array($value)) { $unit = Arr::get($value, 'type'); $value = Arr::get($value, 'value'); } if ($value && $unit) { $value = $this->getResolveValue($value, $unit); $cssStyle .= "width: {$value};"; } else { return ''; } } else if ($styleKey == 'color_asterisk' || $styleKey == 'color_imp' || $styleKey == 'hover_color_imp') { if ($value = Arr::get($style, 'value')) { $cssStyle .= "color: {$value} !important;;"; } else { return ''; } } else if ($styleKey == 'margin' || $styleKey == 'padding') { $value = Arr::get($style, 'value'); $cssStyle .= $this->generateAroundDimention($styleKey, $value); } else if ($styleKey == 'border' || $styleKey == 'hover_border') { if (Arr::get($style, 'value.status') != 'yes') { return ''; } if ($borderType = Arr::get($style, 'value.border_type')) { $cssStyle .= 'border-style: ' . $borderType . ';'; } if ($borderColor = Arr::get($style, 'value.border_color')) { $cssStyle .= 'border-color: ' . $borderColor . ';'; } $cssStyle .= $this->generateAroundDimentionBorder(Arr::get($style, 'value.border_width')); $cssStyle .= $this->generateAroundDimentionBorderRadius('border', Arr::get($style, 'value.border_radius')); } else if ($styleKey == 'typography' || $styleKey == 'des_typography' || $styleKey == 'hover_typography') { $cssStyle .= $this->generateTypegraphy(Arr::get($style, 'value')); } else if ($styleKey == 'des_margin') { $cssStyle .= $this->generateAroundDimention('margin', Arr::get($style, 'value')); } else if ($styleKey == 'des_padding') { $cssStyle .= $this->generateAroundDimention('padding', Arr::get($style, 'value')); } else if ($styleKey == 'boxshadow' || $styleKey == 'hover_boxshadow') { $cssStyle .= $this->generateBoxshadow(Arr::get($style, 'value')); } else if ($styleKey == 'allignment') { $cssStyle .= $this->generateAllignment(Arr::get($style, 'value')); } else if ($styleKey == 'placeholder') { $cssStyle .= $this->generatePlaceholder(Arr::get($style, 'value')); } else if ($styleKey == 'height') { if ($height = Arr::get($style, 'value.value')) { $height = $this->getResolveValue($height, Arr::get($style, 'value.type')); $cssStyle .= "height: {$height};"; } else { return ''; } } if ($cssStyle && $selector) { return $selector . '{ ' . $cssStyle . ' } '; } return $cssStyle; } public function generateAroundProperty($property, $values, $isRadius = false) { $cssStyle = ''; $unit = Arr::get($values, 'type', 'px'); if ($this->hasValue($top = Arr::get($values, 'top'))) { $value = $this->getResolveValue($top, $unit); $cssProperty = str_replace('{replace}', $isRadius ? 'top-left' : 'top', $property); $cssStyle .= "{$cssProperty}: {$value};"; } if ($this->hasValue($left = Arr::get($values, 'left'))) { $value = $this->getResolveValue($left, $unit); $cssProperty = str_replace('{replace}', $isRadius ? 'bottom-right' : 'left', $property); $cssStyle .= "{$cssProperty}: {$value};"; } if ($this->hasValue($right = Arr::get($values, 'right'))) { $value = $this->getResolveValue($right, $unit); $cssProperty = str_replace('{replace}', $isRadius ? 'top-right' : 'right', $property); $cssStyle .= "{$cssProperty}: {$value};"; } if ($this->hasValue($bottom = Arr::get($values, 'bottom'))) { $value = $this->getResolveValue($bottom, $unit); $cssProperty = str_replace('{replace}', $isRadius ? 'bottom-left' : 'bottom', $property); $cssStyle .= "{$cssProperty}: {$value};"; } return $cssStyle; } private function hasValue($value) { return $value === '0' || !empty($value); } public function generateAroundDimention($styleKey, $values) { $unit = Arr::get($values, 'type', 'px'); if (Arr::get($values, 'linked') == 'yes') { if ($this->hasValue($top = Arr::get($values, 'top'))) { $top = $this->getResolveValue($top, $unit); return "{$styleKey}: {$top};"; } return ''; } return $this->generateAroundProperty("$styleKey-{replace}", $values); } public function generateAroundDimentionBorder($values) { $unit = Arr::get($values, 'type', 'px'); if (Arr::get($values, 'linked') == 'yes') { if ($this->hasValue($top = Arr::get($values, 'top'))) { $top = $this->getResolveValue($top, $unit); return "border-width: {$top};"; } return ''; } return $this->generateAroundProperty("border-{replace}-width", $values); } public function generateAroundDimentionBorderRadius($styleKey, $values) { if (!$values) return ''; $unit = Arr::get($values, 'type', 'px'); if (Arr::get($values, 'linked') == 'yes') { if ($this->hasValue($top = Arr::get($values, 'top'))) { $top = $this->getResolveValue($top, $unit); return "{$styleKey}-radius: {$top};"; } return ''; } return $this->generateAroundProperty("$styleKey-{replace}-radius", $values, true); } public function generateTypegraphy($values) { $styles = ''; if ($fontSize = Arr::get($values, 'fontSize.value')) { $fontSize = $this->getResolveValue($fontSize, Arr::get($values, 'fontSize.type', 'px')); $styles .= "font-size: {$fontSize};"; } if ($value = Arr::get($values, 'fontWeight')) { $styles .= "font-weight: {$value};"; } if ($value = Arr::get($values, 'transform')) { $styles .= "text-transform: {$value};"; } if ($value = Arr::get($values, 'fontStyle')) { $styles .= "font-style: {$value};"; } if ($value = Arr::get($values, 'textDecoration')) { $styles .= "text-decoration: {$value};"; } if ($lineHeight = Arr::get($values, 'lineHeight.value')) { $lineHeight = $this->getResolveValue($lineHeight, Arr::get($values, 'lineHeight.type', 'px')); $styles .= "line-height: {$lineHeight};"; } if ($letterSpacing = Arr::get($values, 'letterSpacing.value')) { $letterSpacing = $this->getResolveValue($letterSpacing, Arr::get($values, 'letterSpacing.type', 'px')); $styles .= "letter-spacing: {$letterSpacing};"; } if ($wordSpacing = Arr::get($values, 'wordSpacing.value')) { $wordSpacing = $this->getResolveValue($wordSpacing, Arr::get($values, 'wordSpacing.type', 'px')); $styles .= "word-spacing: {$wordSpacing};"; } return $styles; } public function generateBackgroundImage($values) { $styles = ''; if ('classic' == Arr::get($values, 'type')) { if ($imgUrl = Arr::get($values, 'image.url')) { $styles .= "background-image: url('". $imgUrl ."');"; if ($position = Arr::get($values, 'image.position.value')) { if ("custom" == $position) { if ($xPosition = Arr::get($values, 'image.position.valueX.value')) { $xPosition = $this->getResolveValue($xPosition, Arr::get($values, 'image.position.valueX.type')); $styles .= "background-position-x: {$xPosition};"; } if ($yPosition = Arr::get($values, 'image.position.valueY.value')) { $yPosition = $this->getResolveValue($yPosition, Arr::get($values, 'image.position.valueY.type')); $styles .= "background-position-y: {$yPosition};"; } } else { $styles .= "background-position: {$position};"; } } if ($repeat = Arr::get($values, 'image.repeat')) { $styles .= "background-repeat: {$repeat};"; } if ($attachment = Arr::get($values, 'image.attachment')) { $styles .= "background-attachment: {$attachment};"; } if ($size = Arr::get($values, 'image.position.value')) { if ("custom" == $size) { $x = 'auto'; $y = 'auto'; if ($xSize = Arr::get($values, 'image.position.valueX.value')) { $x = $this->getResolveValue($xSize, Arr::get($values, 'image.position.valueX.type')); } if ($ySize = Arr::get($values, 'image.position.valueY.value')) { $y = $this->getResolveValue($ySize, Arr::get($values, 'image.position.valueY.type')); } $size = "{$x} {$y}"; } $styles .= "background-size: {$size};"; } } } else { $primary = Arr::get($values, 'gradient.primary'); $secondary = Arr::get($values, 'gradient.secondary'); if (Arr::get($primary, 'color') && Arr::get($secondary, 'color')) { $primaryColor = Arr::get($primary, 'color'); $secondaryColor = Arr::get($secondary, 'color'); $primaryLocation = Arr::get($primary, 'location.value'); $primaryLocation = $primaryLocation ?: 0; $primaryLocation = $this->getResolveValue($primaryLocation, Arr::get($primary, 'location.type', '%')); $secondaryLocation = Arr::get($secondary, 'location.value'); $secondaryLocation = $secondaryLocation ?: 0; $secondaryLocation = $this->getResolveValue($secondaryLocation, Arr::get($secondary, 'location.type', '%')); if ("radial" == Arr::get($values, 'gradient.type')) { $position = Arr::get($values, 'gradient.position', 'center-center'); $styles .= "background-image: radial-gradient(at {$position}, {$primaryColor} {$primaryLocation}, {$secondaryColor} {$secondaryLocation});"; } else { $angle = Arr::get($values, 'gradient.angle.value', 0); $angle = $angle ?: 0; $angle = $this->getResolveValue($angle, Arr::get($values, 'gradient.angle.type', '%')); $styles .= "background-image: linear-gradient({$angle}, {$primaryColor} {$primaryLocation}, {$secondaryColor} {$secondaryLocation});"; } } } return $styles; } public function generateBoxshadow($values) { $styles = ''; $color = Arr::get($values, 'color', ''); $horValue = Arr::get($values, 'horizontal.value'); $verValue = Arr::get($values, 'vertical.value'); $blurValue = Arr::get($values, 'blur.value'); $spreadValue = Arr::get($values, 'spread.value'); if ($horValue) { $horValue = $this->getResolveValue($horValue, Arr::get($values, 'horizontal.type', 'px')); } if ($verValue) { $verValue = $this->getResolveValue($verValue, Arr::get($values, 'vertical.type', 'px')); } if ($blurValue) { $blurValue = $this->getResolveValue($blurValue, Arr::get($values, 'blur.type', 'px')); } if ($spreadValue) { $spreadValue = $this->getResolveValue($spreadValue, Arr::get($values, 'spread.type', 'px')); } if ($horValue || $verValue || $blurValue || $spreadValue) { $horValue = $horValue ?: 0; $verValue = $verValue ?: 0; $blurValue = $blurValue ?: 0; $spreadValue = $spreadValue ?: 0; $styles = "box-shadow: {$horValue} {$verValue} {$blurValue} {$spreadValue} {$color}"; if (Arr::get($values, 'position') == 'inset') { $styles .= ' inset'; } $styles .= ';'; } return $styles; } public function generateAllignment($value) { if (!$value) { return ''; } return 'text-align: ' . $value . ';'; } public function generatePlaceholder($value) { if (!$value) { return ''; } return 'color: ' . $value . ';'; } public function getResolveValue($value, $type) { return 'custom' == $type ? $value : $value . $type; } } PK!C%%src/classes/SurveyResultProcessor.phpnu[ null, 'field_name' => '', 'label' => 'yes', 'counts' => 'yes' )); if (empty($attributes['form_id'])) { return ''; } $form = wpFluent()->table('fluentform_forms')->find($attributes['form_id']); if (!$form) { return ''; } $reportingFields = $this->getReportableFields($form, $attributes['field_name']); $reports = ReportHelper::getInputReport($form->id, array_keys($reportingFields)); $formattedReports = []; foreach ($reports as $reportKey => $report) { $formattedValues = []; $options = $reportingFields[$reportKey]['options'];; foreach ($report['reports'] as $reportItem) { $reportItem['percent'] = round( ($reportItem['count'] / $report['total_entry']) * 100); if (isset($options[$reportItem['value']])) { $itemKey = $reportItem['value']; $reportItem['value'] = $options[$itemKey]; $formattedValues[$itemKey] = $reportItem; } } $shotableArray = array_intersect(array_keys($options), array_keys($formattedValues)); $formattedValues = array_replace(array_flip($shotableArray), $formattedValues); $formattedValues = array_filter($formattedValues, 'is_array'); $report['reports'] = $formattedValues; $report['label'] = $reportingFields[$reportKey]['label']; $report['options'] = $options; $report['element'] = $reportingFields[$reportKey]['element']; $formattedReports[$reportKey] = $report; } $reportHtml = '
    '; foreach ($formattedReports as $formattedReport) { $reportHtml .= $this->getGereratedReortHtml($formattedReport, $attributes['label'], $attributes['counts'], $form); } $reportHtml .= '
    '; $css = $this->getPollCss(); return $css.$reportHtml; } public function getReportableFields($form, $reportFieldName) { $reportFieldNames = explode(',', $reportFieldName); $fields = FormFieldsParser::getInputs($form, ['element', 'options', 'label']); $reportableFields = Helper::getReportableInputs(); $reportableItems = []; foreach ($fields as $fieldName => $field) { if ($field['element'] == 'select_country') { $field['options'] = getFluentFormCountryList(); } if (in_array($field['element'], $reportableFields) && !empty($field['options'])) { $reportableItems[$fieldName] = $field; } } if (!$reportFieldName) { return $reportableItems; } $returnItems = []; foreach ($reportFieldNames as $reportFieldName) { if (isset($reportableItems[$reportFieldName])) { $returnItems[$reportFieldName] = $reportableItems[$reportFieldName]; } } return $returnItems; } public function getGereratedReortHtml($data, $showLabel = 'yes', $showCount = 'yes', $form) { $showLabel = $showLabel == 'yes'; $showCount = $showCount == 'yes'; ob_start(); ?>
    %
    ()
    $exception->getMessage() ], 423); } wp_send_json_success([ 'message' => __('Entry data successfully updated', 'fluentformpro'), 'data' => $entryData ]); } public static function updateEntryResponse($id, $response) { // Find the database Entry First $entry = wpFluent()->table('fluentform_submissions') ->where('id', $id) ->first(); if (!$entry) { throw new \Exception('No Entry Found'); } $origianlResponse = json_decode($entry->response, true); $diffs = []; foreach ($response as $resKey => $resvalue) { if (!isset($origianlResponse[$resKey]) || $origianlResponse[$resKey] != $resvalue) { $diffs[$resKey] = $resvalue; } } if (!$diffs) { return true; } $response = wp_parse_args($response, $origianlResponse); wpFluent()->table('fluentform_submissions') ->where('id', $id) ->update([ 'response' => json_encode($response, JSON_UNESCAPED_UNICODE), 'updated_at' => current_time('mysql') ]); $entries = new Entries(); $entries->updateEntryDiffs($id, $entry->form_id, $diffs); $user = get_user_by('ID', get_current_user_id()); $message = ''; if ($user) { $message = __('Entry data has been updated by ', 'fluentformpro') . $user->user_login; } $logData = [ 'parent_source_id' => $entry->form_id, 'source_type' => 'submission_item', 'source_id' => $entry->id, 'component' => 'EntryEditor', 'status' => 'info', 'title' => 'Entry Data Updated', 'description' => $message, ]; do_action('fluentform/log_data', $logData); return true; } } PK!1:ah h src/classes/Analytics.phpnu[ 'analytics', // 'title' => __('Analytics', 'fluentformpro') // ); return $menus; } public function render($form_id) { $analytics = array( // 'uniqueViews' => $this->getUniqueViews($form_id) ); require (FLUENTFORMPRO_DIR_PATH.'src/views/analytics_view.php'); wp_enqueue_script( 'fluentformpro_analytics_render', FLUENTFORMPRO_DIR_URL."public/js/analytics.js", false ); wp_localize_script('fluentformpro_analytics_render', 'fluentformpro_analytics', array( 'form_id' => $form_id, 'analytics' => $analytics )); } private function getUniqueViews($form_id, $start, $end) { return wpFluent()->table('fluentform_form_analytics') ->where('form_id', $form_id) ->whereBetween('created_at', $start, $end) ->count(); } private function getTotalViews($form_id, $start, $end) { global $wpdb; $views = wpFluent()->table('fluentform_form_analytics') ->select(wpFluent()->raw('SUM('.$wpdb->prefix.'fluentform_form_analytics.count) as total_views')) ->where('form_id', $form_id) ->whereBetween('created_at', $start, $end) ->first(); return ($views) ? $views->total_views : 0; } private function byWeek($form_id) { $data = []; for ($i = 6; $i >= 0; $i--) { $start = date('Y-m-d 00:00:00', strtotime("-$i day")); $day = date('l', strtotime($start)); $end = date('Y-m-d 23:59:59', strtotime("-$i day")); $uniqueViews = $this->getUniqueViews($form_id, $start, $end); $totalViews = $this->getTotalViews($form_id, $start, $end); $data['labels'][] = $day; $data['totalViews'][] = $totalViews; $data['uniqueViews'][] = $uniqueViews; } return $data; } private function byMonth($form_id) { $data = []; $totalDays = (int)date('t'); for ($i = 1; $i <= $totalDays; $i++) { $start = date("Y-m-$i 00:00:00", strtotime("-$i day")); $end = date("Y-m-$i 23:59:59", strtotime("-$i day")); $uniqueViews = $this->getUniqueViews($form_id, $start, $end); $totalViews = $this->getTotalViews($form_id, $start, $end); $data['labels'][] = date('Y-m-d', strtotime($start)); $data['totalViews'][] = $totalViews; $data['uniqueViews'][] = $uniqueViews; } return $data; } public function fetchAnalytics() { $data_span = sanitize_text_field($_REQUEST['data_span']); $form_id = intval($_REQUEST['form_id']); $data = []; if ($data_span == 'week') { $data = $this->byWeek($form_id); } if ($data_span == 'month') { $data = $this->byMonth($form_id); } wp_send_json_success(array( 'analytics' => $data ), 200); wp_send_json_error(array( ), 421); } }PK!}>j>j'src/classes/DraftSubmissionsManager.phpnu[app = $app; $this->init(); } public function init() { add_action('init', [$this, 'maybeLoadSavedProgress'], 99); add_action('fluentform/submission_inserted', [$this, 'delete'], 10, 3); add_filter('fluentform/form_fields_update', [$this, 'checkPartialSettings'], 10, 2); $this->registerAjaxHandlers(); } public static function boot($app) { return new static($app); } public function registerAjaxHandlers() { $this->app->addAdminAjaxAction('fluentform_step_form_save_data', [$this, 'saveWithCookie']); $this->app->addPublicAjaxAction('fluentform_step_form_save_data', [$this, 'saveWithCookie']); $this->app->addAdminAjaxAction('fluentform_step_form_get_data', [$this, 'getEntry']); $this->app->addPublicAjaxAction('fluentform_step_form_get_data', [$this, 'getEntry']); $this->app->addAdminAjaxAction('fluentform_save_form_progress_with_link', [$this, 'saveWithLink']); $this->app->addPublicAjaxAction('fluentform_save_form_progress_with_link', [$this, 'saveWithLink']); $this->app->addAdminAjaxAction('fluentform_email_progress_link', [$this, 'emailProgressLink']); $this->app->addPublicAjaxAction('fluentform_email_progress_link', [$this, 'emailProgressLink']); $this->app->addAdminAjaxAction('fluentform_get_form_state', [$this, 'getEntryFromLink']); $this->app->addPublicAjaxAction('fluentform_get_form_state', [$this, 'getEntryFromLink']); } public static function get($hash, $formId = false) { if ($formId) { return wpFluent()->table(static::$tableName) ->where('hash', $hash) ->where('form_id', $formId) ->first(); } return wpFluent()->table(static::$tableName)->where('hash', $hash)->first(); } public function getEntry() { $data = null; $entry = false; $formId = intval($_REQUEST['form_id']); if ($hash = $this->getHash()) { $entry = $this->get($hash, $formId); } if (!$entry && $userId = get_current_user_id()) { $entry = wpFluent()->table(static::$tableName) ->where('user_id', $userId) ->where('form_id', $formId) ->first(); } if ($entry) { $data['step_completed'] = (int)$entry->step_completed; $data['response'] = json_decode($entry->response, true); $form = wpFluent()->table('fluentform_forms')->where('id', $formId)->first(); if ($form) { $fields = FormFieldsParser::getInputsByElementTypes($form, ['input_file', 'input_image']); foreach ($fields as $name => $field) { if ($urls = Arr::get($data['response'], $name)) { foreach ($urls as $index => $url) { $data['response'][$name][$index] = [ "data_src" => $url, "url" => \FluentForm\App\Helpers\Helper::maybeDecryptUrl($url) ]; } } } } unset( $data['response']['_wp_http_referer'], $data['response']['__fluent_form_embded_post_id'], $data['response']['_fluentform_' . $entry->form_id . '_fluentformnonce'] ); } wp_send_json($data, 200); } public function getEntryFromLink() { $this->verify(); $data = null; $entry = false; $hash = $_REQUEST['hash']; $formId = intval($_REQUEST['form_id']); $entry = $this->get($hash, $formId); if (!$entry && $userId = get_current_user_id()) { $entry = wpFluent()->table(static::$tableName) ->where('user_id', $userId) ->where('form_id', $formId) ->first(); } if ($entry) { $data['step_completed'] = (int)$entry->step_completed; $data['response'] = json_decode($entry->response, true); unset( $data['response']['_wp_http_referer'], $data['response']['__fluent_form_embded_post_id'], $data['response']['_fluentform_' . $entry->form_id . '_fluentformnonce'] ); } wp_send_json($data, 200); } public function saveWithLink() { $formData = $this->app->request->get(); $formId = $this->app->request->get('form_id'); $saveProgressBttn = $this->getSaveProgressButtonData($formId); $successMessage = Arr::get($saveProgressBttn,'raw.settings.save_success_message'); $this->verify(); $hash = isset($formData['hash']) ? sanitize_text_field($formData['hash']) : -1; if ($hash == -1) { $hash = $this->getHash(); } $this->saveState($hash); $sourceUrl = $this->getSavedLink($hash); wp_send_json_success( [ 'saved_url' => $sourceUrl, 'hash' => $hash, 'message' => $successMessage, ] ); } public function saveWithCookie() { $hash = $this->getHash(); $this->saveState($hash); wp_send_json_success(); } public function saveState($hash) { $formData = $this->app->request->get(); parse_str($formData['data'], $formData['data']); $isStepForm = true; if ($formData['active_step'] == 'no') { $formData['active_step'] = -1; $isStepForm = false; } $response = json_encode($formData['data']); $formId = $formData['form_id']; $exist = $this->get($hash); if (!$exist) { $browser = new Browser(); $ipAddress = $this->app->request->getIp(); $status = apply_filters_deprecated( 'fluentform_disable_ip_logging', [ false, $formId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/disable_ip_logging', 'Use fluentform/disable_ip_logging instead of fluentform_disable_ip_logging.' ); if ((defined('FLUENTFROM_DISABLE_IP_LOGGING') && FLUENTFROM_DISABLE_IP_LOGGING) || apply_filters('fluentform/disable_ip_logging', $status, $formId)) { $ipAddress = false; } $response = [ 'form_id' => $formData['form_id'], 'hash' => $hash, 'response' => $response, 'source_url' => site_url(Arr::get($formData, 'data._wp_http_referer')), 'user_id' => get_current_user_id(), 'browser' => $browser->getBrowser(), 'device' => $browser->getPlatform(), 'ip' => $ipAddress, 'step_completed' => $formData['active_step'], 'created_at' => current_time('mysql'), 'type' => $isStepForm ? 'step_data' : 'saved_state_data', 'updated_at' => current_time('mysql') ]; $insertId = wpFluent()->table(static::$tableName)->insertGetId($response); if ($isStepForm) { do_action_deprecated( 'fluentform_partial_submission_added', [ $formData['data'], $response, $insertId, $formId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/partial_submission_added', 'Use fluentform/partial_submission_added instead of fluentform_partial_submission_added.' ); do_action('fluentform/partial_submission_added', $formData['data'], $response, $insertId, $formId); do_action_deprecated( 'fluentform_partial_submission_step_completed', [ 1, $formData['data'], $insertId, $formId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/partial_submission_step_completed', 'Use fluentform/partial_submission_step_completed instead of fluentform_partial_submission_step_completed.' ); do_action('fluentform/partial_submission_step_completed', 1, $formData['data'], $insertId, $formId); } else { do_action_deprecated( 'fluentform_saved_progress_submission_added', [ $formData['data'], $response, $insertId, $formId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/saved_progress_submission_added', 'Use fluentform/saved_progress_submission_added instead of fluentform_saved_progress_submission_added.' ); do_action('fluentform/saved_progress_submission_added', $formData['data'], $response, $insertId, $formId); } } else { wpFluent()->table(static::$tableName)->where('id', $exist->id)->update([ 'response' => $response, 'step_completed' => $formData['active_step'], 'updated_at' => current_time('mysql') ]); if ($isStepForm) { do_action_deprecated( 'fluentform_partial_submission_step_completed', [ $formData['active_step'], $formData['data'], $exist->id, $formId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/partial_submission_step_completed', 'Use fluentform/partial_submission_step_completed instead of fluentform_partial_submission_step_completed.' ); do_action('fluentform/partial_submission_step_completed', $formData['active_step'], $formData['data'], $exist->id, $formId); do_action_deprecated( 'fluentform_partial_submission_updated', [ $formData['data'], $formData['active_step'], $exist->id, $formId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/partial_submission_updated', 'Use fluentform/partial_submission_updated instead of fluentform_partial_submission_updated.' ); do_action('fluentform/partial_submission_updated', $formData['data'], $formData['active_step'], $exist->id, $formId); } else { do_action_deprecated( 'fluentform_saved_progress_submission_updated', [ $formData['data'], $formData['active_step'], $exist->id, $formId ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/saved_progress_submission_updated', 'Use fluentform/saved_progress_submission_updated instead of fluentform_saved_progress_submission_updated.' ); do_action('fluentform/saved_progress_submission_updated', $formData['data'], $formData['active_step'], $exist->id, $formId); } } if ($isStepForm) { $this->setcookie($this->getCookieName($formId), $hash, $this->getExpiryDate()); } } public function delete($insertId, $formData, $form) { $this->deleteSavedStateDraft($form, $formData); $this->deleteStepFormDraft($form); } protected function getHash() { return Arr::get( $_COOKIE, $this->getCookieName(), wp_generate_uuid4() ); } protected function getCookieName($formId = false) { $formId = $formId ? $formId : $this->app->request->get('form_id'); return static::$cookieName . '_' . $formId; } protected function getExpiryDate($previousTime = false) { $offset = 7 * 24 * 60 * 60; return ($previousTime) ? time() - $offset : time() + $offset; } protected function setCookie($name, $value, $expiryDate) { setcookie( $name, $value, $expiryDate, COOKIEPATH, COOKIE_DOMAIN ); } protected function deleteCookie($formId = false) { $this->setcookie($this->getCookieName($formId), '', $this->getExpiryDate(true)); } public function checkPartialSettings($fields, $formId) { $fieldsArray = \json_decode($fields, true); $isPartialEnabled = 'no'; if (isset($fieldsArray['stepsWrapper'])) { $isPartialEnabled = Arr::get($fieldsArray, 'stepsWrapper.stepStart.settings.enable_step_data_persistency', 'no'); } self::migrate(); Helper::setFormMeta($formId, 'step_data_persistency_status', $isPartialEnabled); $savedStateButton = array_filter($fieldsArray['fields'], function ($field) { return Arr::get($field, 'element') == 'save_progress_button'; }); if (!empty($savedStateButton)) { Helper::setFormMeta($formId, 'form_save_state_status', 'yes'); } else { Helper::setFormMeta($formId, 'form_save_state_status', 'no'); } return $fields; } /** * Migrate the table. * * @return void */ public static function migrate() { global $wpdb; $charsetCollate = $wpdb->get_charset_collate(); $table = $wpdb->prefix . static::$tableName; if ($wpdb->get_var("SHOW TABLES LIKE '$table'") != $table) { $sql = "CREATE TABLE $table ( `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, `form_id` INT UNSIGNED NULL, `hash` VARCHAR(255) NOT NULL, `type` VARCHAR(255) DEFAULT 'step_data', `step_completed` INT UNSIGNED NOT NULL, `user_id` INT UNSIGNED NOT NULL, `response` LONGTEXT NULL, `source_url` VARCHAR(255) NULL, `browser` VARCHAR(45) NULL, `device` VARCHAR(45) NULL, `ip` VARCHAR(45) NULL, `created_at` TIMESTAMP NULL, `updated_at` TIMESTAMP NULL, PRIMARY KEY (`id`) ) $charsetCollate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); } } /** * @param $hash */ private function getSavedLink($hash) { $postData = $this->app->request->get(); $sourceUrl = sanitize_url($postData['source_url']); $slug = 'fluent_state'; if (strpos($sourceUrl, '?') !== false) { $sourceUrl .= '&'; } else { $sourceUrl .= '?'; } $pattern = "/(?<={$slug}=).*$/"; preg_match($pattern, $sourceUrl, $match); if (!empty($match)) { return str_replace($match[0], base64_encode($hash), $sourceUrl); } return $sourceUrl . "{$slug}=" . base64_encode($hash); } public function maybeLoadSavedProgress() { $key = isset($_GET['fluent_state']) ? sanitize_text_field($_GET['fluent_state']) : false; if (!$key) { return; } $key = base64_decode($key); $draftForm = \FluentFormPro\classes\DraftSubmissionsManager::get($key); if (!$draftForm) { return; } add_action('wp_enqueue_scripts', function () use ($key) { $vars = apply_filters('fluentform/save_progress_vars', [ 'source_url' => home_url($_SERVER['REQUEST_URI']), 'key' => $key, 'nonce' => wp_create_nonce(), 'copy_button' => sprintf("", fluentFormMix('img/copy.svg')), 'copy_success_button' => sprintf("", fluentFormMix('img/check.svg')), 'email_button' => sprintf("", fluentFormMix('img/email.svg')), ]); wp_localize_script('form-save-progress', 'form_state_save_vars', $vars); }); } public function emailProgressLink() { $this->verify(); $requestData = $this->app->request->get(); $hash = $requestData['hash']; $formId = intval($requestData['form_id']); $toEmail = trim($requestData['to_email']); if (!is_email($toEmail)) { wp_send_json_error([ 'Error' => __('Please provide a valid email address','fluentformpro') ], 423); } $link = $requestData['link']; $form = wpFluent()->table('fluentform_forms')->find($formId); $settings = FormFieldsParser::getElement($form, ['save_progress_button'], ['raw']); if (empty($settings) || !is_array($settings)) { wp_send_json_error([ 'Error' => __('Element Not Found.Please check again!', 'fluentformpro') ], 423); } $settings = array_pop($settings); $entry = $this->get($hash, $formId); if (!$entry && $userId = get_current_user_id()) { $entry = wpFluent()->table(static::$tableName) ->where('user_id', $userId) ->where('form_id', $formId) ->first(); } $submittedData = null; if ($entry) { $submittedData['step_completed'] = (int)$entry->step_completed; $submittedData['response'] = json_decode($entry->response, true); unset( $submittedData['response']['_wp_http_referer'], $submittedData['response']['__fluent_form_embded_post_id'], $submittedData['response']['_fluentform_' . $entry->form_id . '_fluentformnonce'] ); } $emailFormat = $this->processEmail($settings, $form, $link, $toEmail); $emailFormat = apply_filters_deprecated( 'fluentform_email_form_resume_link_config', [ $emailFormat, $submittedData, $requestData, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/email_form_resume_link_config', 'Use fluentform/email_form_resume_link_config instead of fluentform_email_form_resume_link_config.' ); $emailFormat = apply_filters('fluentform/email_form_resume_link_config', $emailFormat, $submittedData, $requestData, $form); do_action_deprecated( 'fluentform_email_form_resume_link_before_sent', [ $emailFormat, $submittedData, $requestData, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/email_form_resume_link_before_sent', 'Use fluentform/email_form_resume_link_before_sent instead of fluentform_email_form_resume_link_before_sent.' ); do_action('fluentform/email_form_resume_link_before_sent', $emailFormat, $submittedData, $requestData, $form); $notifier = $this->app->make( 'FluentForm\App\Services\FormBuilder\Notifications\EmailNotification' ); $notify = $notifier->notify($emailFormat, $submittedData, $form); if ($notify) { $message = sprintf(__('Email Successfully Sent to %s', 'fluentformpro'),$toEmail); $message = apply_filters_deprecated( 'fluentform_email_resume_link_response', [ $message ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/email_resume_link_response', 'Use fluentform/email_resume_link_response instead of fluentform_email_resume_link_response.' ); wp_send_json_success([ 'response' => apply_filters('fluentform/email_resume_link_response', $message) ]); } wp_send_json_error([ 'Error' => __('Error Occurred while sending email', 'fluentformpro') ], 423); } private function deleteSavedStateDraft($form, $formData) { if (!isset($formData['__fluent_state_hash'])) { return; } $hash = sanitize_text_field($formData['__fluent_state_hash']); ob_start(); $draft = $this->get($hash, $form->id); if ($draft) { wpFluent()->table(static::$tableName) ->where('hash', $hash) ->delete(); ob_get_clean(); do_action_deprecated( 'fluentform_saved_progress_submission_deleted', [ $draft, $form->id ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/saved_progress_submission_deleted', 'Use fluentform/saved_progress_submission_deleted instead of fluentform_saved_progress_submission_deleted.' ); do_action('fluentform/saved_progress_submission_deleted', $draft, $form->id); } } private function deleteStepFormDraft($form) { if ( Helper::getFormMeta($form->id, 'step_data_persistency_status') != 'yes' && !Helper::getFormMeta($form->id, 'conv_form_per_step_save', false) ) { return; } if ($hash = Arr::get($_COOKIE, $this->getCookieName($form->id))) { $draft = $this->get($hash, $form->id); if ($draft) { ob_start(); wpFluent()->table(static::$tableName) ->where('id', $draft->id) ->delete(); wpFluent()->table('fluentform_logs') ->where('parent_source_id', $form->id) ->where('source_id', $draft->id) ->where('source_type', 'draft_submission_meta') ->delete(); $this->deleteCookie($form->id); $errors = ob_get_clean(); do_action_deprecated( 'fluentform_partial_submission_deleted', [ $draft, $form->id ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/partial_submission_step_completed', 'Use fluentform/partial_submission_step_completed instead of fluentform_partial_submission_deleted.' ); do_action('fluentform/partial_submission_deleted', $draft, $form->id); } } if ($userId = get_current_user_id()) { wpFluent()->table(static::$tableName) ->where('user_id', $userId) ->where('form_id', $form->id) ->delete(); } } private function processEmail($settings, $form, $link, $toEmail) { $emailSubject = Arr::get($settings, 'raw.settings.email_subject'); $emailBody = Arr::get($settings, 'raw.settings.email_body', '

    Hi there,

    Please Continue To Your Submission Process of the Form by clicking on the link below.

    {email_resume_link}

    Thanks

    '); if (false !== strpos($emailSubject, '{form_name}')) { $emailSubject = str_replace('{form_name}', $form->title, $emailSubject); } if (false !== strpos($emailBody, '{email_resume_link}')) { $emailBody = str_replace('{email_resume_link}', $link, $emailBody); $emailBody = apply_filters_deprecated( 'fluentform_email_resume_link_body', [ $emailBody, $form, $link ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/email_resume_link_body', 'Use fluentform/email_resume_link_body instead of fluentform_email_resume_link_body.' ); $emailBody = apply_filters('fluentform/email_resume_link_body', $emailBody, $form, $link); } if (false !== strpos($emailBody, '{form_name}')) { $emailBody = str_replace('{form_name}', $form->title, $emailBody); } return [ 'fromEmail' => get_option('admin_email'), 'fromName' => get_bloginfo(), 'asPlainText' => 'no', 'message' => $emailBody, 'replyTo' => get_option('admin_email'), 'subject' => $emailSubject, 'sendTo' => [ 'email' => $toEmail, ] ]; } private function getSaveProgressButtonData($formId) { $form = wpFluent()->table('fluentform_forms')->find($formId); $settings = FormFieldsParser::getElement($form, ['save_progress_button'], ['raw']); if (empty($settings) || !is_array($settings)) { return false; } return array_pop($settings); } private function verify() { $nonce = $this->app->request->get('nonce'); if (!wp_verify_nonce($nonce)) { $nonceMessage = __('Nonce verification failed, please try again.', 'fluentform'); $nonceMessage = apply_filters_deprecated( 'fluentform_nonce_error', [ $nonceMessage ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/nonce_error', 'Use fluentform/nonce_error instead of fluentform_nonce_error.' ); $message = apply_filters('fluentform/nonce_error', $nonceMessage); wp_send_json_error([ 'message' => $message, ], 422); } } } PK! r "src/classes/ConditionalContent.phpnu[ '', 'is' => '', 'to' => '' ]; $default = apply_filters_deprecated( 'fluentform_conditional_shortcode_defaults', [ $default, $atts ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/conditional_shortcode_defaults', 'Use fluentform/conditional_shortcode_defaults instead of fluentform_conditional_shortcode_defaults.' ); $shortcodeDefaults = apply_filters('fluentform/conditional_shortcode_defaults', $default, $atts); extract(shortcode_atts($shortcodeDefaults, $atts)); if(!$field || !$is || !isset($to)) { return ''; } $operatorMaps = [ 'equal' => '=', 'not_equal' => '!=', 'greater_than' => '>', 'less_than' => '<', 'greater_or_equal' => '>=', 'less_or_equal' => '<=', 'starts_with' => 'startsWith', 'ends_with' => 'endsWith', 'contains' => 'contains', 'not_contains' => 'doNotContains' ]; if(!isset($operatorMaps[$is])) { return ''; } $is = $operatorMaps[$is]; $condition = [ 'conditionals' => [ 'status' => true, 'type' => 'any', 'conditions' => [ [ "field" => $field, "operator" => $is, "value" => $to ] ] ] ]; if (\FluentForm\App\Services\ConditionAssesor::evaluate($condition, static::$formData)) { return do_shortcode($content); } return ''; } public static function initiate($content, $entryId, $formData, $form) { if(!has_shortcode($content, 'ff_if') || !$content) { return $content; } static::$entryId = $entryId; static::$formData = $formData; static::$form = $form; return do_shortcode($content); } } PK!f__)src/views/receipt/transaction_details.phpnu[
    $transaction, 'transactionTotal' => $transactionTotal ]); echo \FluentFormPro\Payments\PaymentHelper::loadView('order_items_table', [ 'items' => $items, 'discount_items' => $discountItems, 'subTotal' => $subTotal, 'orderTotal' => $orderTotal ]); echo \FluentFormPro\Payments\PaymentHelper::loadView('customer_details', [ 'transaction' => $transaction ]); echo \FluentFormPro\Payments\PaymentHelper::loadView('custom_css', []); ?>
    PK!F x .src/views/receipt/user_subscriptions_table.phpnu[
    #id; ?> title; ?>
    plan_name; ?> (item_name ?>)
    formatted_recurring_amount; ?> /billing_interval; ?> status; ?> billing_text): ?>

    billing_text; ?>

    starting_date_formated; ?>

    can_cancel): ?>
    can_cancel): ?>
    PK!src/views/receipt/header.phpnu[
    PK! g)src/views/receipt/subscriptions_table.phpnu[
    plan_name . ' (' . $subscription->item_name . ')'; ?> original_plan): ?>

    original_plan, $subscription->form_id, $submission->currency, false); ?>

    status); ?>
    PK!kL src/views/receipt/custom_css.phpnu[PK!#ss&src/views/receipt/customer_details.phpnu[payer_name || $transaction->payer_email) : ?>

      payer_name): ?>
    • payer_name; ?>
    • payer_email): ?>
    • payer_email; ?>
    • billing_address && strlen($transaction->billing_address) > 2): ?>
    • billing_address; ?>
    • shipping_address && strlen($transaction->shipping_address) > 2): ?>
    • shipping_address; ?>
    PK! 9&src/views/receipt/transaction_info.phpnu[
    #id; ?>
    created_at)); ?>
    payment_method): ?>
    payment_method; $method = apply_filters_deprecated( 'fluentform_payment_method_public_name_' . $method, [ $method ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/payment_method_public_name_' . $method, 'Use fluentform/payment_method_public_name_' . $method . ' instead of fluentform_payment_method_public_name_' . $method ); echo ucfirst( apply_filters( 'fluentform/payment_method_public_name_' . $method, $method ) ); ?>
    status): ?>
    status); ?>
    PK!XXX0src/views/receipt/user_subscription_payments.phpnu[
    view_url): ?>
    formatted_amount; ?> currency) ?> status; ?> formatted_date; ?>
    PK!src/views/receipt/index.phpnu[
    #id; ?>
    created_at)); ?>
    payment_method; if($paymentMethod): ?>
    payment_status): $allStatus = \FluentFormPro\Payments\PaymentHelper::getPaymentStatuses(); if (isset($allStatus[$submission->payment_status])) { $submission->payment_status = $allStatus[$submission->payment_status]; } ?>
    payment_status; ?>
    PK!g'src/views/receipt/payment_info_list.phpnu[
    • payment_method; if($paymentMethod): ?>
    • payment_status): $allStatus = \FluentFormPro\Payments\PaymentHelper::getPaymentStatuses(); if (isset($allStatus[$submission->payment_status])) { $submission->payment_status = $allStatus[$submission->payment_status]; } ?>
    • payment_status; ?>
    PK![(src/views/receipt/transactions_table.phpnu[
    #id;?> formatted_amount; ?> status); ?> payment_method); ?> formatted_date; ?>
    PK!K2}II'src/views/receipt/order_items_table.phpnu[
    item_name; ?> quantity; ?> formatted_item_price; ?> formatted_line_total; ?>
    item_name; ?> -formatted_line_total; ?>
    PK!k k src/views/frameless_view.phpnu[ >
    PK!cJsrc/views/landing_page_view.phpnu[ >

    0) { $brightnessCss .= 'contrast(' . ((100 - $brightness) / 100) . ') '; } $brightnessCss .= ' brightness(' . (1 + $brightness / 100) . ')'; $layout = isset($settings['layout']) ? $settings['layout'] : 'default'; ?>
    <?php echo  $settings['alt_text'] ;?>
    PK!Usrc/views/analytics_view.phpnu[
    PK!=~~src/views/inventory_list.phpnu[
    PK!'ݙyysrc/views/step_form_entries.phpnu[
    PK!T src/index.phpnu[request->get('formId')); $this->formData = $this->request->all(); if ($formId) { $this->setForm($formId); $this->validateNonce(); if ($this->form) { // Get the HTTP files. It'll be an array with always one item. $files = $this->request->files(); do_action_deprecated( 'fluentform_starting_file_upload', [ $files, $this->form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/starting_file_upload', 'Use fluentform/starting_file_upload instead of fluentform_starting_file_upload.' ); do_action('fluentform/starting_file_upload', $files, $this->form); // Get the form attribute name then. $arrayKeys = array_keys($files); $attribute = array_pop($arrayKeys); // Get the specific form field by using the element type and it's attribute name. $field = FormFieldsParser::getField( $this->form, ['input_file', 'input_image', 'featured_image'], $attribute, ['rules', 'settings'] ); if ($field) { // Extract the validation rules & messages for file upload element. list($rules, $messages) = FormFieldsParser::getValidations( $this->form, $files, $field ); /** * Delegate 'max_file_size', 'allowed_file_types' rules & messages to * 'max', 'mimes' since the validation library doesn't recognise those */ list($rules, $messages) = $this->delegateValidations($rules, $messages); $delegateValidations = apply_filters_deprecated( 'fluentform_file_upload_validations', [ [$rules, $messages], $this->form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/file_upload_validations', 'Use fluentform/file_upload_validations instead of fluentform_file_upload_validations.' ); // Fire an event so that one can hook into it to work with the rules & messages. $validations = $this->app->applyFilters( 'fluentform/file_upload_validations', $delegateValidations, $this->form ); $validator = fluentValidator( $files, $validations[0], $validations[1] ); if ($validator->validate()->fails()) { $errors = $validator->errors(); $errors = apply_filters_deprecated( 'fluentform_file_upload_validation_error', [ $errors, $this->form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/file_upload_validation_error', 'Use fluentform/file_upload_validation_error instead of fluentform_file_upload_validation_error.' ); // Fire an event so that one can hook into it to work with the errors. $errors = $this->app->applyFilters( 'fluentform/file_upload_validation_error', $errors, $this->form ); wp_send_json([ 'errors' => $errors ], 422); } // let's upload to a temp location $field = current($field); //add default upload location for old inputs if (!$uploadLocation = ArrayHelper::get($field, 'settings.upload_file_location')) { $uploadLocation = 'default'; } $uploadedFiles = []; if (!empty($uploadLocation)) { $this->overrideUploadDir(); $uploadedFiles = $this->uploadToTemp($files, $field); } wp_send_json_success([ 'files' => $uploadedFiles ], 200); } } } } /** * Uploads files to its target locations * @return void */ public function processFiles() { $fileTypes = ['input_file', 'input_image', 'featured_image']; foreach ($fileTypes as $fileType) { add_filter('fluentform/input_data_' . $fileType, function ($files, $field, $formData, $form) { if (!$this->form) { $this->setForm($form->id); } $uploadLocation = $this->getUploadLocation($field); $files = is_array($files) ? $files : [$files]; $files = $this->maybeDecrypt($files); do_action_deprecated( 'fluentform_starting_file_processing', [ $files, $uploadLocation, $formData, $form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/starting_file_processing', 'Use fluentform/starting_file_processing instead of fluentform_starting_file_processing.' ); do_action('fluentform/starting_file_processing', $files, $uploadLocation, $formData, $form); $this->initUploads($files, $uploadLocation); $formattedFiles = []; foreach ($files as $file) { $formattedFiles[] = $this->getProcessedUrl($file, $uploadLocation); } return $formattedFiles; }, 10, 4); } } /** * Register filters for custom upload dir */ public function overrideUploadDir() { add_filter('wp_handle_upload_prefilter', function ($file) { add_filter('upload_dir', [$this, 'setCustomUploadDir']); add_filter('wp_handle_upload', function ($fileinfo) { remove_filter('upload_dir', [$this, 'setCustomUploadDir']); $fileinfo['file'] = basename($fileinfo['file']); return $fileinfo; }); return $this->renameFileName($file); }); } /** * Set plugin's custom upload dir * @param array $param * @return array $param */ public function setCustomUploadDir($param) { $param['url'] = $param['baseurl'] . FLUENTFORM_UPLOAD_DIR . '/temp'; $param['path'] = $param['basedir'] . FLUENTFORM_UPLOAD_DIR . '/temp'; $param = apply_filters_deprecated( 'fluentform_file_upload_params', [ $param, $this->formData, $this->form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/file_upload_params', 'Use fluentform/file_upload_params instead of fluentform_file_upload_params.' ); $param = apply_filters('fluentform/file_upload_params', $param, $this->formData, $this->form); $this->secureDirectory($param['path']); return $param; } /** * Rename the uploaded file name before saving * @param array $file * @return array $file */ public function renameFileName($file) { $originalFileArray = $file; $prefix = 'ff-' . md5(uniqid(rand())) . '-ff-'; $file['name'] = $prefix . $file['name']; $file = apply_filters_deprecated( 'fluentform_uploaded_file_name', [ $file, $originalFileArray, $this->formData, $this->form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/uploaded_file_name', 'Use fluentform/uploaded_file_name instead of fluentform_uploaded_file_name.' ); return apply_filters('fluentform/uploaded_file_name', $file, $originalFileArray, $this->formData, $this->form); } /** * Prepare the validation rules & messages specific to * file type inputs when actual form is submitted. * * @param $validations * @param $form \stdClass * @return array */ public function prepareValidations($validations, $form) { $element = FormFieldsParser::getElement($form, ['input_file', 'input_image']); if (count($element)) { // Delegate the `max_file_count` validation to `max` $validations = $this->delegateValidations( $validations[0], $validations[1], ['max_file_count'], ['max'] ); } return $validations; } /** * Process uploads from temp directory location to its final location * * @param $formData * @param $form * @return void */ public function initUploads($files, $uploadLocation) { if (empty($files)) { return; } if ($uploadLocation == 'wp_media') { $this->copyToWpMedia($files); } elseif ($uploadLocation == 'default') { $this->copyToDefault($files); } self::removeOldTempFiles(); } /** * Copy files to default location * * @param array $files */ protected function copyToDefault($files) { $uploadedFiles = []; $wpUploadDir = wp_upload_dir(); foreach ($files as $file) { $fileInfo = pathinfo($file); $filename = $fileInfo['basename']; $filePath = $wpUploadDir['basedir'] . FLUENTFORM_UPLOAD_DIR; $tempFilePath = $filePath . '/temp/' . $filename; $filePath = apply_filters_deprecated( 'fluentform_default_upload_path', [ $filePath, $this->form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/default_upload_path', 'Use fluentform/default_upload_path instead of fluentform_default_upload_path.' ); $destinationFilePath = apply_filters('fluentform/default_upload_path', $filePath, $this->form); $this->secureDirectory($filePath); $destinationFilePath = trailingslashit($destinationFilePath) . $filename; self::copyFile($tempFilePath, $destinationFilePath); } return $uploadedFiles; } /** * Copy files to WordPress Media * * @param $files * @return void */ public function copyToWpMedia($files) { $uploadedFiles = []; $wpUploadDir = wp_upload_dir(); foreach ($files as $file) { $fileInfo = pathinfo($file); $filename = $fileInfo['basename']; $tempFilePath = $wpUploadDir['basedir'] . FLUENTFORM_UPLOAD_DIR . '/temp/' . $filename; $destinationFilePath = $wpUploadDir['path'] . '/' . $filename; $mimeType = wp_check_filetype($tempFilePath); //Copy this file into the wp uploads dir $move = self::copyFile($tempFilePath, $destinationFilePath); if (!$move) { continue; } $destinationFileFileUrl = $wpUploadDir['url'] . '/' . $filename; $uploadId = wp_insert_attachment( [ 'guid' => $destinationFileFileUrl, 'post_mime_type' => $mimeType['type'], 'post_title' => preg_replace('/\.[^.]+$/', '', $filename), 'post_content' => '', 'post_status' => 'inherit', ], $destinationFilePath ); // wp_generate_attachment_metadata() needs this file. require_once ABSPATH . 'wp-admin/includes/image.php'; if (!is_wp_error($uploadId)) { wp_update_attachment_metadata( $uploadId, wp_generate_attachment_metadata($uploadId, $destinationFilePath) ); } } } /** * Upload files to temp directory * * @param array $files * @param array $field * @return array */ private function uploadToTemp($files, $field) { $uploadedFiles = []; foreach ($files as $file) { /** * @var $file \FluentForm\Framework\Request\File */ $filesArray = $file->toArray(); $args = [ 'test_form' => false ]; $args = apply_filters_deprecated( 'fluentform_uploader_args', [ $args, $filesArray, $this->form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/uploader_args', 'Use fluentform/uploader_args instead of fluentform_uploader_args.' ); $uploaderArgs = apply_filters('fluentform/uploader_args', $args, $filesArray, $this->form); $uploadFile = wp_handle_upload( $filesArray, $uploaderArgs ); if ($error = ArrayHelper::get($uploadFile, 'error')) { wp_send_json([ 'errors' => [ 'error' => $error ] ], 422); } $file = ArrayHelper::get($uploadFile, 'file'); if ($file) { $uploadFile['file'] = \FluentForm\App\Helpers\Protector::encrypt($file); $uploadFile['url'] = str_replace($file, $uploadFile['file'], $uploadFile['url']); $uploadFile = apply_filters_deprecated( 'fluent_file_uploaded', [ $uploadFile, $this->formData, $this->form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/file_uploaded', 'Use fluentform/file_uploaded instead of fluent_file_uploaded.' ); $uploadedFiles[] = apply_filters('fluentform/file_uploaded', $uploadFile, $this->formData, $this->form); } } return $uploadedFiles; } private static function copyFile($fromPath = null, $toPath = null) { $status = false; if (isset($fromPath) and file_exists($fromPath)) { //if destination dir exists if not make it if (!file_exists(dirname($toPath))) { mkdir(dirname($toPath)); } if (file_exists(dirname($toPath))) { //Move file into dir if (copy($fromPath, $toPath)) { if (file_exists($toPath)) { $status = true; } } } } return $status; } /** * Get File url after processing uploads * * @param $file * @param $uploadLocations * @return string|void */ public function getProcessedUrl($file, $location) { $wpUploadDir = wp_upload_dir(); $fileInfo = pathinfo($file); $filename = $fileInfo['basename']; $filePath = $wpUploadDir['baseurl'] . FLUENTFORM_UPLOAD_DIR; if ($location == 'wp_media') { $fileUrl = $wpUploadDir['url'] . '/' . $filename; } elseif ($location == 'default') { $filePath = apply_filters_deprecated( 'fluentform_default_file_upload_url', [ $filePath, $this->form ], FLUENTFORM_FRAMEWORK_UPGRADE, 'fluentform/default_file_upload_url', 'Use fluentform/default_file_upload_url instead of fluentform_default_file_upload_url.' ); $fileUrl = apply_filters('fluentform/default_file_upload_url', $filePath, $this->form); $fileUrl = trailingslashit($fileUrl) .$filename; } else { //if not location found store temp file url for other file uploader $fileUrl = $filePath . '/temp/' . $filename; } return $fileUrl; } /** * Cleanup temp Directory * * @param $files * @return void */ private static function removeOldTempFiles() { $maxFileAge = apply_filters('fluentform/temp_file_delete_time', 2 * 3600); $wpUploadDir = wp_upload_dir(); $tempDir = $wpUploadDir['basedir'] . FLUENTFORM_UPLOAD_DIR . '/temp/'; // Remove old temp files if (is_dir($tempDir) and ($dir = opendir($tempDir))) { while (($file = readdir($dir)) !== false) { $tempFilePath = $tempDir . DIRECTORY_SEPARATOR . $file; if ((filemtime($tempFilePath) < time() - $maxFileAge)) { @unlink($tempFilePath); } } closedir($dir); } } /** * Adds htaccess file to directory * @param $path * @return void */ private function secureDirectory($path) { if (!is_dir($path)) { mkdir($path, 0755); file_put_contents( $path . '/.htaccess', file_get_contents(__DIR__ . '/Stubs/htaccess.stub') ); file_put_contents( $path . '/index.php', file_get_contents(__DIR__ . '/Stubs/index.stub') ); } /* * @todo: Rempve this block after November 2023 */ if(!file_exists($path . '/index.php')) { file_put_contents( $path . '/index.php', file_get_contents(__DIR__ . '/Stubs/index.stub') ); } } /** * Maybe Decrypt file names * * @param $files * @return array */ private function maybeDecrypt($files) { $decrypted = []; foreach ($files as $file) { $decrypted[] = \FluentForm\App\Helpers\Helper::maybeDecryptUrl($file); } return $decrypted; } public function deleteFile() { if (!empty($file_name = $this->request->get('path'))) { if (!empty($this->request->get('attachment_id')) && wp_delete_attachment( $this->request->get('attachment_id') )) { wp_die(); } else { $file_name = \FluentForm\App\Helpers\Protector::decrypt($file_name); wp_die(@unlink(wp_upload_dir()['basedir'] . FLUENTFORM_UPLOAD_DIR . '/temp/' . $file_name)); } } } /** * @param $upload_file_location * @return mixed */ public function getUploadLocation($field) { if (!$locationType = ArrayHelper::get($field, 'raw.settings.file_location_type')) { $locationType = 'follow_global_settings'; } if ($locationType == 'follow_global_settings') { $settings = get_option('_fluentform_global_form_settings', false); $location = ArrayHelper::get($settings, 'misc.file_upload_locations'); } else { $location = ArrayHelper::get($field, 'raw.settings.upload_file_location'); } if (empty($location)) { $location = 'default'; } return $location; } } PK!c$zjzjfluentformpro.phpnu[injectDependency(); return; } if (!defined('FLUENTFORM_FRAMEWORK_UPGRADE')) { $message = '

    ' . __('Fluent Forms Pro is not working. Update required.

    Fluent Forms Pro requires the latest version of the Fluent Forms Core Plugin.', 'fluentformpro') . '' . __('Please update Fluent Forms to latest version', 'fluentformpro') . '.

    '; $actions = [ 'fluentform/global_menu', 'fluentform/after_form_menu', 'admin_notices' ]; foreach ($actions as $action) { add_action($action, function () use ($message) { printf('
    %1$s
    ', $message); }); } return; } if (function_exists('wpFluentForm')) { $this->registerHooks(wpFluentForm()); } } protected function registerHooks($fluentForm) { $this->ajaxHooks($fluentForm); $this->adminHooks($fluentForm); $this->publicHooks($fluentForm); $this->commonHooks($fluentForm); $this->registerAddOns($fluentForm); add_action('wp_enqueue_scripts', array($this, 'registerScripts'), 999); new \FluentFormPro\Components\PhoneField(); new \FluentFormPro\Components\RangeSliderField(); new \FluentFormPro\Components\NetPromoterScore(); new \FluentFormPro\Components\ChainedSelect\ChainedSelect(); new \FluentFormPro\Components\ColorPicker(); new \FluentFormPro\Components\RepeaterField(); new \FluentFormPro\Components\PostSelectionField(); new \FluentFormPro\Components\Post\Components\PostContent('rich_text_input', 'Rich Text Input', ['content', 'rich', 'html'], 'advanced'); new \FluentFormPro\Components\SaveProgressButton(); /* * Complience Settings here */ add_action('fluentform/global_notify_completed', function ($entryId, $form) { if (\FluentForm\App\Helpers\Helper::isEntryAutoDeleteEnabled($form->id)) { $entriesService = new \FluentForm\App\Services\Submission\SubmissionService(); $entriesService->deleteEntries($entryId, $form->id); } }, 10, 2); /* * Form Styler */ (new \FluentFormPro\classes\FormStyler)->boot(); /* * Form Landing Pages */ (new \FluentFormPro\classes\SharePage\SharePage)->boot(); /* * Boot Payment Module */ (new \FluentFormPro\Payments\PaymentHandler)->init(); /* * Address AutoComplete */ (new \FluentFormPro\classes\AddressAutoComplete())->init(); if (defined('BP_VERSION')) { (new \FluentFormPro\Integrations\BuddyIntegration\FluentFormBuddyBoss())->init(); } /* * Quiz Module */ (new \FluentFormPro\classes\Quiz\QuizController())->init($fluentForm); /* * Inventory Settings Module */ (new \FluentFormPro\classes\Inventory\InventoryController())->boot(); /* * Chat Field Manager Module * Need more improvement */ (new \FluentFormPro\classes\Chat\ChatFieldController($fluentForm)); /* * Entries Import Module */ (new \FluentFormPro\classes\EntriesImport\EntriesImportController())->boot(); } /** * Notify the user about the FluentForm dependency and instructs to install it. */ protected function injectDependency() { add_action('admin_notices', function () { $pluginInfo = $this->getFluentFormInstallationDetails(); $class = 'notice notice-error'; $install_url_text = __('Click Here to Install the Plugin', 'fluentformpro'); if ($pluginInfo->action == 'activate') { $install_url_text = __('Click Here to Activate the Plugin', 'fluentformpro'); } $message = __('FluentForm PRO Add-On Requires FluentForm Base Plugin, ', 'fluentformpro') . '' . $install_url_text . ''; printf('

    %2$s

    ', esc_attr($class), $message); }); } /** * Get the FluentForm plugin installation information e.g. the URL to install. * * @return \stdClass $activation */ protected function getFluentFormInstallationDetails() { $activation = (object)[ 'action' => 'install', 'url' => '' ]; $allPlugins = get_plugins(); if (isset($allPlugins['fluentform/fluentform.php'])) { $url = wp_nonce_url( self_admin_url('plugins.php?action=activate&plugin=fluentform/fluentform.php'), 'activate-plugin_fluentform/fluentform.php' ); $activation->action = 'activate'; } else { $api = (object)[ 'slug' => 'fluentform' ]; $url = wp_nonce_url( self_admin_url('update.php?action=install-plugin&plugin=' . $api->slug), 'install-plugin_' . $api->slug ); } $activation->url = $url; return $activation; } /** * Register admin/backend hooks * @return void */ public function adminHooks($app) { add_filter('fluentform/disabled_components', [$this, 'filterDisabledComponents']); add_action('wp_ajax_fluentform_update_entry', function () { $formId = intval($_REQUEST['form_id']); \FluentForm\App\Modules\Acl\Acl::verify('fluentform_entries_viewer', $formId); \FluentFormPro\classes\EntryEditor::editEntry(); }); (new \FluentFormPro\classes\ResendNotificationHandler())->init(); (new \FluentFormPro\classes\FailedIntegrationNotification())->init(); (new \FluentFormPro\Uploader($app))->processFiles(); \FluentFormPro\classes\StepFormEntries::boot($app); if (defined('AFFILIATEWP_VERSION')){ (new \FluentFormPro\Integrations\AffiliateWP\AffiliateWPFF())->boot(); } /** * Field selection for slack */ add_filter('fluentform/slack_field_label_selection', function ($labels, $settings) { if (FluentForm\Framework\Helpers\ArrayHelper::exists($settings, 'fields')) { $selectedFields = FluentForm\Framework\Helpers\ArrayHelper::get($settings, 'fields'); $labels = array_intersect($labels, $selectedFields); } return $labels; }, 10, 2); } /** * Register public/frontend hooks * @return void */ public function publicHooks($app) { $this->registerProElementsRenderingHook($app); } /** * Registers common hooks. */ public function commonHooks($app) { $app->addfilter('fluentform/validations', function ($validations, $form) use ($app) { return (new \FluentFormPro\Uploader($app))->prepareValidations($validations, $form); }, 10, 2); // Filter other confirmations for form submission response $app->addFilter('fluentform/form_submission_confirmation', function ($confirmation, $data, $form) { $confirmations = wpFluent()->table('fluentform_form_meta') ->where('form_id', $form->id) ->where('meta_key', 'confirmations') ->get(); foreach ($confirmations as $item) { $item->value = json_decode($item->value, true); if ($item->value['active']) { if (\FluentForm\App\Services\ConditionAssesor::evaluate($item->value, $data)) { return $item->value; } } } return $confirmation; }, 10, 3); add_filter('fluentform/email_template_footer_credit', '__return_empty_string'); add_shortcode('fluentform_modal', function ($atts) { $shortcodeDefaults = apply_filters_deprecated( 'fluentform_popup_shortcode_defaults', [ [ 'form_id' => null, 'btn_text' => 'Contact Me', 'css_class' => 'btn btn-success', 'bg_color' => 'white' ], $atts ], 'fluentform/popup_shortcode_defaults', 'Use fluentform/popup_shortcode_defaults instead of fluentform_popup_shortcode_defaults.' ); $shortcodeDefaults = apply_filters('fluentform/popup_shortcode_defaults', $shortcodeDefaults, $atts); $atts = shortcode_atts($shortcodeDefaults, $atts); if (empty($atts['form_id'])) { return; } return \FluentFormPro\classes\FormModal::renderModal($atts); }); add_shortcode('fluentform_survey', function ($atts) { $shortcodeDefaults = apply_filters_deprecated( 'fluentform_survey_shortcode_defaults', [ [ 'form_id' => null, 'field_name' => '', 'label' => 'yes', 'counts' => 'yes' ], $atts ], 'fluentform/survey_shortcode_defaults', 'Use fluentform/survey_shortcode_defaults instead of fluentform_survey_shortcode_defaults.' ); $shortcodeDefaults = apply_filters('fluentform/survey_shortcode_defaults', $shortcodeDefaults, $atts); $atts = shortcode_atts($shortcodeDefaults, $atts); return (new \FluentFormPro\classes\SurveyResultProcessor())->getSurveyResultHtml($atts); }); add_filter('fluentform/submission_message_parse', array('FluentFormPro\classes\ConditionalContent', 'initiate'), 10, 4); add_shortcode('ff_if', array('FluentFormPro\classes\ConditionalContent', 'handle')); add_shortcode('ff_sub_if', array('FluentFormPro\classes\ConditionalContent', 'handle')); add_action('fluentform/rendering_calculation_form', function ($form, $element) { (new \FluentFormPro\classes\Calculation())->enqueueScripts(); }, 10, 2); // Hook into the `fluentform_submission_confirmation` before returning the data // so that if append survey result is enabled we could display survey result. add_filter('fluentform/submission_confirmation', function ($data, $form) { if (isset($form->settings['appendSurveyResult']) && $form->settings['appendSurveyResult']['enabled']) { $data['message'] .= (new \FluentFormPro\classes\SurveyResultProcessor())->getSurveyResultHtml([ 'form_id' => $form->id, 'field_name' => '', 'label' => $form->settings['appendSurveyResult']['showLabel'] ? 'yes' : false, 'counts' => $form->settings['appendSurveyResult']['showCount'] ? 'yes' : false, ]); } return $data; }, 10, 2); \FluentFormPro\Components\Post\Bootstrap::boot(); \FluentFormPro\classes\DraftSubmissionsManager::boot($app); add_filter('fluentform/validation_errors', function ($errors, $data, $form, $fields) { return (new \FluentFormPro\classes\AdvancedFormValidation())->validateAdvancedConditions($errors, $data, $form, $fields); }, 10, 4); (new \FluentFormPro\classes\ProSmartCodes())->register(); (new \FluentFormPro\classes\DoubleOptin())->init(); (new \FluentFormPro\classes\AdminApproval\AdminApproval())->init(); /** * Post Type Selections for Post Form */ add_filter('fluentform/all_forms_vars', function ($vars) { $postSettings = new \FluentFormPro\Components\Post\PostFeedSettings; if (!isset($vars['post_types'])) { $vars['post_types'] = $postSettings->getPostTypes(); } return $vars; }, 10, 1); } /** * Registers ajax hooks. */ public function ajaxHooks($app) { $app->addAdminAjaxAction('fluentform_file_upload', function () use ($app) { (new \FluentFormPro\Uploader($app))->upload(); }); $app->addPublicAjaxAction('fluentform_file_upload', function () use ($app) { (new \FluentFormPro\Uploader($app))->upload(); }); $app->addPublicAjaxAction('fluentform_delete_uploaded_file', function () use ($app) { (new \FluentFormPro\Uploader($app))->deleteFile(); }); $app->addAdminAjaxAction('fluentform_delete_uploaded_file', function () use ($app) { (new \FluentFormPro\Uploader($app))->deleteFile(); }); // Post Form Creation Ajax Hook On Backend $app->addAdminAjaxAction('fluentform_get_post_settings', function () { \FluentForm\App\Modules\Acl\Acl::verify('fluentform_settings_manager'); $postSettings = new \FluentFormPro\Components\Post\PostFeedSettings; wp_send_json_success($postSettings->getPostSettings()); }); // Chained Select Ajax Hook On Backend $app->addAdminAjaxAction('fluentform_chained_select_file_upload', function () use ($app) { require_once(__DIR__ . '/libs/CSVParser/CSVParser.php'); $cs = new \FluentFormPro\Components\ChainedSelect\ChainedSelectDataSourceManager( $app ); $cs->saveDataSource(new CSVParser); }); // Chained Select Ajax Hook On Backend $app->addAdminAjaxAction('fluentform_chained_select_remove_ds', function () use ($app) { $cs = new \FluentFormPro\Components\ChainedSelect\ChainedSelectDataSourceManager( $app ); $cs->deleteDataSource(); }); // Chained Select Ajax Hook On Frontend $getChainedSelectOptions = function () use ($app) { require_once(__DIR__ . '/libs/CSVParser/CSVParser.php'); $cs = new \FluentFormPro\Components\ChainedSelect\ChainedSelectDataSourceManager( $app ); $cs->getOptionsForNextField(new CSVParser); }; $app->addAdminAjaxAction('fluentform_get_chained_select_options', $getChainedSelectOptions); $app->addPublicAjaxAction('fluentform_get_chained_select_options', $getChainedSelectOptions); $app->addPublicAjaxAction('fluentform_get_chained_select_options', $getChainedSelectOptions); $app->addAdminAjaxAction('fluentform_apply_coupon', function () { (new \FluentFormPro\Payments\Classes\CouponController())->validateCoupon(); }); $app->addPublicAjaxAction('fluentform_apply_coupon', function () { (new \FluentFormPro\Payments\Classes\CouponController())->validateCoupon(); }); $app->addAdminAjaxAction('fluentform_paypal_delayed_check', function () use ($app) { (new \FluentFormPro\Payments\PaymentMethods\PayPal\PayPalProcessor())->isPaid(); }); $app->addPublicAjaxAction('fluentform_paypal_delayed_check', function () use ($app) { (new \FluentFormPro\Payments\PaymentMethods\PayPal\PayPalProcessor())->isPaid(); }); } /** * Register pro element's rendering hooks * @return void */ protected function registerProElementsRenderingHook($app) { add_action('fluentform/render_item_input_file', function () { $class = new \FluentFormPro\Components\Uploader; call_user_func_array(array($class, 'compile'), func_get_args()); }, 10, 2); add_action('fluentform/render_item_input_image', function () { $class = new \FluentFormPro\Components\Uploader; call_user_func_array(array($class, 'compile'), func_get_args()); }, 10, 2); add_action('fluentform/render_item_input_repeat', function () { $class = new \FluentFormPro\Components\Repeater; call_user_func_array(array($class, 'compile'), func_get_args()); }, 10, 2); add_action('fluentform/render_item_step_start', function () { $class = new \FluentFormPro\Components\FormStep; call_user_func_array(array($class, 'stepStart'), func_get_args()); }, 10, 2); add_action('fluentform/render_item_form_step', function () { $class = new \FluentFormPro\Components\FormStep; call_user_func_array(array($class, 'compile'), func_get_args()); }, 10, 2); add_action('fluentform/render_item_step_end', function ($data, $form) { $class = new \FluentFormPro\Components\FormStep; call_user_func_array(array($class, 'stepEnd'), [$data, $form]); }, 10, 2); add_action('fluentform/render_item_shortcode', function () { $class = new \FluentFormPro\Components\ShortCode; call_user_func_array(array($class, 'compile'), func_get_args()); }, 10, 2); add_action('fluentform/render_item_action_hook', function () { $class = new \FluentFormPro\Components\ActionHook; call_user_func_array(array($class, 'compile'), func_get_args()); }, 10, 2); } /** * Activate disabled components * * @param array $disabled * * @return array */ public function filterDisabledComponents($disabled) { foreach ($disabled as $key => &$value) { if (in_array($key, $this->proElements)) { $value['disabled'] = false; } } return $disabled; } /** * Register 3rd party Integrations on Form Submit * @return void */ public function registerAddOns($app) { foreach ($this->addOns as $addOn) { $class = "{$addOn}\Bootstrap"; new $class($app); } } public function registerScripts() { $cssSource = FLUENTFORMPRO_DIR_URL . 'public/libs/intl-tel-input/css/intlTelInput.min.css'; if (is_rtl()) { $cssSource = FLUENTFORMPRO_DIR_URL . 'public/libs/intl-tel-input/css/intlTelInput-rtl.min.css'; } wp_register_style('intlTelInput', $cssSource, [], '18.1.1'); wp_register_style('pickr', FLUENTFORMPRO_DIR_URL . 'public/libs/pickr/themes/monolith.min.css', [], '1.5.1'); wp_register_script('intlTelInput', FLUENTFORMPRO_DIR_URL . 'public/libs/intl-tel-input/js/intlTelInput.min.js', [], '18.1.1', true); wp_register_script('intlTelInputUtils', FLUENTFORMPRO_DIR_URL . 'public/libs/intl-tel-input/js/utils.js', [], '18.1.1', true); wp_register_script( 'fluentform-uploader-jquery-ui-widget', FLUENTFORMPRO_DIR_URL . 'public/libs/jQuery-File-Upload-10.32.0/js/vendor/jquery.ui.widget.js', array('jquery'), true, true ); wp_register_script( 'fluentform-uploader-iframe-transport', FLUENTFORMPRO_DIR_URL . 'public/libs/jQuery-File-Upload-10.32.0/js/jquery.iframe-transport.js', array('fluentform-uploader-jquery-ui-widget'), true, true ); wp_register_script( 'fluentform-uploader', FLUENTFORMPRO_DIR_URL . 'public/libs/jQuery-File-Upload-10.32.0/js/jquery.fileupload.js', array('fluentform-uploader-iframe-transport'), true, true ); wp_register_script( 'pickr', FLUENTFORMPRO_DIR_URL . 'public/libs/pickr/pickr.min.js', array(), true, true ); //beaver builder editor page tiny mce editor conflict fix if (class_exists('FLBuilderModel') && FLBuilderModel::is_builder_active()) { wp_deregister_script('fluentform-uploader-jquery-ui-widget'); } } } /** * Plugin init hook * @return void */ add_action('init', function () { load_plugin_textdomain( 'fluentformpro', false, dirname(plugin_basename(__FILE__)) . '/resources/languages' ); (new FluentFormPro)->boot(); }); register_activation_hook(__FILE__, function ($siteWide) { \FluentFormPro\Payments\Migrations\Migration::run($siteWide); \FluentFormPro\classes\DraftSubmissionsManager::migrate(); }); add_action('plugins_loaded', function () { if (defined('FLUENTFORM')) { include plugin_dir_path(__FILE__) . 'libs/ff_plugin_updater/ff-fluentform-pro-update.php'; } }); } /** * Registers a custom integration in AffiliateWP **/ add_filter('affwp_extended_integrations', function ($integrations) { // Register the custom integration $integrations['fluentforms'] = [ 'name' => 'Fluent Forms', 'class' => '\FluentFormPro\Integrations\AffiliateWP\AffiliateWPFF', 'file' => FLUENTFORMPRO_DIR_PATH . 'src/Integrations/AffiliateWP/AffiliateWPFF.php' ]; return $integrations; }); PK!ɸQHH readme.txtnu[=== Contact Form Plugin - Fastest Contact Form Builder Plugin for WordPress by Fluent Forms === Contributors: techjewel,adreastrian,heera,wpmanageninja Tags: contact form, contact forms, wp forms, forms, form builder, contact form builder, fluent forms Requires at least: 4.5 Tested up to: 6.5.3 Requires PHP: 7.4 Stable tag: 5.1.18 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html The Fastest Contact Form Builder Plugin for WordPress. Drag and drop contact form builder plugin with all premium features. == Description == = The Best and Fastest Contact Form Builder Plugin by Fluent Forms = **Fluent Forms** is the ultimate user-friendly, **customizable drag-and-drop WordPress Contact Form Plugin** that offers you all the premium features, plus many more completely unique additional features. A perfect **WordPress Form builder** plugin should be developed in a way, so that you don’t have to code every time you need to integrate a form in your website, but can be set up in minutes. And that’s why, we have developed Fluent Forms for you. [youtube https://www.youtube.com/watch?v=FFR2ZZaVF3g] [Demo](https://fluentforms.com/forms/) | [User Guide](https://wpmanageninja.com/docs/fluent-form/) | [Get Support](https://wpmanageninja.com/support-tickets/) | [Youtube Video Tutorials](https://www.youtube.com/watch?v=JJ0fBWMW174&list=PLXpD0vT4thWEu4gAkLE0Eq7PRCFp_8j2z) | [Official Facebook Community](https://www.facebook.com/groups/fluentforms/) Fluent Forms helps you create hassle-free contact forms, subscription forms, or any kind of WP Forms you need for your website in minutes. [youtube https://www.youtube.com/watch?v=uysITMu7Ml8] ==Amazing Features== * Conversational Forms and Classic Form Builder * Drag & Drop Contact Form Builder * Multi-column Contact Form Layout * Smart Conditional Logic Form Fields * Conditional Confirmation Messages * Build 100% Responsive and Mobile Friendly Web Forms and Contact Forms. * Reusable Templates for All kind of Forms including many contact forms. * Spam Protection with Google Recaptcha for your contact forms. * Placeholder Customization for your contact forms. * AJAX Submission and Both Client-Side and Server-Side Data Validation for contact forms. * Send Beautiful Email to submitter and admin after contact form submission. * You can configure what will happen after a contact form submission. You can show a success message, or you can redirect the user to a selected URL. * Restrict Your Web Contact Form by user role * Show the form only for a time/date range. * 30+ Form Field Types to build any Web Forms quickly. * In-Depth Analytics where you can see how many times it's displayed and how many leads were captured from Contact Forms. * Set Default Value On Contact Form Fields or you can populate from URL parameters * Export/Import Contact Forms * Mailchimp Integration - Add Lead/Contact on Mailchimp on form submission * Slack Integration - Send Slack notification of Contact Form Submission. * Export Data - You can export data as CSV/Exel/ODS or JSON format. * Advanced Data Filtering where you can see data by status and also by date range. What a good Contact Form builder plugin is if the users can’t use it with ease and the way they want. And deep inside, you know too as well, how important it is to present your audience a website that is designed keeping in mind the audience’s need and necessity first. So in times, you might as well feel like customizing a contact form or subscription form suitable for a specific portion of your audience. And this is where you will find that Fluent Forms is the most powerful and flexible form builder tool developed so far. And not only that, this form builder is so easy to use, even a complete beginner will be able to create and publish forms in less than 5 minutes! As responsiveness is a must for any online tool these days, Fluent Forms is developed as a 100% mobile responsive contact form builder, so that your forms look great on all kinds of devices (mobiles, tablets, laptops, and desktops). Here goes a list of all the Premium features you will be enjoying in Fluent Forms: == Super Fast Contact Forms == Fluent Forms is built for speed. It does not slow down your site nor load lots of css & js. A standard form only loads less than 30KB css and js combined, which is the lowest among all the form builders out there. Fluent Forms will outperform a big way if you compare with all the form builders plugin. Most of the form builders plugin loads at least 300KB assets to load a simple form where Fluent Forms load 10% of the average size. Build the fastest contact forms and web forms in minutes. == Conversational Forms == Fluent Forms v4.0 is live, and it's more powerful than ever! With the most awaited Conversational Forms, the plugin became your no. 1 choice to build next-level WordPress forms. [youtube https://www.youtube.com/watch?v=lLQWsjqrGtg] With Conversational Form Style you can easily build awesome high converting type styled forms easily. It's completely free. [View Conversational Form Demo](https://fluentforms.com/?fluent-form=138) Starting from v4.3.0, Conversational Forms got even more powerful. Now you have full-on keyboard access. With Fluent Forms Pro, you can enjoy more advanced functionalities, such as payment, coupon, file upload, and checkable grid. == Built-in Data Analysis Tool == In version 3.0.0, we have added the most exciting features that no other form plugins provide, and that is built-in data visualization tool. Using the data visualization module, you can analyze your data from your web and contact forms, analyze the data using a pie-chart, bar chart, tabular view. Using Ninja Tables plugin you can even show the submitted data in the frontend. == Best Contact Form Plugin in WordPress == Fluent Forms is an extremely feature-rich plugin that delivers a beautiful and bright user interface. Everything works with drag-and-drop, which makes creating new forms slightly quicker and more accessible, You will get all the premium components like conditional logics, more than 30 custom fields, 3rd party integrations, built-in entry management system, etc. Fluent Forms can be used for your regular contact forms, event forms, online forms and any data collection form. You can connect the form data with many 3rd party CRM without writing a single line of code. And the Best thing is this is entirely free, and it always is free and opensource. == DRAG & DROP CONTACT FORM BUILDER == Our powerful drag & drop contact form builder allows you to easily create WordPress contact forms and other online forms in just a few minutes without writing any code. Building forms is now easier for you than writing and drawing it on a piece of paper! == ONE-CLICK MIGRATOR == Already using a form plugin? If you are looking forward to switching to Fluent Forms, but already using Caldera Forms, Ninja Forms or Gravity Forms; we will make the switch easy for you. Now Fluent Forms comes packed with a one-click migrator. With this migrator, you can import all of your forms made with Caldera along with the customizations, configuration, and form entries! For Ninja Forms, and Gravity Forms the migrator will only import your forms and form settings, but not the form entries. == MULTI-COLUMN FORM LAYOUT == We have all faced the hassle of long forms, filling out which seems like meeting a Dementor from the Harry Potter series that might suck the soul out of you and leave you dead. These “long” forms are often nothing more than just mismanagement of space. Say, you are showing your potential lead a form that has ten input fields in it. Now stacking these 10 fields one after one makes it a long, tedious, and scary form. But if you cleverly stack them 2 or 3 columns, the whole thing looks compact, smart, and not that much scary at all! This is the most unique feature that helps Fluent Forms stand out from the herd. The **Multi-column form layout** option is a feature that you won’t even find in the premium form builder plugins! And also if you find any, those will not be as fluent, intuitive and easy to use as our one does. == 100% RESPONSIVE MOBILE-FRIENDLY CONTACT FORMS FOR YOUR AUDIENCE == As of the current user behavior throughout the world, a significant portion of your visitors will be visiting your website with their handheld devices. And you do not want to disappoint them with some disoriented contact form. Keeping that in mind, Fluent Forms was developed to make sure that it satisfies devices of all sizes of display. == CONDITIONAL LOGICS == Why irritate your users with unnecessary fields that they do not need? Use Fluent Forms' Conditional Logic feature to make your forms more efficient and user-friendly. Show and hide specific fields according to users’ behavior so that they do not have to be bothered with unnecessary fields they do not need to fill up. You can show and hide entire sections or steps (in step forms) if you need using Fluent Forms' Conditional Logic. Whereas, in most of the Contact Form Plugins available, this Conditional Logic is a Premium Feature. But in Fluent Forms, you can enjoy this feature in our free version! == CONDITIONAL CONFIRMATION == Along with Conditional Logics, we have introduced Conditional Confirmations (pro) as well. It allows admins to convey to users customized messages if they do not comply with specific logics, or fail to achieve certain values while filling out forms. For an example, you are looking for a value of equal to or more than 2 in a certain field of your form. But what if they put 0 or 1 in that field? In that case, using a conditional confirmation feature, you can let your users know of what went wrong and how to fix it. Remember, this is an entirely different feature than the usual error messages. == GET REAL TIME EMAIL NOTIFICATION == Get notified every time someone fills up a form with entry details. With Fluent Forms, you can also inform your team members every time someone fills up a form and also send back a confirmation email to the new subscriber. Fluent Forms also enables you to automatically send out certain submissions from the email notification process if they fail to comply with specific conditions set by the admin. == REUSABLE FORM TEMPLATES == Why do the same thing over and over again? Isn’t it madness? Fluent Forms enables you to reuse the same contact form again and again. You can copy the whole setup with a click and make necessary tweaks in a short time, which will be saving your precious time. == FLEXIBLE CUSTOMIZATION == Customizing your subscription forms has never been easier. According to your need, you can create forms with HTML blocks, tooltips, suitable orientations, and custom CSS, etc. If you are interested in having a peak under the hood and see if it can be made more useful, we have that option too! == MANAGE YOUR SUBSCRIPTIONS SMARTLY == You are not installing a form builder plugin to lure in 5-10 subscribers, right? What do you do when thousands of visitors subscribe to your website? You will need a smart system to handle such an influx. That is where Fluent Forms can help you manage things easily. Managing your submitted data has never been easier! With Fluent Forms, you can organize your submitted entries according to their value and export the whole list with just a click, or you can integrate with **slack**, **Mailchimp**, and 16 more. == Form Fields available in Fluent Forms == - Name Fields - Email Address - Simple Text - Mask Input - Text Area / Multiline Texts - Address Fields - Country List - Numeric Field - Dropdown / Select - Radio Button - Check Box Field - Multiple Choice / Multi-Select Form Field - Website URL - Time & Date - Custom HTML - Hidden Field - Section Break - Google reCAPTCHA - hCaptcha - Terms and Conditions - GDPR Agreement Field - Password Field - Custom Submit Button - Two Column Container - Three Column Container **More Advanced Fields in Pro** - Image Upload - Phone Field - File Upload - Shortcode Field - Action Hook Field - Form Step to build multi-step form - Google Maps & Address autocomplete - Quiz Module - Ratings Form Field - Checkable Grid - Range Slider - Color Picker - Net Promoter Score - Repeat Field - Save and Resume - Post/CPT selection field - Post Update - Chained Select - Post Creation Fields - Payment Field - Custom Payment - Inventory Module - Item Quantity - PayPal Payments - Credit Card Payments Via Stripe - Accept Payments Via RazorPay - Accept Payments Via Mollie - Accept Payments Via Paystack - Accept Payments Via Square **Advanced Form Styler (Pro)** Advanced form styler is our most amazing feature of 2019 and we are so much excited about it and I am sure our users will love it. Using this styler, you can easily style every element of a form. We also added four pre-defined styles template that you can just select and pre-defined css will be added applied realtime. If you choose custom design then the styler will show the style elements based on your form's available styles and you and you can design the form elements fro the style controls. **Create PDF from Form Submission** Now, You can generate PDF from your templates and download or attach the PDF via email. This feature is completely free. == 66+ Pre-Built Forms == We have added 66+ pre-build forms for you so you can easily select the right form and start using it. Here are the few forms from those that we have packed for you: * **Contact Form** - A simple contact form for your site. * **Support Form** - Using this support form, users can ask questions. * **Event Registration Form** - Using this registration form, you can enable your event to achieve its goal. * **Vendor Contact Form** - Easily create a vendor contact form and get logged in user details easily. * **Patient Intake Form** - Using this form, you can get the patient information with the medical history. * **Volunteer Application Form** - Get volunteer applicants data according to their particular interests with working days. * **Request for Quote Form** - Get user request for quote using this simple form. * **Conference Proposal Form** - This sample form is to make a conference proposal efficient and effective. * **Report a bug Form** - You can get user feedback, bug reports, and the issue details from the user. * **Polling Form** - A sample polling form to get user opinion from your scheduled time. * **Tell A Friend Form** - Get text from your site users. * **My Directory Information Form** - This form allows you to get the directory information. * **My Directory Information Form** - This form will enable you to get the directory information. * **Request for Leave Form** - Receive leave requests from your employee instantly. * **Admissions Form** - Receive new admission students' data along with their documents using this sample admission form. * **Loan Application Form** - Get loan applications from applicants with their detail information. * **Job Listing Form Form** - Get application and uploaded a resume from online applicants. * **Website Feedback Form** - To make effective for your site users, you may get the feedback and suggestions using this sample form. * **Comment & Rating Form** - Get user ratings and feedback instantly. * **User Registration Form (pro)** - Create user and make automatic login as part of the form submission process. * **Donation Form (pro)** - Let your users input the donation amount and donate via paypal, Stripe, RazorPay and Mollie as a form submission process. * **Payment Form (pro)** - You can easily process payments using Fluent Forms. PayPal, Stripe, RazorPay and Mollie available as payment methods. * **Subscription Payments (pro)** - Accept and Manage subscription payments easily with Fluent Forms Pro. ==Pro Integrations ==
    • Zapier Integration - Connect your Fluent Forms data with Zapier and push data to thousands of online softwares
    • WebHook - Broadcast your WP Forms Submission to any web api endpoint with powerful webhook module.
    • Google Sheet - Directly push your form entries to google sheet.
    • ActiveCampaign - WordPress Forms ActiveCampaign Module allows you to create ActiveCampaign list signup forms in WordPress, so you can grow your email list.
    • Campaign Monitor - Fluent Forms Campaign Monitor module allows you to create Campaign Monitor newsletter signup forms in WordPress, so you can grow your email list.
    • Constant Contact - Connect Constant Contact with your WP Forms and create subscriptions forms right into WordPress and grow your list.
    • ConvertKit - Connect ConvertKit with your WP Forms and create subscriptions forms right into WordPress and grow your list.
    • GetResponse - Fluent Forms GetResponse module allows you to create GetResponse newsletter signup forms in WordPress, so you can grow your email list.
    • HubSpot - Connect HubSpot with Your WP Forms and subscribe a contact when a form is submitted
    • iContact - Connect iContact with your WP Forms and subscribe a contact when a form is submitted
    • MooSend - Connect MooSend with WP Forms and subscribe a contact when a form is submitted
    • SendFox - Connect SendFox with WP Forms and subscribe a contact when a form is submitted
    • MailerLite - Connect your WP Forms with MailerLite and add subscribers easily
    • MooSend - Connect MooSend with Fluent Forms and subscribe a contact when a form is submitted.
    • SMS Notification - Send SMS when new submission will be happened in real time with Twilio
    • Platform.ly - Connect Your WordPress form with Platform.ly
    • Trello - Create Trello Cards in your boards on form submission
    • Drip - Fluent Forms Drip Module allows you to create Drip subscribers from WordPress, so you can grow your email list.
    • iContact - Connect iContact with Fluent Forms and subscribe a contact when a form is submitted.
    • SendinBlue - Connect Your Contact Forms with SendinBlue CRM
    • Automizy - Connect Your Contact Forms with Automizy Marketing Solution
    • User Registration - Create WordPress users from fluent form submissions
    • Post/CPT integration - Create any type of posts from form submission. You can visually map the ACF fields from Fluent Forms
    • PayPal - Create PayPal forms to easily collect payments, donations, and online orders. Sale your items easily using WordPress Forms
    • Stripe - Easily collect credit card payments, donations, and online orders with Fluent Forms Pro. No Extra addon requires
    • Mollie - Easily collect credit card payments, donations, and online orders with Fluent Forms Pro. No Extra addon requires
    • RazorPay - Easily collect credit card payments, donations, and online orders with Fluent Forms Pro. No Extra addon requires
    • Paystack - Easily collect credit card payments, donations, and online orders with Fluent Forms Pro. No Extra addon requires
    • Discord - Get automated form notifications on your Discord server
    • Salesflare - Connection with the Salesflare CRM got more 'Fluent' with this integration
    == PAYMENT FORM, DONATION FORM, ORDER FORM, AND MORE == Fluent Forms started is not just a contact form plugin, it is a powerful forms solution that you can use to create a payment form, donation form, registration form, online booking form, guest posting forms and more. Fluent Forms Pro integrates with both PayPal and Stripe, so you can easily create a payment form to accept credit card payment on your website. You can also use PayPal payment method to make a donation form and accept payments online. Business owners also use Fluent Forms to create custom product purchase forms like t-shirt order forms, online booking forms, custom amount payment form and more. [youtube https://www.youtube.com/watch?v=iYOmHLtkRfQ] == Checkout The Documentation with video tutorial == Fluent Forms Documentation comes with a detailed step-by-step instruction of how to use this Drag & Drop responsive WordPress form builder plugin. The following topics are covered in this documentation. Please check few of them as bellow: [youtube https://www.youtube.com/watch?v=z9W5p8TJK7I] == What our users saying about the Best Contact Form Plugin for WordPress == >__Best form plugin ever with first class support__ >This is the lightest form plugin I’ve ever used (except basic CF7 which is not enough for me). Great performances, great UI, great features, and above all, amazing dev/support team!!! Plugin is improving almost every week and they listen to you 🙂 - By @yankiara >__Excellent !!!__ >This is going to replace the current form making plugin I’ve been using since 2012, and I won’t be looking back, it’s that good. And things will only get better with the development of this plugin. Looking forward for the repeat field, among other things. I wish I could give it 6 stars !!! - By @nick6352683 >__One of the best form builder__ >I been using other form builder plugins, and this form builder is easy and it gets the job done. I have switch all my sites to this form builder, and i’m not going back. >The support team is very help full, I have message him about issues I have found, and he would be all over it to solve the issue. I recommend this builder, it has everything you need and more, specially with the builder making the plugin better over time. Looking forward to what other options will be available in the future. Thank you - By @antoniolucio >__A great life time saver and what performances!__ >Great plugin, really. You have to test it… it’s super fast and super lightweight. - By @seventhose >__Fluent Forms is just so excellent__ >I came in contact with Fluent Forms about 2weeks ago and has change my experience in using forms. The easiest and sweetest plugin available. Also Great support team. >Thanks excellent Hasanuzzaman for your support - By @austinigbe >__Free Version Has Options Found only in Premium Plugins__ >This is a fantastic email form. It’s fast (very light weight), easy to use, and the support is great. To boot, the free version also has options usually found only in premium email forms. Don’t waste your time looking for another form. I spent countless hours looking for the “right” form, and this one is it, hands down. - By @nevrsmer == Other Plugins By WPManageNinja Team == == Installation == This section describes how to install the plugin and get it working. e.g. 1. Upload the plugin files to the `/wp-content/plugins/fluentform` directory, or install the plugin through the WordPress plugins screen directly. 1. Activate the plugin through the \'Plugins\' screen in WordPress 1. Use the `Fluent Forms` -> `Settings` screen to configure the plugin 1. (Make your instructions match the desired user flow for activating and installing your plugin. Include any steps that might be needed for explanatory purposes) == Frequently Asked Questions == = Do I need coding skill to use Fluent Forms? = No, You don't need any pre-requisite programming knowledge to build beautiful forms. With Powerful drag and drop features you can build any simple or complex form. = Will Fluent Forms slow down my website? = Absolutely not. We build Fluent Forms very carefully and maintained WP standards as well as we only load styles / scripts in the pages where you will use the Fluent Forms. Fluent Forms is faster than any form builder plugin. Fluent Forms only load less than 30KB css and js combined. = Can I use conditional logics when building a form? = Yes, With our powerful conditional logic panel you can build any type of complex forms. You can add one or multiple conditional logics to any field and it will work like a charm. = Can I build multi-column forms? = Yes, You can use 2 column or 3 column containers and you can build forms. = Can I export the form submission data? = Yes, You can export your data in CSV, Excel, ODS, JSON format. You can also import in pro version. = Do you have a public roadmap? = Yes, Please check our public road map in Trello = I want to report a bug, where to report? = The entire source code is available on github. Please feel free to fork and send a pull request or report a bug. == Screenshots == 1. Form Builder with Editor 2. Form Preview 3. Conversational Form Preview 4. Form Settings 5. Email Notification Settings 6. Entries List 7. Entry Details 8. Data Reporting 9. Advanced Form Editor 10. Form Integration Manager 11. All Submission Chart by Date 12. Asset Loading Comparison with Other Plugins == Changelog == = 5.1.18 (Date: May 23, 2024) = - Adds Form creation using AI (ChatGPT) - Adds confirmation message using AI (ChatGPT) - Adds post shortcodes - Supports kenyan shilling for paystack - Fixes unselected radio payment field validation - Fixes repeater field data on Trello board = 5.1.16 (Date: May 6, 2024) = - Improved CleverReach & Twilio feed error response - Fix Hubspot & OnePageCRM custom fields - Fix action reply feed = 5.1.14 (Date: April 25, 2024) = - Fix entry action for post feed = 5.1.13 (Date: April 19, 2024) = - Fixed Entry delete on submission = 5.1.12 (Date: April 18, 2024) = - Adds JetEngine CPT Compatible - Adds Conversational Form Save And Resume - Adds entries API Logs retry action - Adds multiple email support in email routing - Improve accessibility on repeater field and file upload field - Improve CleverReach all scopes message check - Improve filter hook to change stripe inline custom style - Improve file upload, repeater and name field on entry update - Removed non-essential 'required' attributes from Pipedrive integration - Fixes Hubspot checkbox on custom field - Fixes GetResponse integration empty name - Fixes custom mask input on repeater field - Fixes repeat field default value on new row - Fixes multiple choice user meta dynamic default value - Fixes subscription user input minimum value with conditions - Fixes empty name on stripe subscription payment - Fixes global inventory same radio options remaining count - Fixes inventory same label name conflict on Inventory page - Fixes Quiz score value mapping on FluentCRM dynamic tag section - Fixes border on custom style - Fixes post update for current user on logout session - Fixes html tag on Zoho CRM textarea field - Fixes checkable grid data on Discord, Trello description - Upgrade JQuery UI widget.js to v1.13.2 = 5.1.11 (Date: February 28, 2024) = - Fixes Stripe statement_descriptor issue = 5.1.10 (Date: February 26, 2024) = - Adds Range slider support for quantity Field - Fixes PayPal payment IPN issue - Fixes payment summery shortcode on email - Fixes quiz advanced condition mismatch - Fixes Quiz Result shortcode {quiz_result} in PDF - Fixes payment debug log info - Improves Airtable Phone Field with validation - Improves Admin Approval to support User registration Integration - Adds (.wav) file support = 5.1.7 (Date: January 7, 2024) = - Add Entries Admin Approval - Add Entries Import - Add Global Inventory - Add support for background image & gradient in form styler - Improve Custom Styler - Support ZohoCRM currency field - Improve cleverreach error handling - Fix background color not showing on landing preview page - Fix quiz field condition on the conditional confirmation - Fix range slider default value with required option - Fix multiple subscription plan minimum value - Fix showing trashed entries on Survey Result - Fix airtable phone field validation - Fix subscription plan custom input min value - Fix step from conditional slide button UI issue = 5.1.6 (Date: December 2, 2023) = - Fixes Paypal custom payment issue - Fixes personality quiz conversational issue - Fixes Notion multi select = 5.1.5 (Date: November 23, 2023) = - Fixes Notion multi select = 5.1.3 (Date: November 22, 2023) = - Adds support ACF field on Post revision & ACF rich-text value on Post Update Form - Improves Gravity Forms migration entries by status - Improves WP Forms migration fetch webhook feed - Improves AirTable integration - Fixes null value on mapping Post create feed - Fixes inventory quantity field issue - Fixes range slider required field value on render - Fixes temp attachment files deletion - Fixes checkable grid and repeater field data format on webhook - Fixes google address autocomplete on elementor popup = 5.1.1 (Date: November 4, 2023) = - Improves custom CSS & JS loading = 5.1.0 (Date: November 1, 2023) = - Adds Notion Integration - Adds Personality Type Quiz - Adds success and failure message option for coupon - Adds form submission restriction based on IP and Country - Fixes dynamic default value of single payment item - Fixes Conditional shortcode empty condition - Fixes unique email checking for pending payment - Fixes file/image on step form partial entry view & front end - Fixes PHP 8+ issue for quiz advanced scoring - Fixes CleverReach endpoint - Fixes displaying password in partial entries - Improves ACF Support (checkbox, multi-select, ACF image for user registration and update) = 5.0.10 (Date: October 18, 2023) = - Adds form preview in Gutenberg block - Adds form theme change support in Gutenberg block - Adds theme style inherit option - Fixed Form finder = 5.0.9 (Date: September 8, 2023) = - Added selected fields export from entries page with additional fields - Updated support PHP 8.2 - Fixes save form state issue = 5.0.8 (Date: August 24, 2023) = - Adds Inventory Details Page - Adds Inventory Item Disable option when item is stock out - Adds ACF repeater field on post update - Improves formatted email for failed integration notification - Improves Airtable integration with latest API - Improves Phone Field’s validation library (supports more carrier) - Fixes checkable fields payment calculation issue in Conversational Form - Fixes landing page style after double opt-in confirmation - Fixes Pipedrive custom fields - Fixes payment method required - Fixes Platformly tags and integration disconnect - Fixes rendering custom payment field in calculation - Fixes conditional step form not skipping with image is used as button - Fixes payment module deactivation issue with inventory - Fixes Salesforce required field and currency code issue - Fixes landing page facebook share image preview - Fixes numeric field in quiz = 5.0.7 (Date: July 18, 2023) = - Fixes LiteSpeed caching issue - Fixes dynamic shortcode bug - Fixes style issues - Fixes PDF issue for checkbox field - Fixes post update issue for block themes - Fixes conditional issue for payment items - Fixes Double Opt-In save issue - Fixes entry export filter issue - Improves email on iOS devices = 5.0.3 (Date: Jun 27, 2023) = - Form Restrictions check improved - User registration / login issues fixed - Email Notification improved - Visual Reporting issues fixed - Fixed issues with the REST API endpoints - Fixed Compatibility issue with Caching Plugins and Few other servers - Styling issues fixed - Deprecated hooks notices fixed - Litespeed cache compatibility issue fixed = 5.0.2 (Date: Jun 23, 2023) = - Fixed UI issues with Conversational Forms - Fixed Styling issues from 5.0.0 - Stripe Subscription Payment Issues Fixed - Advanced Calculation issues fixed = 5.0.0 (Date: Jun 22, 2023) = - Added post update permission for guest users - Added Style Export & Import - Styler Improvement - Added multi-step form animation type - Added range slider functionality to conversational form - Improved support for Metabox and ACF in Post Form - Updated WooCommerce Product Creation using Post Form to allow for multiple image addition. - Fixed issue with form duplication due to chained select source CSV file - Fixed custom payment amount shortcode - Fixed coupon code date issue - Fixed ACF checkbox/multiple choice not working - Fixed Drip issue - Fixed checkbox list field behavior when all boxes are unchecked using Metabox - Fixed quiz option order issue - Fixed payment summary display issue when using coupons in conversational form = 4.3.23 (Date: February 02, 2023) = - Adds Landing Page Layout Design & Shadow Configurator - Adds Copy Button & Email option for Save & Resume Form Link - Adds Clickable Form Step - Improve Razorpay Modal (color config) - Updated File Upload Library - Fixes Inventory Issues with Conversational Form - Fixes Buddyboss username issue - Fixes Airtable br tag issue for textarea field - Fixes Twillo SMS Format - Fixes Translation Issue For File Upload - Fixes Google Sheet & Excel Export Format Issue for Repeater Field - Fixes Excel and CSV Format Issue for Checkable Grid - Fixes Payment Info on {all.data} shortcode when Product display type is set as Checkbox - Fixes Resume Step Form Multiple Choice Field Issue - Fixes Address Field’s Country List Mapping with FluentCRM - Fixes User Registration Integration’s username issues in URL Slug - Fixes Post Update Field’s Placeholder - Fixes Range Slider Field’s Required Option - Fixes Tags and Lists webhook to work with FluentCRM - Fixes Mailjet Custom Field - Fixes Post Update Field’s Conditional Logic Issue - Fixes Country restriction in google address auto complete = 4.3.21 (Date: November 10, 2022) = - Fixes Quantity field = 4.3.20 (Date: October 27, 2022) = - Adds Date field support on HubSpot - Fixes negative payment bug - Fixes Checkable Grid on Google Sheet - Improves UX = 4.3.19 (Date: October 21, 2022) = - Adds ACF gallery support - Adds RazorPay customer prefill = 4.3.18 (Date: October 19, 2022) = - Fixes ZohoCRM tags support = 4.3.17 (Date: October 18, 2022) = - Adds HubSpot error handler = 4.3.16 (Date: October 16, 2022) = - Adds input mask for Repeater field - Fixes PayPal IPN - Fixes ACF field date section bug - Fixes zero value bug for Discord - Fixes Repeater field select width issue = 4.3.15 (Date: October 10, 2022) = - Fixes conditional support - Fixes integration failed notification - Fixes Google Sheet integration = 4.3.14 (Date: October 08, 2022) = - Fixes calculation module = 4.3.13 (Date: October 07, 2022) = - Adds Inventory Management module - Adds Coupon Code limitation feature - Adds ACF and Metabox support in Post feed - Adds Salesforce sandbox support - Adds min function to calculations - Improves PHP 8 support - Improves Quiz module - Improves Google Sheet integration - Fixes Webhook
    tag - Fixes HubSpot custom field issue - Fixes BuddyBoss user registration issue - Fixes elementor popup for conditional fields = 4.3.12 (Date: September 01, 2022) = - Improves translation for reciept page - Fixes Resend email notification custom recipient bug - Fixes pending payment entry count of additional shortcode - Fixes BuddyBoss nickname issue - Fixes Zoho CRM: Customized Lead Status Issue - Fixes Rich Text input not working in modal - Fixes Step Form previous session bug - Fixes popup issue for Elementor with conversational form - Fixes user update password issue - Fixes image upload button issue - Fixes Conversational form Phone field country code issue - Fixes Rating field option editing bug - Fixes Quiz field randomize issue - Fixes Conversational form payment bug - Fixes iPhone image upload issue conversational form - Fixes Step form issue with submit button = 4.3.10 (Date: August 04, 2022) = - Adds Save & Resume form submission - Adds Rich Text Input - Adds Insightly Integration - Adds Mailster Integration - Adds Airtable Multiple table connection - Adds email notification for Pending Payment - Improves Quiz Module - Improves Post Update with ACF - Improves User Update with meta fields - Improves failed integration notification email - Fixes Signature field placement issue - Fixes HubSpot API update issue - Fixe User Registration password reset email issue - Fixes Step form data save issue with Checkable Grid field - Fixes Coupon Code issue - Fixes ACF image upload with media upload - Fixes Constant Contact Issue - Fixes br tag issue in Twilio = 4.3.9 (Date: July 04, 2022) = - Adds User Profile Update feature - Adds Partial entry bulk delete - Fixes Phone field issue hidden country issue - Fixes Payment method conditional logic issue - Fixes taxonomy field default value issue - Fixes Post update dynamic default value - Fixes Range slider issue on same page = 4.3.8 (Date: June 02, 2022) = - Fixes Post update taxonomy issue - Adds MailJet integration - Fixes Pipedrive custom field issue - Fixes zero custom payment issue - Fixes payment styling issue = 4.3.7 (Date: May 20, 2022) = - Adds Airtable setup validation - Fixes CPT selection issue for Post Update - Fixes license error notice display issue - Fixes smart dropdown style issue = 4.3.6 (Date: May 19, 2022) = - Adds WP Media file upload option - Adds Airtable integration - Adds advanced quiz scoring system - Improves Post update feature - Improves Paystack integration - Improves ZohoCRM integration - Improves Discord integration - Fixes chained selector issue on Elementor popup = 4.3.5 (Date: April 22, 2022) = - Adds Quiz module - Adds amoCRM integration - Adds OnePageCRM integration - Adds Pipedrive integration - Adds phone number support for ZohoCRM - Adds other data center support for ZohoCRM - Adds email notification support for failed integrations - Adds resubscribe option for MailerLite - Adds dyanmic default value for payment item - Adds support for programmatically license management - Adds smart search for chained select field - Adds {payment_total} shortcode support on Conversational Form - Adds Subscription Payment field in Condition Logic groups - Improves payment item display for radio fields - Fixes Phone Field validation message for Conversational Form - Fixes currency position issue for payment items for Conversational Form - Fixes payment item value zero issue - Fixes payment method selection issue - Fixes Stripe donation issue = 4.3.3 (Date: Mar 18, 2022) = - Adds Post update feature - Adds Salesforce integration - Adds filter for post feed data - Adds quantity field for Subscription - Adds field customization option for Slack - Adds remote CSV upload for Chained Select field - Improves User Registration module - Improves Trello integration - Improves Zoho CRM and ClickSend integrations - Fixes Address Line 1 duplication for autocomplete - Fixes BuddyPress bug for Multisite - Fixes Step Form saved data issue - Fixes multiple payment method selection bug = 4.3.2 (Date: Feb 17, 2022) = - Fixes single payment method bug = 4.3.1 (Date: Feb 14, 2022) = - Adds AffiliateWP integration - Adds Zoho CRM integration - Adds ClickSend integration - Adds CleverReach integration - Adds Phone Number validation message configuration - Adds conditional block support in PDF Feed - Fixes payment hooks for FluentCRM - Fixes custom payment issue for one time billing - Fixes Phone Field country settings - Fixes Range Slider width - Fixes Stripe Subscription meta data - Fixes Stripe Inline customer information - Fixes Checkable Grid stat in Entries' Visual Data Report - Fixes payment issue in Elementor Popup - Fixes PayPal empty cart issue - Fixes Salesflare custom fields issue - Improves partial entry sorting = 4.3.0 (Date: Jan 18, 2022) = - Adds Payment Inputs in Conversational Forms - Adds Checkable Grid Field in Conversational Forms - Adds File Upload Field in Conversational Forms - Adds Image Upload Field in Conversational Forms - Adds Discord integration - Adds SalesFlare integration - Adds Address autocomplete with map - Adds Auto-locate user in address field - Adds Media Attachment in email notifications - Adds support for country-wise google autocomplete - Fixes Stripe subscription trial Days issue - Fixes Stripe donation issue with subscription - Improves Customer Billing Address for Payments = 4.2.1 (Date: Sep 01, 2021) = - Improvements on Conversational Forms - RTL Improvements - UI Improvements - New developer APIs - Performance improvements for form submissions = 4.1.5 (Date: July 13, 2021) = - Improvements on Conversational Forms - Help Message positioning - Predefined Data Set for Checkable Input Fields - Raw HTML Email Templates - Regex on conditional Logic - Other Improvements = 4.1.0 (Date: June 30, 2021) = * Improvements on Conversational Forms * Introducing ReCaptcha V3 * Elementor Integration Widget Improvements * Added prefix and suffix to text, email, mask inputs * Integration Improvements * Other CRON related issues fixed * Custom RAW HTML Email Body for advanced or simple designs = 4.0.0 (Date: June 08, 2021) = * Introducing Conversational Form Style * Dedicated landing page for Conversational Form * Added Layout Option for Conversational Form * Bulk Resend Notification Fixed * Various Integration Improvements * Editor UI improvements * PHP 8.0 Support * PHP API * Custom Submit Button = 3.6.74 (Date: May 27, 2021) = * Hot Fix: Form hide issue fixed after submission * A big update is coming soon = 3.6.72 (Date: May 22, 2021) = * Fixes Sanitize Data and Escaping on render for custom CSS and JS * Sub-Page Slug URL escaping issue fixed * Mailchimp Data Sanitization Fixed * Includes Licenses txt files * Fix smart filter UI saving * Added Column Re-order and show and hide data for form entries * Added ReSubscribe option for Mailchimp = 3.6.70 (Date: Mar 09, 2021) = * Fix Form Scheduling * Fix Preview Page Slug = 3.6.68 (Date: Mar 06, 2021) = * PHP 8 deprecated issue fixed * Export and Import Form/Entries Nonce issue fixed * Add Date range selection on entries chart = 3.6.67 (Date: Mar 05, 2021) = * Refactored VueJS build system, Form editor is now 40% faster. * Added Hooks for Smart Codes * Mailchimp Integration Issue fixed * Added Week-days to Date Field * Nonce check issue fixed on admin ajax * Admin Panel icon load issue fixed * PHP 8 compatibility issue fixed = 3.6.65 (Date: Feb 09, 2021) = * Randomize /Shuffle checkable options * PHP 8.0 support – Fluent Forms is not 100% compatible with PHP8 * Limit how many option a user can select for a select field. * UI improvements * Elementor Widget improvement * Better CSS loading time * FluentSMTP support * Replace icon fonts with SVG = 3.6.62 (Date: Dec 20, 2020) = * Database Improvement * Smartcode improvement * UI Improvement = 3.6.61 (Date: Dec 01, 2020) = * Form Builder screen improvement * Smartcode parser improvement * Non-ASCI chars handling when redirecting fix * Internal Improvements = 3.6.60 (Date: Nov 23, 2020) = * New: Number formats on the fly for numeric fields * New: Import Global Styles from another form * New: Dynamic Input Values as Label HTML (Live Update) * New: Inline Conditional Tags on CRM integration Feeds * Improvement: Oxygen Builder & ACF Integration * Many other small bug fixes and improvements * Overall UI/UX improvement = 3.6.51 (Date: Aug 24, 2020) = * UI/UX improvement * Conditional Logic Improvement * Added Advanced Conditions * Plain Text Email issue fixed * Elementor Popup integration issue fixed * Email Notification issue fixed = 3.6.42 (Date: July 28, 2020) = * Email sending issue has been fixed * Input background issue has been fixed * Cleaner All entries chart = 3.6.41 (Date: July 27, 2020) = * Conditional Logic improvements * Validate Uniqueness for Text Input values * Replace select2 with choices.JS library (cool) * Enable Search option for single select options * Reset selects after form submission bug fix * Popup issue fix for Elementor * Added new tooltip style for better visibility * Translation loading issue fixed * Slack Notification issue has been fixed * Internal Improvements and Performence increase = 3.6.31 (Date: July 3, 2020) = * Conditional Logic improvement (Now you can add Conditional Logic to Containers) * Query String php notice fixed * wp_date() support for older versions * Added "Mark as Favorite" in the entry details page * Email Summary Error Issue fixed * Taxonomies issue has been fixed for container fields * File Upload for drag and drop issue fixed * Dutch translation has been added * RTL support has been added for some elements = 3.6.22 (Date: June 19, 2020) = * Address Field Parser Fix * Fix Conditional Logic issue for multi-select * Added {inputs.fieldName.label} smartcode for accessing checkable field label = 3.6.0 (Date: June 18, 2020) = * Brand new UI for Form Builder * Introducing Weekly Email Summary for all of your forms * See All the Entries aggregated from all the forms * Better Oxygen Page Builder Support * Advanced Form Validation (Less Spam) * Introducing Elementor widget * Added German Language File * Mobile-friendly Admin Panel * Conditional logic issues for “less than” and “less than equal” * Added priority-based country selection * Added Kosovo to the country list * Elementor and Oxygen popup issues for step forms * Option to position input labels below the fields * Added layout option to make Radio/Checkbox as Button Selection style * Passwords will be now truncated after feeds and API calls completed * Added conditional source support for Hidden Fields = 3.5.6 (Date: April 29, 2020) = * PDF module has been added, Now you can send PDF via email or download * Added 2 PDF templates * Added *Not Contains* conditional Logic * Improved Submit Button (no loader gif now) * Better RTP support * Remove Empty keys when redirecting to a new page after form submission * Internal Improvements under the hood = 3.5.5 (Date: April 17, 2020) = * Refactored Frontend Javascript, For a basic form, it will load only 12KB JS * Multiple Address block copy error fixed * Conditional Logic Refactored * Internal Improvements = 3.5.4 (Date: April 09, 2020) = * Refactored Conditional Logics JS (New it's really faster for complex conditions) * Custom Dynamic URL issue fixed * Editor Improvement = 3.5.3 (Date: April 03, 2020) = * Conditional Logic improvement * T&C and GDPR UI improvement * Submission JS improvement = 3.5.0 (Date: March 30, 2020) = * Mailchimp tags syncing bug fix * CleanTalk issue fix * Beaver Builder integration issue fix * Added indication icon for conditional fields * Internal Architecture improvement = 3.2.3 (Date: March 02, 2020) = * Minor Bug Fixes = 3.2.3 (Date: February 29, 2020) = * Conditional Fields Improvement * UI Improvement * Internal Code improvement and bug fixes = 3.2.0 (Date: February 10, 2020) = * Email delivery fix for multiple emails * Frontend Form Submission Error handle * prevent form submission on Enter key press * Re-Arrange issue fixed for the checkbox and radio * Add css class field for containers * Added Suffix and Prefix label for Numeric Fields * Few bug and typo fixed = 3.1.5 (Date: December 31, 2019) = * Conditional Logic improvement * Form rendering process has been improved * Few CSS issue has been fixed * Ability to Reset Form Analytics * Several Typo Fix * Ability to send email as Plain Text * Improve Email Delivery process * Date-Time Field improvement * Form init Javascript Refactored * Sorting issue fixed from checkable options * Improved form validation message for checkable fields * +28 issues have been resolved in this release * Total ~95 commits submitted to git (in this version alone) = 3.1.0 (Date: November 19, 2019) = * Added gutenberg block * Added native form widget for sidebars and widget arias * Added step attribute to numeric field * CSV/Excel export issue fixed * File attachment list view improved * Added hidden fields to conditional logics * Fix submission error handler * Added global activity logs * Improved Form Editor UX * Added success message for redirect type confirmations * Integration improvements * Internal improvements = 3.0.8 (Date: November 06, 2019) = * Empty form submission issue resolved * Admin UI improvement * File Upload issue resolved * Added extra css class to containers. * Fix ' and " in value issue * Editor Improvement * Added more hooks for developers. * Elementor Pro Popup issue fix for reCaptcha = 3.0.6 (Date: November 03, 2019) = * Conditional Logics improvements. * Dynamic Error Message fix. * Elementor PopUp Compatability * Compliance Settings improvement * Section Break alignment fix. * JS Duplicate event fix. * Export-Import Forms fix. * Use WP timestamp as a default * Checkbox value parse fix. * Help messages added to name fields = 3.0.5 (Date: October 20, 2019) = * Email sending improvement * Step Text improvement and Translatable * Added User meta as default value * Fix element attributes special chars * Added RTL support * Fix submit button styling issue. * Fix Multi-site Update Issue * Internal Improvements * Shortcode Parser Improvements * Improve Default values * Added More hooks for developers * Ability to hide name field's label = 3.0.3 (Date: October 16, 2019) = * Email sending bug fix * Typo fix * Added Submission Properties to Smart Codes * Added symmetric HTML to file upload * Add option to hide labels * Multisite installation fix * Honeypot added = 3.0.0 (Date: October 13. 2019) = * All new form editor screen with a simple, powerful and clean interface * Built-in Data analysis tool for form submissions. * Email bug fix * Added new DB table for advanced reporting * Submit button styling and customization option * Improve form security * Form Preview re-engineered now. In any theme, it will work fine. * Exporting data issue fixed * Entry status management improvement * File upload issue fixed * Lots of integration added * Global Integration and Module manager. = 2.0.1 (Date: June 01, 2019) = * Added lots of UI improvement * Add option to add custom css and JS * add response filter options * add an option to export data * Add Dashboard widget for a quick look * Fixes for some form fields = 1.8.0 (Date: April 10, 2019) = * Fix conditional logic for multiple dropdown fields * Added clean, responsive html email templates * Improve integrations * Added few filter and action hooks for developers. * improve backend performance * added pre-written email on default forms. = 1.7.5 (Date: November 19, 2018) = * Small Fixes for COnditional Logic * Added option to give access of Fluent Forms to other user roles * Fix editor Sidebar Elements disorder * Added More hooks for developers = 1.7.4 (Date: October 31, 2018) = * Fix for some theme compitability * CSS fix for rating field * Minor fix for CSV export for contact forms = 1.7.3 (Date: October 27, 2018) = * Conditional Logic Bug fix for Internet Explorer * CSS fix for other browsers = 1.7.2 (Date: October 20, 2018) = * Minor Bug Fixes * Change Form Submission Process, Now the form submission process is more faster = 1.7.0 (Date: October 11, 2018) = * Added Lots of New features * Added Brand New Fields * Improve Performance by around 50% * Added Integration Bugs * Conditional Fields have more options = 1.6.0 (Date: June 28, 2018) = * Added More Integrations * Added Rating fields * Improve Export Entries * Added GDPR Compliance * = 1.5.3 (Date: April 30, 2018) = * Improved Conditional Logics * Fix Builder Drag and Drop Bug = 1.5.2 (Date: April 24, 2018) = * Support for php 5.4 = 1.5.1 (Date: April 20, 2018) = * Fix Admin Screen bug fix for special directory names for some servers = 1.5.0 (Date: April 19, 2018) = * Added Mask Input Field * Added Submit Button Customization * Added Dynamic Default Value from $_GET Parameter * Added + icon on Form Editor for faster Form Create and Edit * Placement of Required Items * * Added Ratings component * Add dynamic fields on Redirects = 1.4.3 ( Date: 24.03.2018 ) = * Added Name Input Field transformer * Make the input fields settings more User Friendly * Added Admin Label for all the elements * Fix Recaptcha on Form Submission * Restricts special chars on name attributes * Terms and Condition field bug fix * By default showing the entries latest first * Added compact mode on all entries page = 1.4.0 ( Date: 19.03.2018 ) = * Whole New Form Builder Editor * Improve the overall performance * Added More Input Fields * Reviewing form entries is more easy by going next and previous. * added capability to add custom fields for 3rd party developers. = 1.3.4 ( Date: 20.02.2018 ) = * Fix conflict with Jetpack * Added loading at form submission. * Improved entry view = 1.3.0 ( Date: 17.02.2018 ) = * Refactoring Form Builder for better performance * Add Image as Submit Button on form * Fix conflict with Jetpack * 20% performance increase at backend = 1.2.5 = * Google Recaptcha iOS UX Improvement ( Thanks to Antonio Lucio ) * Unread Entries Navigation Improvement = 1.2.4 = * Fix Google Recaptca Conflict with Contact form 7 * Form Builder Fix for Safari = 1.2.3 = * Fix Google Recaptca * Added Next and Previous Button on Form Entry * Simple Hidden Fields Editor = 1.1.3 = * Added More fields * Added more Field Customization options * Fix select and radio fields * Mailchimp double opt-in support = 1.1.3 = * Fix Mailchimp List Selection = 1.1.2 = * Fix Mailchimp Double Opt-In issue = 1.1.0 = * Added Mailchimp Integration * Added Slack Integration * Added Label positioning for each form element * Added Country Field * Improvements of Conditional Logic rendering * Lots of Improvement in Form Builder = 1.0.0 = * Init The most Advanced form builder plugin == Upgrade Notice == The latest Version is compatible with previous version, So nothing to worry PK!j autoload.phpnu[/Apublic/libs/jQuery-File-Upload-10.32.0/js/jquery.fileupload.jsnu[PK!' * *DהBpublic/libs/jQuery-File-Upload-10.32.0/js/jquery.fileupload-image.jsnu[PK!k1kBpublic/libs/jQuery-File-Upload-10.32.0/js/demo.jsnu[PK!Bpublic/libs/lity/lity.min.jsnu[PK!17 7 Bpublic/libs/lity/lity.min.cssnu[PK!""(DBpublic/libs/pickr/themes/classic.min.cssnu[PK!zO"")Cpublic/libs/pickr/themes/monolith.min.cssnu[PK!+Y""%5Cpublic/libs/pickr/themes/nano.min.cssnu[PK!G¬``XCpublic/libs/pickr/pickr.min.jsnu[PK!lyy'Cpublic/libs/rangeslider/rangeslider.cssnu[PK!d-J-J&_Cpublic/libs/rangeslider/rangeslider.jsnu[PK!& w)-)-"Dpublic/libs/math-expression.min.jsnu[PK!& w)-)-,]FDpublic/libs/math-expression-evaluator.min.jsnu[PK! gg*sDresources/languages/fluentformpro-fr_FR.ponu[PK!k"DD*Fresources/languages/fluentformpro-fr_FR.monu[PK!(ORR*nGresources/languages/fluentformpro-de_DE.monu[PK!Izz*FHresources/languages/fluentformpro-nl_NL.monu[PK!m; i i*3}Hresources/languages/fluentformpro-de_DE.ponu[PK!(XXX*Jresources/languages/fluentformpro-nl_NL.ponu[PK!MM%>Mresources/languages/fluentformpro.potnu[PK!T\Qresources/index.phpnu[PK!Jơ((.Qsrc/Components/ChainedSelect/ChainedSelect.phpnu[PK!1%n\&\&?Qsrc/Components/ChainedSelect/ChainedSelectDataSourceManager.phpnu[PK!hT:Qsrc/Components/Post/Components/NonHierarchicalTaxonomy.phpnu[PK!t9z, , 4rQsrc/Components/Post/Components/DynamicTaxonomies.phpnu[PK!.Qsrc/Components/Post/Components/PostExcerpt.phpnu[PK!!.qQsrc/Components/Post/Components/PostContent.phpnu[PK!V110Rsrc/Components/Post/Components/FeaturedImage.phpnu[PK!,'(Rsrc/Components/Post/Components/PostTitle.phpnu[PK!uHk"k"-i7Rsrc/Components/Post/Components/PostUpdate.phpnu[PK!6ٞ: 71ZRsrc/Components/Post/Components/HierarchicalTaxonomy.phpnu[PK!tT!5eRsrc/Components/Post/Bootstrap.phpnu[PK!#pEpE'6zRsrc/Components/Post/JetEngineHelper.phpnu[PK!ý&RR'Rsrc/Components/Post/PostFormHandler.phpnu[PK!޵88(Ssrc/Components/Post/PopulatePostForm.phpnu[PK!ۋ__(zKSsrc/Components/Post/PostFeedSettings.phpnu[PK!/WO O 1gSsrc/Components/Post/Getter.phpnu[PK!%=re,e,%sSsrc/Components/Post/MetaboxHelper.phpnu[PK!,q}]]&Ssrc/Components/Post/EditorSettings.phpnu[PK!^hP6P6!;Ssrc/Components/Post/AcfHelper.phpnu[PK!1jdd%Ssrc/Components/PostSelectionField.phpnu[PK! 7ooSsrc/Components/ColorPicker.phpnu[PK!8Tsrc/Components/FormStep.phpnu[PK! ɢ33%2Tsrc/Components/SaveProgressButton.phpnu[PK!x$ $ ?fTsrc/Components/Uploader.phpnu[PK!)NrTsrc/Components/ShortCode.phpnu[PK!Y&&zTsrc/Components/Repeater.phpnu[PK!M99(Tsrc/Components/PhoneField.phpnu[PK!КB2B2 xTsrc/Components/RepeaterField.phpnu[PK!6]X**# Tsrc/Components/RangeSliderField.phpnu[PK!@/,'Usrc/Components/ActionHook.phpnu[PK!-T::#f/Usrc/Components/NetPromoterScore.phpnu[PK!JJ-LUsrc/Integrations/ActiveCampaign/Bootstrap.phpnu[PK!iT""5'Usrc/Integrations/ActiveCampaign/ActiveCampaignApi.phpnu[PK!c11.Usrc/Integrations/AffiliateWP/AffiliateWPFF.phpnu[PK! CNN'Usrc/Integrations/Airtable/Bootstrap.phpnu[PK!d*U U !l)Vsrc/Integrations/Airtable/API.phpnu[PK!!gg%4Vsrc/Integrations/Amocrm/Bootstrap.phpnu[PK!;,9Vsrc/Integrations/Amocrm/API.phpnu[PK!TVS:S:'0Vsrc/Integrations/Automizy/Bootstrap.phpnu[PK!?[ !Wsrc/Integrations/Automizy/API.phpnu[PK!7@@%$Wsrc/Integrations/Aweber/Bootstrap.phpnu[PK!qZZ%:fWsrc/Integrations/Aweber/AweberApi.phpnu[PK! %h9xWsrc/Integrations/BuddyIntegration/FluentFormBuddyBoss.phpnu[PK!488.Wsrc/Integrations/CampaignMonitor/Bootstrap.phpnu[PK!'baa7Wsrc/Integrations/CampaignMonitor/CampaignMonitorApi.phpnu[PK!Z " : :*Wsrc/Integrations/CleverReach/Bootstrap.phpnu[PK!2PC33$!Xsrc/Integrations/CleverReach/API.phpnu[PK!SS(4Xsrc/Integrations/ClickSend/Bootstrap.phpnu[PK!8RV(SXsrc/Integrations/ClickSend/ClickSend.phpnu[PK!e]e]`G`G.{Xsrc/Integrations/ConstantContact/Bootstrap.phpnu[PK!/ (9*Ysrc/Integrations/ConstantContact/API.phpnu[PK!,h f7f7)8Ysrc/Integrations/ConvertKit/Bootstrap.phpnu[PK!L #JpYsrc/Integrations/ConvertKit/API.phpnu[PK!ѓ$"$"&{|Ysrc/Integrations/Discord/Bootstrap.phpnu[PK!RL$Ysrc/Integrations/Discord/Discord.phpnu[PK!nBB#3Ysrc/Integrations/Drip/Bootstrap.phpnu[PK!:݌4 4 !Ysrc/Integrations/Drip/DripApi.phpnu[PK!Im0m0&Ysrc/Integrations/GetGist/Bootstrap.phpnu[PK!Dέ Zsrc/Integrations/GetGist/API.phpnu[PK!Q݆33**Zsrc/Integrations/GetResponse/Bootstrap.phpnu[PK!*0)A$$/^Zsrc/Integrations/GetResponse/GetResponseApi.phpnu[PK!Z͔*Zsrc/Integrations/GoogleSheet/API/Sheet.phpnu[PK!###(Zsrc/Integrations/GoogleSheet/API/API.phpnu[PK!+#5#5*{Zsrc/Integrations/GoogleSheet/Bootstrap.phpnu[PK!/|EE&Zsrc/Integrations/Hubspot/Bootstrap.phpnu[PK!g  [src/Integrations/Hubspot/API.phpnu[PK!c)L)L'5[src/Integrations/IContact/Bootstrap.phpnu[PK!*L=VV)o[src/Integrations/IContact/IContactApi.phpnu[PK!/G6}}([src/Integrations/Insightly/Bootstrap.phpnu[PK!Z  "\src/Integrations/Insightly/API.phpnu[PK!r--)P\src/Integrations/MailerLite/Bootstrap.phpnu[PK!Mc  #;\src/Integrations/MailerLite/API.phpnu[PK!Qbaa&\src/Integrations/Mailjet/Bootstrap.phpnu[PK!$  G]src/Integrations/Mailjet/API.phpnu[PK!63+3+'UR]src/Integrations/Mailster/Bootstrap.phpnu[PK!C8//&}]src/Integrations/MooSend/Bootstrap.phpnu[PK!ц (]src/Integrations/MooSend/API.phpnu[PK!QKK*[]src/Integrations/NewAirtable/Bootstrap.phpnu[PK!⒗$h ^src/Integrations/NewAirtable/API.phpnu[PK!di4<<%S^src/Integrations/Notion/Bootstrap.phpnu[PK!/`ER^src/Integrations/Notion/API.phpnu[PK!]S)a^src/Integrations/OnePageCrm/Bootstrap.phpnu[PK!1]8# _src/Integrations/OnePageCrm/API.phpnu[PK!h4jj(8_src/Integrations/Pipedrive/Bootstrap.phpnu[PK!o| +_src/Integrations/Pipedrive/PipedriveApi.phpnu[PK!jG~ E E)̉_src/Integrations/Platformly/Bootstrap.phpnu[PK!  -2_src/Integrations/Platformly/PlatformlyApi.phpnu[PK!f],],._src/Integrations/SMSNotification/Bootstrap.phpnu[PK! ְc c .R `src/Integrations/SMSNotification/TwilioApi.phpnu[PK!H@;@;)`src/Integrations/Salesflare/Bootstrap.phpnu[PK!ʹ #O`src/Integrations/Salesflare/API.phpnu[PK!&T&T)Y`src/Integrations/Salesforce/Bootstrap.phpnu[PK![=mm#w`src/Integrations/Salesforce/API.phpnu[PK!n;[,[,&7`src/Integrations/SendFox/Bootstrap.phpnu[PK!}78dd `src/Integrations/SendFox/API.phpnu[PK!{e6e6)`src/Integrations/Sendinblue/Bootstrap.phpnu[PK!M-Z6asrc/Integrations/Sendinblue/SendinblueApi.phpnu[PK!*++'Easrc/Integrations/Telegram/Bootstrap.phpnu[PK!]  )qasrc/Integrations/Telegram/TelegramApi.phpnu[PK!wEwE%0|asrc/Integrations/Trello/Bootstrap.phpnu[PK!焪W W %asrc/Integrations/Trello/TrelloApi.phpnu[PK!P>P>/asrc/Integrations/UserRegistration/Bootstrap.phpnu[PK!&&,W bsrc/Integrations/UserRegistration/Getter.phpnu[PK!N?=?=;bsrc/Integrations/UserRegistration/UserUpdateFormHandler.phpnu[PK!^n5n59Ybsrc/Integrations/UserRegistration/UserRegistrationApi.phpnu[PK!D>>&Zbsrc/Integrations/WebHook/Bootstrap.phpnu[PK!8bE (bsrc/Integrations/WebHook/NotifyTrait.phpnu[PK!Z%%#ٿbsrc/Integrations/WebHook/Client.phpnu[PK!Rc%Qbsrc/Integrations/Zapier/Bootstrap.phpnu[PK!s/ 'bsrc/Integrations/Zapier/NotifyTrait.phpnu[PK!8n\u "bsrc/Integrations/Zapier/Client.phpnu[PK!<}a\a\&csrc/Integrations/ZohoCRM/Bootstrap.phpnu[PK!I*t$_csrc/Integrations/ZohoCRM/ZohoCRM.phpnu[PK!B++'ycsrc/Payments/Classes/PaymentEntries.phpnu[PK!]k&csrc/Payments/Classes/PaymentAction.phpnu[PK!R4a*<*dsrc/Payments/Classes/PaymentManagement.phpnu[PK!-/L})})'/9dsrc/Payments/Classes/PaymentReceipt.phpnu[PK!/$cdsrc/Payments/Classes/CouponModel.phpnu[PK!fu-ii)Wdsrc/Payments/Classes/CouponController.phpnu[PK!iSHH(dsrc/Payments/Components/Subscription.phpnu[PK! 957571idsrc/Payments/Components/MultiPaymentComponent.phpnu[PK!77*esrc/Payments/Components/PaymentMethods.phpnu[PK!Uh2)Gesrc/Payments/Components/CustomPaymentComponent.phpnu[PK! 5}}"[esrc/Payments/Components/Coupon.phpnu[PK!F 3^lesrc/Payments/Components/PaymentSummaryComponent.phpnu[PK!r(yesrc/Payments/Components/ItemQuantity.phpnu[PK!.ć%esrc/Payments/Migrations/Migration.phpnu[PK!.((.esrc/Payments/Migrations/OrderSubscriptions.phpnu[PK!½&esrc/Payments/Migrations/OrderItems.phpnu[PK!o ll(esrc/Payments/Migrations/Transactions.phpnu[PK!*~!Gesrc/Payments/Orders/OrderData.phpnu[PK!jo.esrc/Payments/PaymentMethods/Mollie/API/IPN.phpnu[PK!994esrc/Payments/PaymentMethods/Mollie/MollieHandler.phpnu[PK!Fv|!|!6esrc/Payments/PaymentMethods/Mollie/MollieProcessor.phpnu[PK![]`5jfsrc/Payments/PaymentMethods/Mollie/MollieSettings.phpnu[PK!""8fsrc/Payments/PaymentMethods/Offline/OfflineProcessor.phpnu[PK!)6<fsrc/Payments/PaymentMethods/Offline/OfflineHandler.phpnu[PK!v1]jXjX. fsrc/Payments/PaymentMethods/PayPal/API/IPN.phpnu[PK! 5jyfsrc/Payments/PaymentMethods/PayPal/PayPalSettings.phpnu[PK!fw;]]6ofsrc/Payments/PaymentMethods/PayPal/PayPalProcessor.phpnu[PK!%Qk k 4fsrc/Payments/PaymentMethods/PayPal/PayPalHandler.phpnu[PK!..:fsrc/Payments/PaymentMethods/Paystack/PaystackProcessor.phpnu[PK!'T9gsrc/Payments/PaymentMethods/Paystack/PaystackSettings.phpnu[PK!Dxo,G%gsrc/Payments/PaymentMethods/Paystack/API.phpnu[PK!8D?gsrc/Payments/PaymentMethods/Paystack/PaystackHandler.phpnu[PK!$YGG:]gsrc/Payments/PaymentMethods/RazorPay/RazorPayProcessor.phpnu[PK!Ϟ!!8ݥgsrc/Payments/PaymentMethods/RazorPay/RazorPayHandler.phpnu[PK!/P#9#gsrc/Payments/PaymentMethods/RazorPay/RazorPaySettings.phpnu[PK! i,~gsrc/Payments/PaymentMethods/RazorPay/API.phpnu[PK!wȅ334gsrc/Payments/PaymentMethods/Square/SquareHandler.phpnu[PK!Fq / /68hsrc/Payments/PaymentMethods/Square/SquareProcessor.phpnu[PK! e51hsrc/Payments/PaymentMethods/Square/SquareSettings.phpnu[PK!j鰤*7hsrc/Payments/PaymentMethods/Square/API.phpnu[PK!(449Lhsrc/Payments/PaymentMethods/Stripe/API/StripeListener.phpnu[PK!j:hsrc/Payments/PaymentMethods/Stripe/API/CheckoutSession.phpnu[PK!,[dd38hsrc/Payments/PaymentMethods/Stripe/API/Customer.phpnu[PK!.5hsrc/Payments/PaymentMethods/Stripe/API/ApiRequest.phpnu[PK!3~ ~ .hsrc/Payments/PaymentMethods/Stripe/API/SCA.phpnu[PK! 2϶hsrc/Payments/PaymentMethods/Stripe/API/Account.phpnu[PK!5u32hsrc/Payments/PaymentMethods/Stripe/API/Invoice.phpnu[PK!D; hsrc/Payments/PaymentMethods/Stripe/API/RequestProcessor.phpnu[PK!`(`(/Yhsrc/Payments/PaymentMethods/Stripe/API/Plan.phpnu[PK! E|C C >hsrc/Payments/PaymentMethods/Stripe/Components/StripeInline.phpnu[PK!%E0335hsrc/Payments/PaymentMethods/Stripe/StripeSettings.phpnu[PK!bk  5aisrc/Payments/PaymentMethods/Stripe/PaymentManager.phpnu[PK!8Tbb6"isrc/Payments/PaymentMethods/Stripe/StripeProcessor.phpnu[PK!%%г4isrc/Payments/PaymentMethods/Stripe/StripeHandler.phpnu[PK!G G G<isrc/Payments/PaymentMethods/Stripe/StripeInlineProcessor.phpnu[PK!7w4wisrc/Payments/PaymentMethods/Stripe/ConnectConfig.phpnu[PK!- jsrc/Payments/PaymentMethods/BaseProcessor.phpnu[PK!FGX@@1jsrc/Payments/PaymentMethods/BasePaymentMethod.phpnu[PK!=īījsrc/Payments/PaymentHelper.phpnu[PK!5^66Jksrc/Payments/AjaxEndpoints.phpnu[PK!sˌhh ksrc/Payments/PaymentHandler.phpnu[PK!GMM&ksrc/Payments/TransactionShortcodes.phpnu[PK!s9lsrc/Stubs/index.stubnu[PK!e9lsrc/Stubs/htaccess.stubnu[PK!fnc,f;lsrc/classes/AdminApproval/GlobalSettings.phpnu[PK!yEE+Xlsrc/classes/AdminApproval/AdminApproval.phpnu[PK!s s lsrc/classes/Chat/ChatApi.phpnu[PK!RˊWII(Ylsrc/classes/Chat/ChatFieldController.phpnu[PK!u:)@)@$lsrc/classes/Chat/ChatFormBuilder.phpnu[PK!ZRP#P#%4msrc/classes/Chat/ChatField.phpnu[PK!%5Wmsrc/classes/EntriesImport/EntriesImportController.phpnu[PK!|w,"WW2_msrc/classes/EntriesImport/EntriesImportService.phpnu[PK!x7H,H,15msrc/classes/Inventory/InventoryFieldsRenderer.phpnu[PK!+j6L6L-msrc/classes/Inventory/InventoryValidation.phpnu[PK!+e---q0nsrc/classes/Inventory/InventoryController.phpnu[PK!X~!!'^nsrc/classes/Inventory/InventoryList.phpnu[PK!~h+#&&2nsrc/classes/Inventory/InventorySettingsManager.phpnu[PK!"Qvv#Ϧnsrc/classes/Quiz/QuizController.phpnu[PK!.R # #'5osrc/classes/Quiz/QuizScoreComponent.phpnu[PK!Hz('('#@osrc/classes/SharePage/SharePage.phpnu[PK!unMMhosrc/classes/DoubleOptin.phpnu[PK! !=ttosrc/classes/FormStyler.phpnu[PK!_<psrc/classes/FormModal.phpnu[PK!䳯V  #psrc/classes/AddressAutoComplete.phpnu[PK!)zoopsrc/classes/Calculation.phpnu[PK!a̹NNpsrc/classes/StepFormEntries.phpnu[PK!^&,qsrc/classes/AdvancedFormValidation.phpnu[PK!:`or>r>)4qsrc/classes/ResendNotificationHandler.phpnu[PK!~qsqsrc/classes/ProSmartCodes.phpnu[PK!Ae-zqsrc/classes/FailedIntegrationNotification.phpnu[PK!+JD~~#qsrc/classes/FormStylerGenerator.phpnu[PK!C%%-rsrc/classes/SurveyResultProcessor.phpnu[PK!̍ Jrsrc/classes/EntryEditor.phpnu[PK!1:ah h Trsrc/classes/Analytics.phpnu[PK!}>j>j'brsrc/classes/DraftSubmissionsManager.phpnu[PK! r "rsrc/classes/ConditionalContent.phpnu[PK!f__)Frsrc/views/receipt/transaction_details.phpnu[PK!F x .rsrc/views/receipt/user_subscriptions_table.phpnu[PK!;rsrc/views/receipt/header.phpnu[PK! g) rsrc/views/receipt/subscriptions_table.phpnu[PK!kL Nrsrc/views/receipt/custom_css.phpnu[PK!#ss&zrsrc/views/receipt/customer_details.phpnu[PK! 9&Crsrc/views/receipt/transaction_info.phpnu[PK!XXX0Tssrc/views/receipt/user_subscription_payments.phpnu[PK! ssrc/views/receipt/index.phpnu[PK!qssrc/views/receipt/body.phpnu[PK!b "ssrc/views/receipt/payment_info.phpnu[PK!g'ssrc/views/receipt/payment_info_list.phpnu[PK![( ssrc/views/receipt/transactions_table.phpnu[PK!K2}II'+ssrc/views/receipt/order_items_table.phpnu[PK!k k 2ssrc/views/frameless_view.phpnu[PK!cJU>ssrc/views/landing_page_view.phpnu[PK!U>Ussrc/views/analytics_view.phpnu[PK!=~~Ussrc/views/inventory_list.phpnu[PK!'ݙyyrVssrc/views/step_form_entries.phpnu[PK!T :Wssrc/index.phpnu[PK!fRRWssrc/Uploader.phpnu[PK!c$zjzj\sfluentformpro.phpnu[PK!ɸQHH treadme.txtnu[PK!j tautoload.phpnu[PK!T tindex.phpnu[PK@@5t