app = $app; } public function registerScripts() { $app = $this->app; // We will just register the scripts here. We will not load any scripts from here $fluentFormPublicCss = $app->publicUrl('css/fluent-forms-public.css'); $fluentFormPublicDefaultCss = $app->publicUrl('css/fluentform-public-default.css'); if (is_rtl()) { $fluentFormPublicCss = $app->publicUrl('css/fluent-forms-public-rtl.css'); $fluentFormPublicDefaultCss = $app->publicUrl('css/fluentform-public-default-rtl.css'); } wp_register_style( 'fluent-form-styles', $fluentFormPublicCss, array(), FLUENTFORM_VERSION ); wp_register_style( 'fluentform-public-default', $fluentFormPublicDefaultCss, array(), FLUENTFORM_VERSION ); wp_register_script( 'fluent-form-submission', $app->publicUrl('js/form-submission.js'), array('jquery'), FLUENTFORM_VERSION, true ); wp_register_script( 'fluentform-advanced', $app->publicUrl('js/fluentform-advanced.js'), array('jquery', 'fluent-form-submission'), FLUENTFORM_VERSION, true ); // Date Pickckr Style wp_register_style( 'flatpickr', $app->publicUrl('libs/flatpickr/flatpickr.min.css') ); // Date Pickckr Script wp_register_script( 'flatpickr', $app->publicUrl('libs/flatpickr/flatpickr.js'), array('jquery'), false, true ); wp_register_script( 'selectWoo', $app->publicUrl('libs/selectWoo/selectWoo.full.min.js'), array('jquery'), '1.0.6', true ); wp_register_style( 'select2', $app->publicUrl('libs/selectWoo/select2.css') ); do_action('fluentform_scripts_registered'); $this->maybeLoadFluentFormStyles(); } protected function maybeLoadFluentFormStyles() { global $post; if (!$post) { return; } $fluentFormIds = get_post_meta($post->ID, '_has_fluentform', true); $hasFluentformMeta = is_a($post, 'WP_Post') && $fluentFormIds; if ($hasFluentformMeta || apply_filters('fluentform_load_styles', false, $post)) { wp_enqueue_style('fluent-form-styles'); wp_enqueue_style('fluentform-public-default'); do_action('fluentform_pre_load_scripts', $post); wp_enqueue_script('fluent-form-submission'); } } /** * Get all the available components * * @return void * @throws \Exception * @throws \FluentForm\Framework\Exception\UnResolveableEntityException */ public function index() { $this->app->doAction( 'fluent_editor_init', $components = $this->app->make('components') ); $editorComponents = $components->sort()->toArray(); $editorComponents = $this->app->applyFilters('fluent_editor_components', $editorComponents); $countries = $this->app->load($this->app->appPath('Services/FormBuilder/CountryNames.php')); wp_send_json_success(array( 'countries' => $countries, 'components' => $editorComponents, 'disabled_components' => $this->getDisabledComponents() )); } /** * Get disabled components * * @return array */ private function getDisabledComponents() { $isReCaptchaDisabled = !get_option('_fluentform_reCaptcha_keys_status', false); $disabled = array( 'recaptcha' => array( 'contentComponent' => 'recaptcha', 'disabled' => $isReCaptchaDisabled ), 'input_image' => array( 'disabled' => true ), 'input_file' => array( 'disabled' => true ), 'shortcode' => array( 'disabled' => true ), 'action_hook' => array( 'disabled' => true ), 'form_step' => array( 'disabled' => true ) ); if (!defined('FLUENTFORMPRO')) { $disabled['ratings'] = array( 'disabled' => true ); $disabled['tabular_grid'] = array( 'disabled' => true ); $disabled['phone'] = array( 'disabled' => true ); $disabled['net_promoter_score'] = array( 'disabled' => true ); $disabled['repeater_field'] = array( 'disabled' => true ); $disabled['custom_submit_button'] = array( 'disabled' => true ); $disabled['rangeslider'] = array( 'disabled' => true ); $disabled['color-picker'] = array( 'disabled' => true ); $disabled['multi_payment_component'] = array( 'disabled' => true, 'is_payment' => true ); $disabled['custom_payment_component'] = array( 'disabled' => true, 'is_payment' => true ); $disabled['item_quantity_component'] = array( 'disabled' => true, 'is_payment' => true ); $disabled['payment_method'] = array( 'disabled' => true, 'is_payment' => true ); } return $this->app->applyFilters('fluentform_disabled_components', $disabled); } /** * Get available shortcodes for editor * * @return void * @throws \Exception */ public function getEditorShortcodes() { $editor_shortcodes = fluentFormEditorShortCodes(); wp_send_json_success(['shortcodes' => $editor_shortcodes], 200); } /** * Get all available shortcodes for editor * * @return void * @throws \Exception */ public function getAllEditorShortcodes() { wp_send_json(fluentFormGetAllEditorShortCodes( $this->app->request->get('formId') ), 200); } /** * Register the form renderer shortcode * * @return void */ public function addFluentFormShortCode() { add_action('wp_enqueue_scripts', array($this, 'registerScripts'), 999); $this->app->addShortCode('fluentform', function ($atts, $content) { $shortcodeDefaults = apply_filters('fluentform_shortcode_defaults', array( 'id' => null, 'title' => null, 'permission' => '', 'permission_message' => __('Sorry, You do not have permission to view this form', 'fluentform') ), $atts); $atts = shortcode_atts($shortcodeDefaults, $atts); return $this->renderForm($atts); }); $this->app->addShortCode('fluentform_info', function ($atts) { $shortcodeDefaults = apply_filters('fluentform_info_shortcode_defaults', array( 'id' => null, // This is the form id 'info' => 'submission_count', // submission_count | created_at | updated_at | payment_total 'status' => 'all', // get submission cound of a particular entry status favourites | unread | read 'with_trashed' => 'no', // yes | no 'substract_from' => 0, // [fluentform_info id="2" info="submission_count" substract_from="20"] 'hide_on_zero' => 'no', 'payment_status' => 'paid', // it can be all / specific payment status 'currency_formatted' => 'yes', 'date_format' => '' ), $atts); $atts = shortcode_atts($shortcodeDefaults, $atts); $formId = $atts['id']; $form = wpFluent()->table('fluentform_forms')->find($formId); if (!$form) { return ''; } if ($atts['info'] == 'submission_count') { $countQuery = wpFluent()->table('fluentform_submissions') ->where('form_id', $formId); if ($atts['status'] != 'trashed' && $atts['with_trashed'] == 'no') { $countQuery = $countQuery->where('status', '!=', 'trashed'); } if ($atts['status'] == 'all') { // ... } else if ($atts['status'] == 'favourites') { $countQuery = $countQuery->where('is_favourite', '=', 1); } else { $countQuery = $countQuery->where('status', '=', sanitize_text_field($atts['status'])); } $total = $countQuery->count(); if ($atts['substract_from']) { $total = intval($atts['substract_from']) - $total; } if ($atts['hide_on_zero'] == 'yes' && !$total || $total < 0) { return ''; } return $total; } else if ($atts['info'] == 'created_at') { if ($atts['date_format']) { $dateFormat = $atts['date_format']; } else { $dateFormat = get_option('date_format') . ' ' . get_option('time_format'); } return date($dateFormat, strtotime($form->created_at)); } else if ($atts['info'] == 'updated_at') { if ($atts['date_format']) { $dateFormat = $atts['date_format']; } else { $dateFormat = get_option('date_format') . ' ' . get_option('time_format'); } return date($dateFormat, strtotime($form->updated_at)); } else if ($atts['info'] == 'payment_total') { if (!defined('FLUENTFORMPRO')) { return ''; } global $wpdb; $countQuery = wpFluent() ->table('fluentform_submissions') ->select(wpFluent()->raw('SUM(total_paid) as payment_total')) ->where('form_id', $formId); if ($atts['status'] != 'trashed' && $atts['with_trashed'] == 'no') { $countQuery = $countQuery->where('status', '!=', 'trashed'); } if ($atts['status'] == 'all') { // ... } else if ($atts['status'] == 'favourites') { $countQuery = $countQuery->where('is_favourite', '=', 1); } else { $countQuery = $countQuery->where('status', '=', sanitize_text_field($atts['status'])); } if ($atts['payment_status'] == 'all') { // ... } else if ($atts['payment_status']) { $countQuery = $countQuery->where('payment_status', '=', sanitize_text_field($atts['payment_status'])); } $row = $countQuery->first(); $total = 0; if ($row) { $total = $row->payment_total; } if ($atts['substract_from']) { $total = intval($atts['substract_from'] * 100) - $total; } if ($atts['hide_on_zero'] == 'yes' && !$total) { return ''; } if ($atts['currency_formatted'] == 'yes') { $currency = \FluentFormPro\Payments\PaymentHelper::getFormCurrency($formId); return \FluentFormPro\Payments\PaymentHelper::formatMoney($total, $currency); } if (!$total) { return 0; } return $total / 100; } return ''; }); $this->app->addShortCode('ff_get', function ($atts) { $atts = shortcode_atts(array( 'param' => '', ), $atts); if ($atts['param'] && isset($_GET[$atts['param']])) { $value = $_GET[$atts['param']]; if (is_array($value)) { return implode(', ', $value); } return esc_html($value); } return ''; }); } public function renderForm($atts) { $form_id = $atts['id']; if ($form_id) { $form = wpFluent()->table('fluentform_forms')->find($form_id); } else if ($formTitle = $atts['title']) { $form = wpFluent()->table('fluentform_forms')->where('title', $formTitle)->first(); } else { return; } if (!$form) { return; } if (!empty($atts['permission'])) { if (!current_user_can($atts['permission'])) { return "
{$atts['permission_message']}
"; } } if(is_feed()) { global $post; $feedText = sprintf( __( 'The form can be filled in the actual website url.', 'fluentform' ), get_permalink($post)); $feedText = apply_filters('fluentform_shortcode_feed_text', $feedText, $form); return $feedText; } $formSettings = wpFluent() ->table('fluentform_form_meta') ->where('form_id', $form_id) ->where('meta_key', 'formSettings') ->first(); if (!$formSettings) { return; } $form->fields = json_decode($form->form_fields, true); if (!$form->fields['fields']) { return; } $form->settings = json_decode($formSettings->value, true); $form = $this->app->applyFilters('fluentform_rendering_form', $form); $isRenderable = array( 'status' => true, 'message' => '' ); $isRenderable = $this->app->applyFilters('fluentform_is_form_renderable', $isRenderable, $form); if (is_array($isRenderable) && !$isRenderable['status']) { return "
{$isRenderable['message']}
"; } $instanceCssClass = Helper::getFormInstaceClass($form->id); $form->instance_css_class = $instanceCssClass; $formBuilder = $this->app->make('formBuilder'); $output = $formBuilder->build($form, $instanceCssClass . ' ff-form-loading', $instanceCssClass); $output = $this->replaceEditorSmartCodes($output, $form); if (!wp_script_is('fluent-form-submission', 'registered')) { $this->registerScripts(); } wp_enqueue_style('fluent-form-styles'); if (apply_filters('fluentform_load_default_public', true, $form)) { wp_enqueue_style('fluentform-public-default'); } wp_enqueue_script('fluent-form-submission'); /* * We will load fluentform-advanced if the form has certain fields or feature */ $this->maybeHasAdvandedFields($form, $formBuilder); $stepText = __('Step %activeStep% of %totalStep% - %stepTitle%', 'fluentform'); $stepText = apply_filters('fluentform_step_string', $stepText); $vars = apply_filters('fluentform_global_form_vars', array( 'ajaxUrl' => admin_url('admin-ajax.php'), 'forms' => array(), 'step_text' => $stepText, 'is_rtl' => is_rtl(), 'date_i18n' => $this->getDatei18n(), 'pro_version' => (defined('FLUENTFORMPRO_VERSION')) ? FLUENTFORMPRO_VERSION : false, 'fluentform_version' => FLUENTFORM_VERSION, 'force_init' => false, 'stepAnimationDuration' => 350, 'upload_completed_txt' => __('100% Completed', 'fluentform'), 'upload_start_txt' => __('0% Completed', 'fluentform'), 'uploading_txt' => __('Uploading', 'fluentform') )); wp_localize_script('fluent-form-submission', 'fluentFormVars', $vars); $formSettings = $form->settings; $formSettings = ArrayHelper::only($formSettings, ['layout', 'id']); $formSettings['restrictions']['denyEmptySubmission'] = [ 'enabled' => false ]; $form_vars = array( 'id' => $form->id, 'settings' => $formSettings, 'form_instance' => $instanceCssClass, 'form_id_selector' => 'fluentform_' . $form->id, 'rules' => $formBuilder->validationRules ); if ($conditionals = $formBuilder->conditions) { $form_vars['conditionals'] = $conditionals; } if ($form->has_payment) { do_action('fluentform_rending_payment_form', $form); } $otherScripts = ''; ob_start(); ?> addInlineVars(); $otherScripts .= ob_get_clean(); if (!apply_filters('fluentform-disabled_analytics', false)) { if (!Acl::hasAnyFormPermission($form->id)) { (new \FluentForm\App\Modules\Form\Analytics($this->app))->record($form->id); } } return $output . $otherScripts; } /** * Process the output HTML to generate the default values. * * @param string $output * @param \stdClass $form * @return string */ public function replaceEditorSmartCodes($output, $form) { // Get the patterns for default values from the output HTML string. // The example of a pattern would be for user ID: {user.ID} preg_match_all('/{(.*?)}/', $output, $matches); $patterns = array_unique($matches[0]); $attrDefaultValues = []; foreach ($patterns as $pattern) { // The default value for each pattern will be resolved here. $attrDefaultValues[$pattern] = apply_filters('fluentform_parse_default_value', $pattern, $form); } // Raising an event so that others can hook into it and modify the default values later. $attrDefaultValues = (array)apply_filters('fluentform_parse_default_values', $attrDefaultValues); if (isset($attrDefaultValues['{payment_total}'])) { $attrDefaultValues['{payment_total}'] = ''; } // Finally, replace the patterns with the replacements and return the output HTML. return str_replace(array_keys($attrDefaultValues), array_values($attrDefaultValues), $output); } /** * Register renderer actions for compiling each element * * @return void */ public function addRendererActions() { $actionMappings = [ 'Select@compile' => ['fluentform_render_item_select'], 'Rating@compile' => ['fluentform_render_item_ratings'], 'Address@compile' => ['fluentform_render_item_address'], 'Name@compile' => ['fluentform_render_item_input_name'], 'TextArea@compile' => ['fluentform_render_item_textarea'], 'DateTime@compile' => ['fluentform_render_item_input_date'], 'Recaptcha@compile' => ['fluentform_render_item_recaptcha'], 'Container@compile' => ['fluentform_render_item_container'], 'CustomHtml@compile' => ['fluentform_render_item_custom_html'], 'SectionBreak@compile' => ['fluentform_render_item_section_break'], 'SubmitButton@compile' => ['fluentform_render_item_submit_button'], 'SelectCountry@compile' => ['fluentform_render_item_select_country'], 'TermsAndConditions@compile' => [ 'fluentform_render_item_terms_and_condition', 'fluentform_render_item_gdpr_agreement' ], 'TabularGrid@compile' => [ 'fluentform_render_item_tabular_grid' ], 'Checkable@compile' => [ 'fluentform_render_item_input_radio', 'fluentform_render_item_input_checkbox', ], 'Text@compile' => [ 'fluentform_render_item_input_url', 'fluentform_render_item_input_text', 'fluentform_render_item_input_email', 'fluentform_render_item_input_number', 'fluentform_render_item_input_hidden', 'fluentform_render_item_input_password', ], ]; $path = 'FluentForm\App\Services\FormBuilder\Components\\'; foreach ($actionMappings as $handler => $actions) { foreach ($actions as $action) { $this->app->addAction($action, function () use ($path, $handler) { list($class, $method) = $this->app->parseHandler($path . $handler); call_user_func_array(array($class, $method), func_get_args()); }, 10, 2); } } } /** * Register dynamic value shortcode parser (filter default value) * * @return void */ public function addFluentFormDefaultValueParser() { $this->app->addFilter('fluentform_parse_default_value', function ($value, $form) { return EditorShortcodeParser::filter($value, $form); }, 10, 2); } /** * Register filter to check whether the form is renderable * * @return mixed */ public function addIsRenderableFilter() { $this->app->addFilter('fluentform_is_form_renderable', function ($isRenderable, $form) { $checkables = array('limitNumberOfEntries', 'scheduleForm', 'requireLogin'); foreach ($form->settings['restrictions'] as $key => $restrictions) { if (in_array($key, $checkables)) { $isRenderable['status'] = $this->{$key}($restrictions, $form, $isRenderable); if (!$isRenderable['status']) { $isRenderable['status'] = false; return $isRenderable; } } } return $isRenderable; }, 10, 2); } /** * Check if limit is set on form submits and it's valid yet * * @param array $restrictions * * @return bool */ private function limitNumberOfEntries($restrictions, $form, &$isRenderable) { if (!$restrictions['enabled']) { return true; } $col = 'created_at'; $period = $restrictions['period']; $maxAllowedEntries = $restrictions['numberOfEntries']; if (!$maxAllowedEntries) { return true; } $query = wpFluent()->table('fluentform_submissions') ->where('form_id', $form->id) ->where('status', '!=', 'trashed'); if ($period == 'day') { $year = "YEAR(`{$col}`) = YEAR(NOW())"; $month = "MONTH(`{$col}`) = MONTH(NOW())"; $day = "DAY(`{$col}`) = DAY(NOW())"; $query->where(wpFluent()->raw("{$year} AND {$month} AND {$day}")); } elseif ($period == 'week') { $query->where( wpFluent()->raw("YEARWEEK(`{$col}`, 1) = YEARWEEK(CURDATE(), 1)") ); } elseif ($period == 'month') { $year = "YEAR(`{$col}`) = YEAR(NOW())"; $month = "MONTH(`{$col}`) = MONTH(NOW())"; $query->where(wpFluent()->raw("{$year} AND {$month}")); } elseif ($period == 'year') { $query->where(wpFluent()->raw("YEAR(`{$col}`) = YEAR(NOW())")); } else if ($period == 'per_user_ip') { $ip = $this->app->request->getIp(); $query->where('ip', $ip); } else if ($period == 'per_user_id') { $userId = get_current_user_id(); if (!$userId) { return true; } $query->where('user_id', $userId); } $count = $query->count(); if ($count >= $maxAllowedEntries) { $isRenderable['message'] = $restrictions['limitReachedMsg']; return false; } return true; } /** * Check if form has scheduled date and open for submission * * @param array $restrictions * * @return bool */ private function scheduleForm($restrictions, $form, &$isRenderable) { if (!$restrictions['enabled']) { return true; } $time = time(); $start = strtotime($restrictions['start']); $end = strtotime($restrictions['end']); if ($time < $start) { $isRenderable['message'] = $restrictions['pendingMsg']; return false; } if ($time >= $end) { $isRenderable['message'] = $restrictions['expiredMsg']; return false; } return true; } /** * * Check if form requires loged in user and user is logged in * * @param array $restrictions * * @return bool */ private function requireLogin($restrictions, $form, &$isRenderable) { if (!$restrictions['enabled']) { return true; } if (!($isLoggedIn = is_user_logged_in())) { $isRenderable['message'] = $restrictions['requireLoginMsg']; } return $isLoggedIn; } /** * Register fluentform_submission_inserted actions * * @return void */ public function addFluentformSubmissionInsertedFilter() { (new EmailNotificationActions($this->app))->register(); } /** * Add inline scripts [Add localized script using same var] * * @return void */ private function addInlineVars() { if (!defined('ELEMENTOR_PRO_VERSION')) { return ''; } $actionName = 'wp_footer'; if (is_admin()) { $actionName = 'admin_footer'; } add_action($actionName, function () { ?> __('Previous Month', 'fluentform'), 'nextMonth' => __('Next Month', 'fluentform'), 'months' => [ 'shorthand' => [ __('Jan', 'fluentform'), __('Feb', 'fluentform'), __('Mar', 'fluentform'), __('Apr', 'fluentform'), __('May', 'fluentform'), __('Jun', 'fluentform'), __('Jul', 'fluentform'), __('Aug', 'fluentform'), __('Sep', 'fluentform'), __('Oct', 'fluentform'), __('Nov', 'fluentform'), __('Dec', 'fluentform') ], 'longhand' => [ __('January', 'fluentform'), __('February', 'fluentform'), __('March', 'fluentform'), __('April', 'fluentform'), __('May', 'fluentform'), __('June', 'fluentform'), __('July', 'fluentform'), __('August', 'fluentform'), __('September', 'fluentform'), __('October', 'fluentform'), __('November', 'fluentform'), __('December', 'fluentform') ] ], 'weekdays' => [ 'longhand' => array( __('Sunday', 'fluentform'), __('Monday', 'fluentform'), __('Tuesday', 'fluentform'), __('Wednesday', 'fluentform'), __('Thursday', 'fluentform'), __('Friday', 'fluentform'), __('Saturday', 'fluentform') ), 'shorthand' => array( __('Sun', 'fluentform'), __('Mon', 'fluentform'), __('Tue', 'fluentform'), __('Wed', 'fluentform'), __('Thu', 'fluentform'), __('Fri', 'fluentform'), __('Sat', 'fluentform') ) ], 'daysInMonth' => [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ], 'rangeSeparator' => __(' to ', 'fluentform'), 'weekAbbreviation' => __('Wk', 'fluentform'), 'scrollTitle' => __('Scroll to increment', 'fluentform'), 'toggleTitle' => __('Click to toggle', 'fluentform'), 'amPM' => [ __('AM', 'fluentform'), __('PM', 'fluentform') ], 'yearAriaLabel' => __('Year', 'fluentform') ); return apply_filters('fluentform/date_i18n', $i18n); } protected function maybeHasAdvandedFields($form, $formBuilder) { $advancedFields = [ 'step_start', 'repeater_field', 'ratings', 'form_step', 'input_file', 'input_image', 'net_promoter_score', 'featured_image' ]; if ($formBuilder->conditions || array_intersect($formBuilder->fieldLists, $advancedFields)) { wp_enqueue_script('fluentform-advanced'); } } }