PageRenderTime 44ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

/plugins/gravityforms/form_display.php

https://github.com/petergibbons/OpenCounterWP
PHP | 2273 lines | 2022 code | 195 blank | 56 comment | 205 complexity | a191c52941c7534290aaeb132dcaa2d6 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. class GFFormDisplay{
  3. public static $submission = array();
  4. private static $init_scripts = array();
  5. const ON_PAGE_RENDER = 1;
  6. const ON_CONDITIONAL_LOGIC = 2;
  7. public static function process_form($form_id){
  8. //reading form metadata
  9. $form = RGFormsModel::get_form_meta($form_id);
  10. $form = RGFormsModel::add_default_properties($form);
  11. $lead = array();
  12. $field_values = RGForms::post("gform_field_values");
  13. $confirmation_message = "";
  14. $source_page_number = self::get_source_page($form_id);
  15. $page_number = $source_page_number;
  16. $target_page = self::get_target_page($form, $page_number, $field_values);
  17. //Loading files that have been uploaded to temp folder
  18. $files = GFCommon::json_decode(stripslashes(RGForms::post("gform_uploaded_files")));
  19. if(!is_array($files))
  20. $files = array();
  21. RGFormsModel::$uploaded_files[$form["id"]] = $files;
  22. $is_valid = true;
  23. //don't validate when going to previous page
  24. if(empty($target_page) || $target_page >= $page_number){
  25. $is_valid = self::validate($form, $field_values, $page_number);
  26. }
  27. //Upload files to temp folder when going to the next page or when submitting the form and it failed validation
  28. if( $target_page >= $page_number || ($target_page == 0 && !$is_valid) ){
  29. //Uploading files to temporary folder
  30. $files = self::upload_files($form, $files);
  31. RGFormsModel::$uploaded_files[$form["id"]] = $files;
  32. }
  33. // Load target page if it did not fail validation or if going to the previous page
  34. if($is_valid){
  35. $page_number = $target_page;
  36. }
  37. $confirmation = "";
  38. if($is_valid && $page_number == 0){
  39. $ajax = isset($_POST["gform_ajax"]);
  40. //adds honeypot field if configured
  41. if(rgar($form,"enableHoneypot"))
  42. $form["fields"][] = self::get_honeypot_field($form);
  43. $failed_honeypot = rgar($form,"enableHoneypot") && !self::validate_honeypot($form);
  44. if($failed_honeypot){
  45. //display confirmation but doesn't process the form when honeypot fails
  46. $confirmation = self::handle_confirmation($form, $lead, $ajax);
  47. $is_valid = false;
  48. }
  49. else{
  50. //pre submission action
  51. do_action("gform_pre_submission", $form);
  52. do_action("gform_pre_submission_{$form["id"]}", $form);
  53. //pre submission filter
  54. $form = apply_filters("gform_pre_submission_filter_{$form["id"]}", apply_filters("gform_pre_submission_filter", $form));
  55. //handle submission
  56. $confirmation = self::handle_submission($form, $lead, $ajax);
  57. //after submission hook
  58. do_action("gform_after_submission", $lead, $form);
  59. do_action("gform_after_submission_{$form["id"]}", $lead, $form);
  60. }
  61. if(is_array($confirmation) && isset($confirmation["redirect"])){
  62. header("Location: {$confirmation["redirect"]}");
  63. do_action("gform_post_submission", $lead, $form);
  64. do_action("gform_post_submission_{$form["id"]}", $lead, $form);
  65. exit;
  66. }
  67. }
  68. if(!isset(self::$submission[$form_id]))
  69. self::$submission[$form_id] = array();
  70. self::set_submission_if_null($form_id, "is_valid", $is_valid);
  71. self::set_submission_if_null($form_id, "form", $form);
  72. self::set_submission_if_null($form_id, "lead", $lead);
  73. self::set_submission_if_null($form_id, "confirmation_message", $confirmation);
  74. self::set_submission_if_null($form_id, "page_number", $page_number);
  75. self::set_submission_if_null($form_id, "source_page_number", $source_page_number);
  76. }
  77. private static function set_submission_if_null($form_id, $key, $val){
  78. if(!isset(self::$submission[$form_id][$key]))
  79. self::$submission[$form_id][$key] = $val;
  80. }
  81. private static function upload_files($form, $files){
  82. //Creating temp folder if it does not exist
  83. $target_path = RGFormsModel::get_upload_path($form["id"]) . "/tmp/";
  84. wp_mkdir_p($target_path);
  85. foreach($form["fields"] as $field){
  86. $input_name = "input_{$field["id"]}";
  87. //skip fields that are not file upload fields or that don't have a file to be uploaded or that have failed validation
  88. $input_type = RGFormsModel::get_input_type($field);
  89. if(!in_array($input_type, array("fileupload", "post_image")) || $field["failed_validation"] || empty($_FILES[$input_name]["name"])){
  90. continue;
  91. }
  92. $file_info = RGFormsModel::get_temp_filename($form["id"], $input_name);
  93. if($file_info && move_uploaded_file($_FILES[$input_name]['tmp_name'], $target_path . $file_info["temp_filename"])){
  94. $files[$input_name] = $file_info["uploaded_filename"];
  95. }
  96. }
  97. return $files;
  98. }
  99. public static function get_state($form, $field_values){
  100. $product_fields = array();
  101. foreach($form["fields"] as $field){
  102. if(GFCommon::is_product_field($field["type"]) || $field["type"] == "donation"){
  103. $value = RGFormsModel::get_field_value($field, $field_values, false);
  104. $value = self::default_if_empty($field, $value);
  105. switch($field["inputType"]){
  106. case "calculation" :
  107. case "singleproduct" :
  108. case "hiddenproduct" :
  109. $price = !is_array($value) || empty($value[$field["id"] . ".2"]) ? $field["basePrice"] : $value[$field["id"] . ".2"];
  110. if(empty($price))
  111. $price = 0;
  112. $price = GFCommon::to_number($price);
  113. $product_name = !is_array($value) || empty($value[$field["id"] . ".1"]) ? $field["label"] : $value[$field["id"] . ".1"];
  114. $product_fields[$field["id"]. ".1"] = wp_hash($product_name);
  115. $product_fields[$field["id"]. ".2"] = wp_hash($price);
  116. break;
  117. case "singleshipping" :
  118. $price = !empty($value) ? $value : $field["basePrice"];
  119. $price = GFCommon::to_number($price);
  120. $product_fields[$field["id"]] = wp_hash($price);
  121. break;
  122. case "radio" :
  123. case "select" :
  124. $product_fields[$field["id"]] = array();
  125. foreach($field["choices"] as $choice){
  126. $field_value = !empty($choice["value"]) || rgar($field,"enableChoiceValue") ? $choice["value"] : $choice["text"];
  127. if($field["enablePrice"])
  128. $field_value .= "|" . GFCommon::to_number(rgar($choice,"price"));
  129. $product_fields[$field["id"]][] = wp_hash($field_value);
  130. }
  131. break;
  132. case "checkbox" :
  133. $index = 1;
  134. foreach($field["choices"] as $choice){
  135. $field_value = !empty($choice["value"]) || $field["enableChoiceValue"] ? $choice["value"] : $choice["text"];
  136. if($field["enablePrice"])
  137. $field_value .= "|" . GFCommon::to_number($choice["price"]);
  138. if($index % 10 == 0) //hack to skip numbers ending in 0. so that 5.1 doesn't conflict with 5.10
  139. $index++;
  140. $product_fields[$field["id"] . "." . $index++] = wp_hash($field_value);
  141. }
  142. break;
  143. }
  144. }
  145. }
  146. $hash = serialize($product_fields);
  147. $checksum = wp_hash(crc32($hash));
  148. return base64_encode(serialize(array($hash, $checksum)));
  149. }
  150. private static function has_pages($form){
  151. return GFCommon::has_pages($form);
  152. }
  153. private static function has_character_counter($form){
  154. if(!is_array($form["fields"]))
  155. return false;
  156. foreach($form["fields"] as $field){
  157. if(rgar($field, "maxLength") && !rgar($field, "inputMask"))
  158. return true;
  159. }
  160. return false;
  161. }
  162. private static function has_enhanced_dropdown($form){
  163. if(!is_array($form["fields"]))
  164. return false;
  165. foreach($form["fields"] as $field){
  166. if(in_array(RGFormsModel::get_input_type($field), array("select", "multiselect")) && rgar($field, "enableEnhancedUI"))
  167. return true;
  168. }
  169. return false;
  170. }
  171. private static function has_password_strength($form){
  172. if(!is_array($form["fields"]))
  173. return false;
  174. foreach($form["fields"] as $field){
  175. if($field["type"] == "password" && RGForms::get("passwordStrengthEnabled", $field))
  176. return true;
  177. }
  178. return false;
  179. }
  180. private static function has_other_choice($form){
  181. if(!is_array($form["fields"]))
  182. return false;
  183. foreach($form["fields"] as $field){
  184. if($field["type"] == "radio" && rgget("enableOtherChoice", $field))
  185. return true;
  186. }
  187. return false;
  188. }
  189. public static function get_target_page($form, $current_page, $field_values){
  190. $page_number = RGForms::post("gform_target_page_number_{$form["id"]}");
  191. $page_number = !is_numeric($page_number) ? 1 : $page_number;
  192. $direction = $page_number >= $current_page ? 1 : -1;
  193. //Finding next page that is not hidden by conditional logic
  194. while(RGFormsModel::is_page_hidden($form, $page_number, $field_values)){
  195. $page_number += $direction;
  196. }
  197. //If all following pages are hidden, submit the form
  198. if($page_number > self::get_max_page_number($form))
  199. $page_number = 0;
  200. return $page_number;
  201. }
  202. public static function get_source_page($form_id){
  203. $page_number = RGForms::post("gform_source_page_number_{$form_id}");
  204. return !is_numeric($page_number) ? 1 : $page_number;
  205. }
  206. public static function set_current_page($form_id, $page_number){
  207. self::$submission[$form_id]["page_number"] = $page_number;
  208. }
  209. public static function get_current_page($form_id){
  210. $page_number = isset(self::$submission[$form_id]) ? self::$submission[$form_id]["page_number"] : 1;
  211. return $page_number;
  212. }
  213. private static function is_page_active($form_id, $page_number){
  214. return intval(self::get_current_page($form_id)) == intval($page_number);
  215. }
  216. private static function get_limit_period_dates($period){
  217. if(empty($period))
  218. return array("start_date" => null, "end_date" => null);
  219. switch($period){
  220. case "day" :
  221. return array(
  222. "start_date" => gmdate("Y-m-d"),
  223. "end_date" => gmdate("Y-m-d"));
  224. break;
  225. case "week" :
  226. return array(
  227. "start_date" => gmdate("Y-m-d", strtotime("last Monday")),
  228. "end_date" => gmdate("Y-m-d", strtotime("next Sunday")));
  229. break;
  230. case "month" :
  231. $month_start = gmdate("Y-m-1");
  232. return array(
  233. "start_date" => $month_start,
  234. "end_date" => gmdate("Y-m-d", strtotime("{$month_start} +1 month - 1 hour")));
  235. break;
  236. case "year" :
  237. return array(
  238. "start_date" => gmdate("Y-1-1"),
  239. "end_date" => gmdate("Y-12-31"));
  240. break;
  241. }
  242. }
  243. public static function get_form($form_id, $display_title=true, $display_description=true, $force_display=false, $field_values=null, $ajax=false, $tabindex = 1){
  244. //looking up form id by form name
  245. if(!is_numeric($form_id))
  246. $form_id = RGFormsModel::get_form_id($form_id);
  247. //reading form metadata
  248. $form = RGFormsModel::get_form_meta($form_id, true);
  249. $form = RGFormsModel::add_default_properties($form);
  250. //disable ajax if form has a reCAPTCHA field (not supported).
  251. if($ajax && self::has_recaptcha_field($form))
  252. $ajax = false;
  253. $is_postback = false;
  254. $is_valid = true;
  255. $confirmation_message = "";
  256. $page_number = 1;
  257. //If form was submitted, read variables set during form submission procedure
  258. $submission_info = isset(self::$submission[$form_id]) ? self::$submission[$form_id] : false;
  259. if($submission_info){
  260. $is_postback = true;
  261. $is_valid = rgar($submission_info, "is_valid") || rgar($submission_info, "is_confirmation");
  262. $form = $submission_info["form"];
  263. $lead = $submission_info["lead"];
  264. $confirmation_message = rgget("confirmation_message", $submission_info);
  265. if($is_valid && !RGForms::get("is_confirmation", $submission_info)){
  266. if($submission_info["page_number"] == 0){
  267. //post submission hook
  268. do_action("gform_post_submission", $lead, $form);
  269. do_action("gform_post_submission_{$form["id"]}", $lead, $form);
  270. }
  271. else{
  272. //change page hook
  273. do_action("gform_post_paging", $form, $submission_info["source_page_number"], $submission_info["page_number"]);
  274. do_action("gform_post_paging_{$form["id"]}", $form, $submission_info["source_page_number"], $submission_info["page_number"]);
  275. }
  276. }
  277. }
  278. else if(!current_user_can("administrator")){
  279. RGFormsModel::insert_form_view($form_id, $_SERVER['REMOTE_ADDR']);
  280. }
  281. if(rgar($form,"enableHoneypot"))
  282. $form["fields"][] = self::get_honeypot_field($form);
  283. //Fired right before the form rendering process. Allow users to manipulate the form object before it gets displayed in the front end
  284. $form = apply_filters("gform_pre_render_$form_id", apply_filters("gform_pre_render", $form, $ajax), $ajax);
  285. if($form == null)
  286. return "<p>" . __("Oops! We could not locate your form.", "gravityforms") . "</p>";
  287. $has_pages = self::has_pages($form);
  288. //calling tab index filter
  289. GFCommon::$tab_index = apply_filters("gform_tabindex_{$form_id}", apply_filters("gform_tabindex", $tabindex, $form), $form);
  290. //Don't display inactive forms
  291. if(!$force_display && !$is_postback) {
  292. $form_info = RGFormsModel::get_form($form_id);
  293. if(!$form_info->is_active)
  294. return "";
  295. // If form requires login, check if user is logged in
  296. if(rgar($form, "requireLogin")) {
  297. if(!is_user_logged_in())
  298. return empty($form["requireLoginMessage"]) ? "<p>" . __("Sorry. You must be logged in to view this form.", "gravityforms"). "</p>" : "<p>" . GFCommon::gform_do_shortcode($form["requireLoginMessage"]) . "</p>";
  299. }
  300. }
  301. // show the form regardless of the following validations when force display is set to true
  302. if(!$force_display) {
  303. $form_schedule_validation = self::validate_form_schedule($form);
  304. // if form schedule validation fails AND this is not a postback, display the validation error
  305. // if form schedule validation fails AND this is a postback, make sure is not a valid submission (enables display of confirmation message)
  306. if( ($form_schedule_validation && !$is_postback) || ($form_schedule_validation && $is_postback && !$is_valid) )
  307. return $form_schedule_validation;
  308. $entry_limit_validation = self::validate_entry_limit($form);
  309. // refer to form schedule condition notes above
  310. if( ($entry_limit_validation && !$is_postback) || ($entry_limit_validation && $is_postback && !$is_valid) )
  311. return $entry_limit_validation;
  312. }
  313. $form_string = "";
  314. //When called via a template, this will enqueue the proper scripts
  315. //When called via a shortcode, this will be ignored (too late to enqueue), but the scripts will be enqueued via the enqueue_scripts event
  316. self::enqueue_form_scripts($form, $ajax);
  317. if(empty($confirmation_message)){
  318. $wrapper_css_class = GFCommon::get_browser_class() . " gform_wrapper";
  319. if(!$is_valid)
  320. $wrapper_css_class .=" gform_validation_error";
  321. //Hidding entire form if conditional logic is on to prevent "hidden" fields from blinking. Form will be set to visible in the conditional_logic.php after the rules have been applied.
  322. $style = self::has_conditional_logic($form) ? "style='display:none'" : "";
  323. $custom_wrapper_css_class = !empty($form["cssClass"]) ? " {$form["cssClass"]}_wrapper": "";
  324. $form_string .= "
  325. <div class='{$wrapper_css_class}{$custom_wrapper_css_class}' id='gform_wrapper_$form_id' " . $style . ">";
  326. $action = add_query_arg(array());
  327. $default_anchor = $has_pages || $ajax ? true : false;
  328. $use_anchor = apply_filters("gform_confirmation_anchor_{$form["id"]}", apply_filters("gform_confirmation_anchor", $default_anchor));
  329. if($use_anchor !== false){
  330. $form_string .="<a id='gf_$form_id' name='gf_$form_id' class='gform_anchor' ></a>";
  331. $action .= "#gf_$form_id";
  332. }
  333. $target = $ajax ? "target='gform_ajax_frame_{$form_id}'" : "";
  334. $form_css_class = !empty($form["cssClass"]) ? "class='{$form["cssClass"]}'": "";
  335. $action = esc_attr($action);
  336. $form_string .= apply_filters("gform_form_tag_{$form_id}", apply_filters("gform_form_tag", "<form method='post' enctype='multipart/form-data' {$target} id='gform_{$form_id}' {$form_css_class} action='{$action}'>", $form), $form);
  337. if($display_title || $display_description){
  338. $form_string .= "
  339. <div class='gform_heading'>";
  340. if($display_title){
  341. $form_string .= "
  342. <h3 class='gform_title'>" . $form['title'] . "</h3>";
  343. }
  344. if($display_description){
  345. $form_string .= "
  346. <span class='gform_description'>" . rgar($form,'description') ."</span>";
  347. }
  348. $form_string .= "
  349. </div>";
  350. }
  351. $current_page = self::get_current_page($form_id);
  352. if($has_pages && !IS_ADMIN){
  353. $page_count = self::get_max_page_number($form);
  354. if($form["pagination"]["type"] == "percentage"){
  355. $form_string .= self::get_progress_bar($form, $form_id,$confirmation_message);
  356. }
  357. else if($form["pagination"]["type"] == "steps"){
  358. $form_string .="
  359. <div id='gf_page_steps_{$form_id}' class='gf_page_steps'>";
  360. for($i=0, $count = sizeof($form["pagination"]["pages"]); $i<$count; $i++){
  361. $step_number = $i+1;
  362. $active_class = $step_number == $current_page ? " gf_step_active" : "";
  363. $first_class = $i==0 ? " gf_step_first" : "";
  364. $last_class = $i+1 == $count ? " gf_step_last" : "";
  365. $complete_class = $step_number < $current_page ? " gf_step_completed" : "";
  366. $previous_class = $step_number + 1 == $current_page ? " gf_step_previous" : "";
  367. $next_class = $step_number - 1 == $current_page ? " gf_step_next" : "";
  368. $pending_class = $step_number > $current_page ? " gf_step_pending" : "";
  369. $classes = "gf_step" . $active_class . $first_class . $last_class . $complete_class . $previous_class . $next_class . $pending_class;
  370. $classes = GFCommon::trim_all($classes);
  371. $form_string .="
  372. <div id='gf_step_{$form_id}_{$step_number}' class='{$classes}'><span class='gf_step_number'>{$step_number}</span>&nbsp;{$form["pagination"]["pages"][$i]}</div>";
  373. }
  374. $form_string .="
  375. <div class='gf_step_clear'></div>
  376. </div>";
  377. }
  378. }
  379. if($is_postback && !$is_valid){
  380. $validation_message = "<div class='validation_error'>" . __("There was a problem with your submission.", "gravityforms") . " " . __("Errors have been highlighted below.", "gravityforms") . "</div>";
  381. $form_string .= apply_filters("gform_validation_message_{$form["id"]}", apply_filters("gform_validation_message", $validation_message, $form), $form);
  382. }
  383. $form_string .= "
  384. <div class='gform_body'>";
  385. //add first page if this form has any page fields
  386. if($has_pages){
  387. $style = self::is_page_active($form_id, 1) ? "" : "style='display:none;'";
  388. $class = !empty($form["firstPageCssClass"]) ? " {$form["firstPageCssClass"]}" : "";
  389. $form_string .= "<div id='gform_page_{$form_id}_1' class='gform_page{$class}' {$style}>
  390. <div class='gform_page_fields'>";
  391. }
  392. $description_class = rgar($form,"descriptionPlacement") == "above" ? "description_above" : "description_below";
  393. $form_string .= "
  394. <ul id='gform_fields_$form_id' class='gform_fields {$form['labelPlacement']} {$description_class}'>";
  395. if(is_array($form['fields']))
  396. {
  397. foreach($form['fields'] as $field){
  398. $field["conditionalLogicFields"] = self::get_conditional_logic_fields($form, $field["id"]);
  399. $form_string .= self::get_field($field, RGFormsModel::get_field_value($field, $field_values), false, $form, $field_values);
  400. }
  401. }
  402. $form_string .= "
  403. </ul>";
  404. if($has_pages){
  405. $previous_button = self::get_form_button($form["id"], "gform_previous_button_{$form["id"]}", $form["lastPageButton"], __("Previous", "gravityforms"), "button gform_previous_button", __("Previous Page", "gravityforms"), self::get_current_page($form_id) -1);
  406. $form_string .= "</div>" . self::gform_footer($form, "gform_page_footer " . $form['labelPlacement'], $ajax, $field_values, $previous_button, $display_title, $display_description, $is_postback) . "
  407. </div>"; //closes gform_page
  408. }
  409. $form_string .= "</div>"; //closes gform_body
  410. //suppress form footer for multi-page forms (footer will be included on the last page
  411. if(!$has_pages)
  412. $form_string .= self::gform_footer($form, "gform_footer " . $form['labelPlacement'], $ajax, $field_values, "", $display_title, $display_description, $is_postback);
  413. $form_string .= "
  414. </form>
  415. </div>";
  416. if($ajax && $is_postback){
  417. global $wp_scripts;
  418. $form_string = "<!DOCTYPE html><html><head>" .
  419. "<meta charset='UTF-8' /></head><body class='GF_AJAX_POSTBACK'>" . $form_string . "</body></html>";
  420. }
  421. if($ajax && !$is_postback){
  422. $spinner_url = apply_filters("gform_ajax_spinner_url_{$form_id}", apply_filters("gform_ajax_spinner_url", GFCommon::get_base_url() . "/images/spinner.gif", $form), $form);
  423. $scroll_position = array('default' => '', 'confirmation' => '');
  424. if($use_anchor !== false) {
  425. $scroll_position['default'] = is_numeric($use_anchor) ? "jQuery(document).scrollTop(" . intval($use_anchor) . ");" : "jQuery(document).scrollTop(jQuery('#gform_wrapper_{$form_id}').offset().top);";
  426. $scroll_position['confirmation'] = is_numeric($use_anchor) ? "jQuery(document).scrollTop(" . intval($use_anchor) . ");" : "jQuery(document).scrollTop(jQuery('#gforms_confirmation_message').offset().top);";
  427. }
  428. $form_string .="
  429. <iframe style='display:none;width:0px; height:0px;' src='about:blank' name='gform_ajax_frame_{$form_id}' id='gform_ajax_frame_{$form_id}'></iframe>
  430. <script type='text/javascript'>" . apply_filters("gform_cdata_open", "") . "" .
  431. "function gformInitSpinner_{$form_id}(){" .
  432. "jQuery('#gform_{$form_id}').submit(function(){" .
  433. "jQuery('#gform_submit_button_{$form_id}').attr('disabled', true).after('<' + 'img id=\"gform_ajax_spinner_{$form_id}\" class=\"gform_ajax_spinner\" src=\"{$spinner_url}\" alt=\"\" />');" .
  434. "jQuery('#gform_wrapper_{$form_id} .gform_previous_button').attr('disabled', true); " .
  435. "jQuery('#gform_wrapper_{$form_id} .gform_next_button').attr('disabled', true).after('<' + 'img id=\"gform_ajax_spinner_{$form_id}\" class=\"gform_ajax_spinner\" src=\"{$spinner_url}\" alt=\"\" />');" .
  436. "});" .
  437. "}" .
  438. "jQuery(document).ready(function($){" .
  439. "gformInitSpinner_{$form_id}();" .
  440. "jQuery('#gform_ajax_frame_{$form_id}').load( function(){" .
  441. "var contents = jQuery(this).contents().find('*').html();" .
  442. "var is_postback = contents.indexOf('GF_AJAX_POSTBACK') >= 0;" .
  443. "if(!is_postback){return;}" .
  444. "var form_content = jQuery(this).contents().find('#gform_wrapper_{$form_id}');" .
  445. "var is_redirect = contents.indexOf('gformRedirect(){') >= 0;".
  446. "jQuery('#gform_submit_button_{$form_id}').removeAttr('disabled');" .
  447. "if(form_content.length > 0){" .
  448. "jQuery('#gform_wrapper_{$form_id}').html(form_content.html());" .
  449. "{$scroll_position['default']}" .
  450. "if(window['gformInitDatepicker']) {gformInitDatepicker();}" .
  451. "if(window['gformInitPriceFields']) {gformInitPriceFields();}" .
  452. "var current_page = jQuery('#gform_source_page_number_{$form_id}').val();".
  453. "gformInitSpinner_{$form_id}();" .
  454. "jQuery(document).trigger('gform_page_loaded', [{$form_id}, current_page]);" .
  455. "}" .
  456. "else if(!is_redirect){" .
  457. "var confirmation_content = jQuery(this).contents().find('#gforms_confirmation_message').html();" .
  458. "if(!confirmation_content){".
  459. "confirmation_content = contents;".
  460. "}" .
  461. "setTimeout(function(){" .
  462. "jQuery('#gform_wrapper_{$form_id}').replaceWith('<' + 'div id=\'gforms_confirmation_message\' class=\'gform_confirmation_message_{$form_id}\'' + '>' + confirmation_content + '<' + '/div' + '>');" .
  463. "{$scroll_position['confirmation']}" .
  464. "jQuery(document).trigger('gform_confirmation_loaded', [{$form_id}]);" .
  465. "}, 50);" .
  466. "}" .
  467. "else{" .
  468. "jQuery('#gform_{$form_id}').append(contents);" .
  469. "if(window['gformRedirect']) gformRedirect();" .
  470. "}" .
  471. "jQuery(document).trigger('gform_post_render', [{$form_id}, current_page]);" .
  472. "});" .
  473. "});" . apply_filters("gform_cdata_close", "") . "</script>";
  474. }
  475. $is_first_load = !$is_postback;
  476. if(!$ajax || $is_first_load) {
  477. $form_string .= self::get_form_init_scripts($form);
  478. $form_string .= "<script type='text/javascript'>" . apply_filters("gform_cdata_open", "") . " jQuery(document).ready(function(){jQuery(document).trigger('gform_post_render', [{$form_id}, {$current_page}])}); " . apply_filters("gform_cdata_close", "") . "</script>";
  479. }
  480. return apply_filters('gform_get_form_filter',$form_string);
  481. }
  482. else{
  483. $progress_confirmation = "";
  484. //check admin setting for whether the progress bar should start at zero
  485. $start_at_zero = rgars($form, "pagination/display_progressbar_on_confirmation");
  486. //check for filter
  487. $start_at_zero = apply_filters("gform_progressbar_start_at_zero", $start_at_zero, $form);
  488. //show progress bar on confirmation
  489. if($start_at_zero && $has_pages && !IS_ADMIN && ($form["confirmation"]["type"] == "message" && $form["pagination"]["type"] == "percentage") && $form["pagination"]["display_progressbar_on_confirmation"])
  490. {
  491. $progress_confirmation = self::get_progress_bar($form, $form_id,$confirmation_message);
  492. if($ajax)
  493. {
  494. $progress_confirmation = "<!DOCTYPE html><html><head><meta charset='UTF-8' /></head><body class='GF_AJAX_POSTBACK'>" . $progress_confirmation . $confirmation_message . "</body></html>";
  495. }
  496. else
  497. {
  498. $progress_confirmation = $progress_confirmation . $confirmation_message;
  499. }
  500. }
  501. else
  502. {
  503. //return regular confirmation message
  504. if($ajax)
  505. {
  506. $progress_confirmation = "<!DOCTYPE html><html><head><meta charset='UTF-8' /></head><body class='GF_AJAX_POSTBACK'>" . $confirmation_message . "</body></html>";
  507. }
  508. else
  509. {
  510. $progress_confirmation = $confirmation_message;
  511. }
  512. }
  513. return $progress_confirmation;
  514. }
  515. }
  516. public static function add_init_script($form_id, $script_name, $location, $script){
  517. $key = $script_name . "_" . $location;
  518. if(!isset(self::$init_scripts[$form_id]))
  519. self::$init_scripts[$form_id] = array();
  520. //add script if it hasn't been added before
  521. if(!array_key_exists($key, self::$init_scripts[$form_id]))
  522. self::$init_scripts[$form_id][$key] = array("location" => $location, "script" => $script);
  523. }
  524. private static function get_form_button($form_id, $button_input_id, $button, $default_text, $class, $alt, $target_page_number){
  525. $tabindex = GFCommon::get_tabindex();
  526. $input_type='submit';
  527. $onclick="";
  528. if(!empty($target_page_number)){
  529. $onclick = "onclick='jQuery(\"#gform_target_page_number_{$form_id}\").val(\"{$target_page_number}\"); jQuery(\"#gform_{$form_id}\").trigger(\"submit\",[true]); '";
  530. $input_type='button';
  531. }
  532. if($button["type"] == "text" || empty($button["imageUrl"])){
  533. $button_text = !empty($button["text"]) ? $button["text"] : $default_text;
  534. $button_input = "<input type='{$input_type}' id='{$button_input_id}' class='{$class}' value='" . esc_attr($button_text) . "' {$tabindex} {$onclick}/>";
  535. }
  536. else{
  537. $imageUrl = $button["imageUrl"];
  538. $button_input= "<input type='image' src='{$imageUrl}' id='{$button_input_id}' class='gform_image_button' alt='{$alt}' {$tabindex} {$onclick}/>";
  539. }
  540. return $button_input;
  541. }
  542. private static function gform_footer($form, $class, $ajax, $field_values, $previous_button, $display_title, $display_description){
  543. $form_id = $form["id"];
  544. $footer = "
  545. <div class='" . $class ."'>";
  546. $button_input = self::get_form_button($form["id"], "gform_submit_button_{$form["id"]}", $form["button"], __("Submit", "gravityforms"), "button gform_button", __("Submit", "gravityforms"), 0);
  547. $button_input = apply_filters("gform_submit_button", $button_input, $form);
  548. $button_input = apply_filters("gform_submit_button_{$form_id}", $button_input, $form);
  549. $footer .= $previous_button . " " . $button_input;
  550. if($ajax){
  551. $footer .= "<input type='hidden' name='gform_ajax' value='" . esc_attr("form_id={$form_id}&amp;title={$display_title}&amp;description={$display_description}") . "' />";
  552. }
  553. $current_page = self::get_current_page($form_id);
  554. $next_page = $current_page + 1;
  555. $next_page = $next_page > self::get_max_page_number($form) ? 0 : $next_page;
  556. $field_values_str = is_array($field_values) ? http_build_query($field_values) : "";
  557. $files_input = "";
  558. if(!empty(RGFormsModel::$uploaded_files[$form_id])){
  559. $files = GFCommon::json_encode(RGFormsModel::$uploaded_files[$form_id]);
  560. $files_input = "<input type='hidden' name='gform_uploaded_files' id='gform_uploaded_files_{$form_id}' value='" . str_replace("'", "&#039;", $files) . "' />";
  561. }
  562. $footer .="
  563. <input type='hidden' class='gform_hidden' name='is_submit_{$form_id}' value='1' />
  564. <input type='hidden' class='gform_hidden' name='gform_submit' value='{$form_id}' />
  565. <input type='hidden' class='gform_hidden' name='gform_unique_id' value='" . esc_attr(RGFormsModel::get_form_unique_id($form_id)) . "' />
  566. <input type='hidden' class='gform_hidden' name='state_{$form_id}' value='" . self::get_state($form, $field_values) . "' />
  567. <input type='hidden' class='gform_hidden' name='gform_target_page_number_{$form_id}' id='gform_target_page_number_{$form_id}' value='" . $next_page . "' />
  568. <input type='hidden' class='gform_hidden' name='gform_source_page_number_{$form_id}' id='gform_source_page_number_{$form_id}' value='" . $current_page . "' />
  569. <input type='hidden' name='gform_field_values' value='{$field_values_str}' />
  570. {$files_input}
  571. </div>";
  572. return $footer;
  573. }
  574. private static function get_max_page_number($form){
  575. $page_number = 0;
  576. foreach($form["fields"] as $field){
  577. if($field["type"] == "page"){
  578. $page_number++;
  579. }
  580. }
  581. return $page_number == 0 ? 0 : $page_number + 1;
  582. }
  583. private static function get_honeypot_field($form){
  584. $max_id = self::get_max_field_id($form);
  585. $labels = self::get_honeypot_labels();
  586. return array("type" => "honeypot", "label" => $labels[rand(0, 3)], "id" => $max_id + 1, "cssClass" => "gform_validation_container", "description" => "This field is for validation purposes and should be left unchanged.");
  587. }
  588. private static function get_max_field_id($form){
  589. $max = 0;
  590. foreach($form["fields"] as $field){
  591. if(floatval($field["id"]) > $max)
  592. $max = floatval($field["id"]);
  593. }
  594. return $max;
  595. }
  596. private static function get_honeypot_labels(){
  597. return array("Name", "Email", "Phone", "Comments");
  598. }
  599. public static function is_empty($field, $form_id=0){
  600. switch(RGFormsModel::get_input_type($field)){
  601. case "post_image" :
  602. case "fileupload" :
  603. $input_name = "input_" . $field["id"];
  604. $file_info = RGFormsModel::get_temp_filename($form_id, $input_name);
  605. return !$file_info && empty($_FILES[$input_name]['name']);
  606. case "list" :
  607. $value = rgpost("input_" . $field["id"]);
  608. if(is_array($value)){
  609. //empty if all inputs are empty (for inputs with the same name)
  610. foreach($value as $input){
  611. if(strlen(trim($input)) > 0 )
  612. return false;
  613. }
  614. }
  615. return true;
  616. }
  617. if(is_array($field["inputs"]))
  618. {
  619. foreach($field["inputs"] as $input){
  620. $value = rgpost("input_" . str_replace('.', '_', $input["id"]));
  621. if(is_array($value) && !empty($value)){
  622. return false;
  623. }
  624. if(!is_array($value) && strlen(trim($value)) > 0)
  625. return false;
  626. }
  627. return true;
  628. }
  629. else{
  630. $value = rgpost("input_" . $field["id"]);
  631. if(is_array($value)){
  632. //empty if any of the inputs are empty (for inputs with the same name)
  633. foreach($value as $input){
  634. if(strlen(trim($input)) <= 0 )
  635. return true;
  636. }
  637. return false;
  638. }
  639. else if($field["enablePrice"]){
  640. list($label, $price) = explode("|", $value);
  641. $is_empty = (strlen(trim($price)) <= 0);
  642. return $is_empty;
  643. }
  644. else{
  645. $is_empty = (strlen(trim($value)) <= 0) || ($field["type"] == "post_category" && $value < 0);
  646. return $is_empty;
  647. }
  648. }
  649. }
  650. private static function clean_extensions($extensions){
  651. $count = sizeof($extensions);
  652. for($i=0; $i<$count; $i++){
  653. $extensions[$i] = str_replace(".", "",str_replace(" ", "", $extensions[$i]));
  654. }
  655. return $extensions;
  656. }
  657. private static function validate_range($field, $value){
  658. if( !GFCommon::is_numeric($value, rgar($field, "numberFormat")) )
  659. return false;
  660. $number = GFCommon::clean_number($value, rgar($field, "numberFormat"));
  661. if( (is_numeric($field["rangeMin"]) && $number < $field["rangeMin"]) ||
  662. (is_numeric($field["rangeMax"]) && $number > $field["rangeMax"])
  663. )
  664. return false;
  665. else
  666. return true;
  667. }
  668. private static function validate_honeypot($form){
  669. $honeypot_id = self::get_max_field_id($form);
  670. return rgempty("input_{$honeypot_id}");
  671. }
  672. public static function handle_submission($form, &$lead, $ajax=false){
  673. //creating entry in DB
  674. RGFormsModel::save_lead($form, $lead);
  675. //reading entry that was just saved
  676. $lead = RGFormsModel::get_lead($lead["id"]);
  677. do_action('gform_entry_created', $lead, $form);
  678. //if Akismet plugin is installed, run lead through Akismet and mark it as Spam when appropriate
  679. $is_spam = false;
  680. if(GFCommon::akismet_enabled($form['id']) && GFCommon::is_akismet_spam($form, $lead)){
  681. $is_spam = true;
  682. }
  683. if(!$is_spam){
  684. GFCommon::create_post($form, $lead);
  685. //send auto-responder and notification emails
  686. self::send_emails($form, $lead);
  687. }
  688. else{
  689. //marking entry as spam
  690. RGFormsModel::update_lead_property($lead["id"], "status", "spam", false, true);
  691. $lead["status"] = "spam";
  692. }
  693. //display confirmation message or redirect to confirmation page
  694. return self::handle_confirmation($form, $lead, $ajax);
  695. }
  696. public static function handle_confirmation($form, $lead, $ajax=false){
  697. if($form["confirmation"]["type"] == "message"){
  698. $default_anchor = self::has_pages($form) ? 1 : 0;
  699. $anchor = apply_filters("gform_confirmation_anchor_{$form["id"]}", apply_filters("gform_confirmation_anchor", $default_anchor)) ? "<a id='gf_{$form["id"]}' name='gf_{$form["id"]}' class='gform_anchor' ></a>" : "";
  700. $nl2br = rgar($form["confirmation"],"disableAutoformat") ? false : true;
  701. $confirmation = empty($form["confirmation"]["message"]) ? "{$anchor} " : "{$anchor}<div id='gforms_confirmation_message' class='gform_confirmation_message_{$form["id"]}'>" . GFCommon::replace_variables($form["confirmation"]["message"], $form, $lead, false, true, $nl2br) . "</div>";
  702. }
  703. else{
  704. if(!empty($form["confirmation"]["pageId"])){
  705. $url = get_permalink($form["confirmation"]["pageId"]);
  706. }
  707. else{
  708. $url = GFCommon::replace_variables(trim($form["confirmation"]["url"]), $form, $lead, false, true);
  709. $url_info = parse_url($url);
  710. $query_string = $url_info["query"];
  711. $dynamic_query = GFCommon::replace_variables(trim($form["confirmation"]["queryString"]), $form, $lead, true);
  712. $query_string .= empty($url_info["query"]) || empty($dynamic_query) ? $dynamic_query : "&" . $dynamic_query;
  713. if(!empty($url_info["fragment"]))
  714. $query_string .= "#" . $url_info["fragment"];
  715. $url = $url_info["scheme"] . "://" . $url_info["host"] . $url_info["path"] . "?" . $query_string;
  716. }
  717. if(headers_sent() || $ajax){
  718. //Perform client side redirect for AJAX forms, of if headers have already been sent
  719. $confirmation = self::get_js_redirect_confirmation($url, $ajax);
  720. }
  721. else{
  722. $confirmation = array("redirect" => $url);
  723. }
  724. }
  725. $confirmation = apply_filters("gform_confirmation_{$form["id"]}", apply_filters("gform_confirmation", $confirmation, $form, $lead, $ajax), $form, $lead, $ajax);
  726. if(!is_array($confirmation)){
  727. $confirmation = GFCommon::gform_do_shortcode($confirmation); //enabling shortcodes
  728. }
  729. else if(headers_sent() || $ajax){
  730. //Perform client side redirect for AJAX forms, of if headers have already been sent
  731. $confirmation = self::get_js_redirect_confirmation($confirmation["redirect"], $ajax); //redirecting via client side
  732. }
  733. return $confirmation;
  734. }
  735. private static function get_js_redirect_confirmation($url, $ajax){
  736. $confirmation = "<script type=\"text/javascript\">" . apply_filters("gform_cdata_open", "") . " function gformRedirect(){document.location.href='$url';}";
  737. if(!$ajax)
  738. $confirmation .="gformRedirect();";
  739. $confirmation .= apply_filters("gform_cdata_close", "") . "</script>";
  740. return $confirmation;
  741. }
  742. public static function send_emails($form, $lead){
  743. $disable_user_notification = apply_filters("gform_disable_user_notification_{$form["id"]}", apply_filters("gform_disable_user_notification", false, $form, $lead), $form, $lead);
  744. if(!$disable_user_notification){
  745. GFCommon::send_user_notification($form, $lead);
  746. }
  747. $disable_admin_notification = apply_filters("gform_disable_admin_notification_{$form["id"]}", apply_filters("gform_disable_admin_notification", false, $form, $lead), $form, $lead);
  748. if(!$disable_admin_notification){
  749. GFCommon::send_admin_notification($form, $lead);
  750. }
  751. }
  752. public static function checkdate($month, $day, $year){
  753. if(empty($month) || !is_numeric($month) || empty($day) || !is_numeric($day) || empty($year) || !is_numeric($year) || strlen($year) != 4)
  754. return false;
  755. return checkdate($month, $day, $year);
  756. }
  757. public static function validate(&$form, $field_values, $page_number=0){
  758. // validate form schedule
  759. if(self::validate_form_schedule($form))
  760. return false;
  761. // validate entry limit
  762. if(self::validate_entry_limit($form))
  763. return false;
  764. foreach($form["fields"] as &$field){
  765. //If a page number is specified, only validates fields that are on current page
  766. if($page_number > 0 && $field["pageNumber"] != $page_number)
  767. continue;
  768. //ignore validation if field is hidden or admin only
  769. if(RGFormsModel::is_field_hidden($form, $field, $field_values) || $field["adminOnly"])
  770. continue;
  771. $value = RGFormsModel::get_field_value($field);
  772. //display error message if field is marked as required and the submitted value is empty
  773. if($field["isRequired"] && self::is_empty($field, $form["id"])){
  774. $field["failed_validation"] = true;
  775. $field["validation_message"] = empty($field["errorMessage"]) ? __("This field is required.", "gravityforms") : $field["errorMessage"];
  776. }
  777. //display error if field does not allow duplicates and the submitted value already exists
  778. else if($field["noDuplicates"] && RGFormsModel::is_duplicate($form["id"], $field, $value)){
  779. $field["failed_validation"] = true;
  780. $input_type = RGFormsModel::get_input_type($field);
  781. switch($input_type){
  782. case "date" :
  783. $default_message = __("This date has already been taken. Please select a new date.", "gravityforms");
  784. break;
  785. default:
  786. $default_message = is_array($value) ? __("This field requires an unique entry and the values you entered have been already been used.", "gravityforms") :
  787. sprintf(__("This field requires an unique entry and '%s' has already been used", "gravityforms"), $value);
  788. break;
  789. }
  790. $field["validation_message"] = apply_filters("gform_duplicate_message_{$form["id"]}", apply_filters("gform_duplicate_message", $default_message, $form), $form);
  791. }
  792. else{
  793. if(self::failed_state_validation($form["id"], $field, $value)){
  794. $field["failed_validation"] = true;
  795. $field["validation_message"] = in_array($field["inputType"], array("singleproduct", "singleshipping", "hiddenproduct")) ? __("Please enter a valid value.", "gravityforms") : __("Invalid selection. Please select one of the available choices.", "gravityforms");
  796. }
  797. else{
  798. switch(RGFormsModel::get_input_type($field)){
  799. case "password" :
  800. $password = $_POST["input_" . $field["id"]];
  801. $confirm = $_POST["input_" . $field["id"] . "_2"];
  802. if($password != $confirm){
  803. $field["failed_validation"] = true;
  804. $field["validation_message"] = __("Your passwords do not match.", "gravityforms");
  805. }
  806. else if(rgar($field,"passwordStrengthEnabled") && !rgempty("minPasswordStrength",$field) && !empty($password)){
  807. $strength = $_POST["input_" . $field["id"] . "_strength"];
  808. $levels = array("short" => 1, "bad" => 2, "good" => 3, "strong" => 4);
  809. if($levels[$strength] < $levels[$field["minPasswordStrength"]]){
  810. $field["failed_validation"] = true;
  811. $field["validation_message"] = empty($field["errorMessage"]) ? __("Your password does not meet the required strength. <br/>Hint: To make it stronger, use upper and lower case letters, numbers and symbols like ! \" ? $ % ^ & ).", "gravityforms") : $field["errorMessage"];
  812. }
  813. }
  814. break;
  815. case "name" :
  816. if($field["isRequired"] && $field["nameFormat"] != "simple")
  817. {
  818. $first = $_POST["input_" . $field["id"] . "_3"];
  819. $last = $_POST["input_" . $field["id"] . "_6"];
  820. if(empty($first) || empty($last)){
  821. $field["failed_validation"] = true;
  822. $field["validation_message"] = empty($field["errorMessage"]) ? __("This field is required. Please enter the first and last name.", "gravityforms") : $field["errorMessage"];
  823. }
  824. }
  825. break;
  826. case "address" :
  827. if($field["isRequired"])
  828. {
  829. $street = $_POST["input_" . $field["id"] . "_1"];
  830. $city = $_POST["input_" . $field["id"] . "_3"];
  831. $state = $_POST["input_" . $field["id"] . "_4"];
  832. $zip = $_POST["input_" . $field["id"] . "_5"];
  833. $country = $_POST["input_" . $field["id"] . "_6"];
  834. if(empty($street) || empty($city) || empty($zip) || (empty($state) && !$field["hideS…

Large files files are truncated, but you can click here to view the full file