PageRenderTime 1355ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/plugins/gravityforms/forms_model.php

https://github.com/ttimsmith/Anythin-Goes
PHP | 3720 lines | 2872 code | 638 blank | 210 comment | 482 complexity | a0de73cf64abd8d521dc89e16c2e2edb MD5 | raw file
Possible License(s): GPL-3.0
  1. <?php
  2. require_once(ABSPATH . "/wp-includes/post.php");
  3. define("GFORMS_MAX_FIELD_LENGTH", 200);
  4. class GFFormsModel {
  5. public static $uploaded_files = array();
  6. public static $unique_ids = array();
  7. private static $_confirmations = array();
  8. private static $_current_forms = array();
  9. private static $_current_lead = null;
  10. public static function flush_current_forms(){
  11. self::$_current_forms = null;
  12. }
  13. public static function flush_current_lead(){
  14. self::$_current_lead = null;
  15. }
  16. public static function flush_confirmations(){
  17. self::$_confirmations = null;
  18. }
  19. public static function get_form_table_name(){
  20. global $wpdb;
  21. return $wpdb->prefix . "rg_form";
  22. }
  23. public static function get_meta_table_name(){
  24. global $wpdb;
  25. return $wpdb->prefix . "rg_form_meta";
  26. }
  27. public static function get_form_view_table_name(){
  28. global $wpdb;
  29. return $wpdb->prefix . "rg_form_view";
  30. }
  31. public static function get_lead_table_name(){
  32. global $wpdb;
  33. return $wpdb->prefix . "rg_lead";
  34. }
  35. public static function get_lead_meta_table_name(){
  36. global $wpdb;
  37. return $wpdb->prefix . "rg_lead_meta";
  38. }
  39. public static function get_lead_notes_table_name(){
  40. global $wpdb;
  41. return $wpdb->prefix . "rg_lead_notes";
  42. }
  43. public static function get_lead_details_table_name(){
  44. global $wpdb;
  45. return $wpdb->prefix . "rg_lead_detail";
  46. }
  47. public static function get_lead_details_long_table_name(){
  48. global $wpdb;
  49. return $wpdb->prefix . "rg_lead_detail_long";
  50. }
  51. public static function get_lead_view_name(){
  52. global $wpdb;
  53. return $wpdb->prefix . "rg_lead_view";
  54. }
  55. public static function get_forms($is_active = null, $sort="title ASC"){
  56. global $wpdb;
  57. $form_table_name = self::get_form_table_name();
  58. $lead_table_name = self::get_lead_table_name();
  59. $view_table_name = self::get_form_view_table_name();
  60. $active_clause = $is_active !== null ? $wpdb->prepare("WHERE is_active=%d", $is_active) : "";
  61. $order_by = !empty($sort) ? "ORDER BY $sort" : "";
  62. $sql = "SELECT f.id, f.title, f.date_created, f.is_active, 0 as lead_count, 0 view_count
  63. FROM $form_table_name f
  64. $active_clause
  65. $order_by";
  66. //Getting all forms
  67. $forms = $wpdb->get_results($sql);
  68. //Getting entry count per form
  69. $sql = "SELECT form_id, count(id) as lead_count FROM $lead_table_name l WHERE status='active' GROUP BY form_id";
  70. $entry_count = $wpdb->get_results($sql);
  71. //Getting view count per form
  72. $sql = "SELECT form_id, sum(count) as view_count FROM $view_table_name GROUP BY form_id";
  73. $view_count = $wpdb->get_results($sql);
  74. //Adding entry counts and to form array
  75. foreach($forms as &$form){
  76. foreach($view_count as $count){
  77. if($count->form_id == $form->id){
  78. $form->view_count = $count->view_count;
  79. break;
  80. }
  81. }
  82. foreach($entry_count as $count){
  83. if($count->form_id == $form->id){
  84. $form->lead_count = $count->lead_count;
  85. break;
  86. }
  87. }
  88. }
  89. return $forms;
  90. }
  91. public static function get_forms_by_id($ids){
  92. _deprecated_function('get_forms_by_id', '1.7', 'get_form_meta_by_id');
  93. return self::get_form_meta_by_id($ids);
  94. }
  95. public static function get_form_payment_totals($form_id){
  96. global $wpdb;
  97. $lead_table_name = self::get_lead_table_name();
  98. $sql = $wpdb->prepare(" SELECT sum(payment_amount) revenue, count(l.id) orders
  99. FROM $lead_table_name l
  100. WHERE form_id=%d AND payment_amount IS NOT null", $form_id);
  101. $totals = $wpdb->get_row($sql, ARRAY_A);
  102. $active = $wpdb->get_var($wpdb->prepare(" SELECT count(id) as active
  103. FROM $lead_table_name
  104. WHERE form_id=%d AND payment_status='Active'", $form_id));
  105. if(empty($active))
  106. $active = 0;
  107. $totals["active"] = $active;
  108. return $totals;
  109. }
  110. public static function get_form_counts($form_id){
  111. global $wpdb;
  112. $lead_table_name = self::get_lead_table_name();
  113. $sql = $wpdb->prepare(
  114. "SELECT
  115. (SELECT count(0) FROM $lead_table_name WHERE form_id=%d AND status='active') as total,
  116. (SELECT count(0) FROM $lead_table_name WHERE is_read=0 AND status='active' AND form_id=%d) as unread,
  117. (SELECT count(0) FROM $lead_table_name WHERE is_starred=1 AND status='active' AND form_id=%d) as starred,
  118. (SELECT count(0) FROM $lead_table_name WHERE status='spam' AND form_id=%d) as spam,
  119. (SELECT count(0) FROM $lead_table_name WHERE status='trash' AND form_id=%d) as trash",
  120. $form_id, $form_id, $form_id, $form_id, $form_id);
  121. $results = $wpdb->get_results($sql, ARRAY_A);
  122. return $results[0];
  123. }
  124. public static function get_form_summary(){
  125. global $wpdb;
  126. $form_table_name = self::get_form_table_name();
  127. $lead_table_name = self::get_lead_table_name();
  128. $sql = "SELECT l.form_id, count(l.id) as unread_count
  129. FROM $lead_table_name l
  130. WHERE is_read=0 AND status='active'
  131. GROUP BY form_id";
  132. //getting number of unread and total leads for all forms
  133. $unread_results = $wpdb->get_results($sql, ARRAY_A);
  134. $sql = "SELECT l.form_id, max(l.date_created) as last_lead_date, count(l.id) as total_leads
  135. FROM $lead_table_name l
  136. WHERE status='active'
  137. GROUP BY form_id";
  138. $lead_date_results = $wpdb->get_results($sql, ARRAY_A);
  139. $sql = "SELECT id, title, '' as last_lead_date, 0 as unread_count
  140. FROM $form_table_name
  141. WHERE is_active=1
  142. ORDER BY title";
  143. $forms = $wpdb->get_results($sql, ARRAY_A);
  144. for($i=0; $count = sizeof($forms), $i<$count; $i++){
  145. if(is_array($unread_results)){
  146. foreach($unread_results as $unread_result){
  147. if($unread_result["form_id"] == $forms[$i]["id"]){
  148. $forms[$i]["unread_count"] = $unread_result["unread_count"];
  149. break;
  150. }
  151. }
  152. }
  153. if(is_array($lead_date_results)){
  154. foreach($lead_date_results as $lead_date_result){
  155. if($lead_date_result["form_id"] == $forms[$i]["id"]){
  156. $forms[$i]["last_lead_date"] = $lead_date_result["last_lead_date"];
  157. $forms[$i]["total_leads"] = $lead_date_result["total_leads"];
  158. break;
  159. }
  160. }
  161. }
  162. }
  163. return $forms;
  164. }
  165. public static function get_form_count(){
  166. global $wpdb;
  167. $form_table_name = self::get_form_table_name();
  168. $results = $wpdb->get_results("SELECT count(0) as count FROM $form_table_name UNION ALL SELECT count(0) as count FROM $form_table_name WHERE is_active=1 ");
  169. return array( "total" => intval($results[0]->count),
  170. "active" => intval($results[1]->count),
  171. "inactive" => intval($results[0]->count) - intval($results[1]->count)
  172. );
  173. }
  174. public static function get_form_id($form_title){
  175. $forms = self::get_forms();
  176. foreach($forms as $form){
  177. $sanitized_name = str_replace("[", "", str_replace("]","", $form->title));
  178. if($form->title == $form_title || $sanitized_name == $form_title)
  179. return $form->id;
  180. }
  181. return 0;
  182. }
  183. public static function get_form($form_id){
  184. global $wpdb;
  185. $table_name = self::get_form_table_name();
  186. $results = $wpdb->get_results($wpdb->prepare("SELECT * FROM $table_name WHERE id=%d", $form_id));
  187. return $results[0];
  188. }
  189. public static function get_form_meta($form_id){
  190. global $wpdb;
  191. // return cached version if form meta has been previously retrieved for this form
  192. if(isset(self::$_current_forms[$form_id])){
  193. return self::$_current_forms[$form_id];
  194. }
  195. $table_name = self::get_meta_table_name();
  196. $form_row = $wpdb->get_row($wpdb->prepare("SELECT display_meta, notifications FROM {$table_name} WHERE form_id=%d", $form_id), ARRAY_A);
  197. //loading main form object
  198. $form = maybe_unserialize($form_row["display_meta"]);
  199. if(!$form)
  200. return null;
  201. //loading notifications
  202. $form["notifications"] = maybe_unserialize($form_row["notifications"]);
  203. //copying some form variables down to fields for easier access
  204. $page_number = 1;
  205. $description_placement = rgar($form, "descriptionPlacement") == "above" ? "above" : "below";
  206. if(is_array(rgar($form,"fields"))){
  207. foreach($form["fields"] as &$field){
  208. $field["formId"] = $form["id"];
  209. $field["pageNumber"] = $page_number;
  210. $field["descriptionPlacement"] = $description_placement;
  211. if($field["type"] == "page"){
  212. $page_number++;
  213. $field["pageNumber"] = $page_number;
  214. }
  215. }
  216. }
  217. // loading confirmations from legacy structure into new structure
  218. $form = self::load_confirmations($form);
  219. //only migrate legacy notification if there isn't any notification configured in new structure
  220. if(!isset($form["notifications"])){
  221. $form = self::load_notifications_from_legacy($form); //moving notification data from legacy structure into new "notifications" array
  222. }
  223. //load notifications to legacy structure to maintain backward compatibility with legacy hooks and functions
  224. $form = self::load_notifications_to_legacy($form);
  225. // cached form meta for cheaper retrieval on subsequent requests
  226. self::$_current_forms[$form_id] = $form;
  227. return $form;
  228. }
  229. public static function get_form_meta_by_id($ids){
  230. global $wpdb;
  231. $form_table_name = self::get_form_table_name();
  232. $meta_table_name = self::get_meta_table_name();
  233. if(is_array($ids))
  234. $ids = implode(",", array_map('intval', $ids ) );
  235. else
  236. $ids = intval($ids);
  237. $results = $wpdb->get_results(" SELECT display_meta, confirmations, notifications FROM {$form_table_name} f
  238. INNER JOIN {$meta_table_name} m ON f.id = m.form_id
  239. WHERE id in({$ids})", ARRAY_A);
  240. foreach ($results as &$result) {
  241. $form = maybe_unserialize($result["display_meta"]);
  242. $form['confirmations'] = maybe_unserialize($result["confirmations"]);
  243. $form['notifications'] = maybe_unserialize($result["notifications"]);
  244. $result = $form;
  245. }
  246. return $results;
  247. }
  248. private static function load_notifications_to_legacy($form){
  249. if(!is_array(rgar($form, "notifications")))
  250. return;
  251. foreach($form["notifications"] as $notification){
  252. if(!in_array(rgar($notification,"type"), array("user", "admin")))
  253. continue;
  254. $legacy_notification = $notification;
  255. if($notification["toType"] == "field"){
  256. $legacy_notification["toField"] = $notification["to"];
  257. unset($legacy_notification["to"]);
  258. }
  259. //unsetting new properties
  260. unset($legacy_notification["toType"]);
  261. unset($legacy_notification["id"]);
  262. unset($legacy_notification["event"]);
  263. unset($legacy_notification["name"]);
  264. if(isset($legacy_notification["type"]))
  265. unset($legacy_notification["type"]);
  266. //saving into form object
  267. $property = $notification["type"] == "user" ? "autoResponder" : "notification";
  268. $form[$property] = $legacy_notification;
  269. }
  270. return $form;
  271. }
  272. private static function load_notifications_from_legacy($form){
  273. $form["notifications"] = array();
  274. if(GFCommon::has_admin_notification($form)){
  275. $admin_notification = $form["notification"];
  276. //if there is a fromField configured, move it to "from" as a merge tag
  277. $admin_notification = self::convert_property_to_merge_tag($form, $form["notification"], "from", "fromField");
  278. //if there is a fromNameField configured, move it to "fromName" as a merge tag
  279. $admin_notification = self::convert_property_to_merge_tag($form, $form["notification"], "fromName", "fromNameField");
  280. //if there is a replyToField configured, move it to "replyTo" as a merge tag
  281. $admin_notification = self::convert_property_to_merge_tag($form, $form["notification"], "replyTo", "replyToField");
  282. //if routing is configured, set toType to routing, otherwise, set it to email
  283. $admin_notification["toType"] = !rgempty("routing", $admin_notification) ? "routing" : "email";
  284. $notification_id = uniqid();
  285. //assigning this notification to the form_submission action
  286. $admin_notification["event"] = "form_submission";
  287. $admin_notification["name"] = __("Admin Notification", "gravityforms");
  288. $admin_notification["type"] = "admin";
  289. $admin_notification["id"] = $notification_id;
  290. //copying admin notification as an item in the new notifications array
  291. $form["notifications"][$notification_id] = $admin_notification;
  292. }
  293. if(GFCommon::has_user_notification($form)){
  294. $user_notification = $form["autoResponder"];
  295. //if there is a toField configured, set toType to field, if not, set it toemail
  296. $to_field = rgar($user_notification, "toField");
  297. if(!empty($to_field)){
  298. $user_notification["toType"] = "field";
  299. $user_notification["to"] = $to_field;
  300. }
  301. else{
  302. $user_notification["toType"] = "email";
  303. }
  304. $notification_id = uniqid();
  305. //assigning this notification to the form_submission action
  306. $user_notification["event"] = "form_submission";
  307. $user_notification["name"] = __("User Notification", "gravityforms");
  308. $user_notification["type"] = "user";
  309. $user_notification["id"] = $notification_id;
  310. //copying user notification as an item in the new notifications array
  311. $form["notifications"][$notification_id] = $user_notification;
  312. }
  313. self::save_form_notifications($form["id"], $form["notifications"]);
  314. return $form;
  315. }
  316. private static function convert_property_to_merge_tag($form, $array, $target_property, $source_property){
  317. $merge_tag = self::get_field_merge_tag($form, rgar($array, $source_property));
  318. if($merge_tag){
  319. $array[$target_property] = $merge_tag;
  320. unset($array[$source_property]);
  321. }
  322. return $array;
  323. }
  324. private static function get_field_merge_tag($form, $field_id){
  325. $field = self::get_field($form, $field_id);
  326. if(!$field)
  327. return false;
  328. return "{" . GFCommon::get_label($field, $field_id) . ":" . $field_id . "}";
  329. }
  330. public static function add_default_properties($form){
  331. if(is_array(rgar($form,"fields"))){
  332. $all_fields = array("adminLabel"=>"","adminOnly"=>"","allowsPrepopulate"=>"","defaultValue"=>"","description"=>"","content"=>"","cssClass"=>"",
  333. "errorMessage"=>"","id"=>"","inputName"=>"","isRequired"=>"","label"=>"","noDuplicates"=>"",
  334. "size"=>"","type"=>"","postCustomFieldName"=>"","displayAllCategories"=>"","displayCaption"=>"","displayDescription"=>"",
  335. "displayTitle"=>"","inputType"=>"","rangeMin"=>"","rangeMax"=>"","calendarIconType"=>"",
  336. "calendarIconUrl"=>"", "dateType"=>"","dateFormat"=>"","phoneFormat"=>"","addressType"=>"","defaultCountry"=>"","defaultProvince"=>"",
  337. "defaultState"=>"","hideAddress2"=>"","hideCountry"=>"","hideState"=>"","inputs"=>"","nameFormat"=>"","allowedExtensions"=>"",
  338. "captchaType"=>"","pageNumber"=>"","captchaTheme"=>"","simpleCaptchaSize"=>"","simpleCaptchaFontColor"=>"","simpleCaptchaBackgroundColor"=>"",
  339. "failed_validation"=>"", "productField" => "", "enablePasswordInput" => "", "maxLength" => "", "enablePrice" => "", "basePrice" => "");
  340. foreach($form["fields"] as &$field)
  341. $field = wp_parse_args($field, $all_fields);
  342. }
  343. return $form;
  344. }
  345. public static function get_grid_column_meta($form_id){
  346. global $wpdb;
  347. $table_name = self::get_meta_table_name();
  348. return maybe_unserialize($wpdb->get_var($wpdb->prepare("SELECT entries_grid_meta FROM $table_name WHERE form_id=%d", $form_id)));
  349. }
  350. public static function update_grid_column_meta($form_id, $columns){
  351. global $wpdb;
  352. $table_name = self::get_meta_table_name();
  353. $meta = maybe_serialize(stripslashes_deep($columns) );
  354. $wpdb->query( $wpdb->prepare("UPDATE $table_name SET entries_grid_meta=%s WHERE form_id=%d", $meta, $form_id) );
  355. }
  356. public static function get_lead_detail_id($current_fields, $field_number){
  357. foreach($current_fields as $field)
  358. if($field->field_number == $field_number)
  359. return $field->id;
  360. return 0;
  361. }
  362. public static function update_form_active($form_id, $is_active){
  363. global $wpdb;
  364. $form_table = self::get_form_table_name();
  365. $sql = $wpdb->prepare("UPDATE $form_table SET is_active=%d WHERE id=%d", $is_active, $form_id);
  366. $wpdb->query($sql);
  367. }
  368. public static function update_forms_active($forms, $is_active){
  369. foreach($forms as $form_id)
  370. self::update_form_active($form_id, $is_active);
  371. }
  372. public static function update_leads_property($leads, $property_name, $property_value){
  373. foreach($leads as $lead)
  374. self::update_lead_property($lead, $property_name, $property_value);
  375. }
  376. public static function update_lead_property($lead_id, $property_name, $property_value, $update_akismet=true, $disable_hook=false){
  377. global $wpdb;
  378. $lead_table = self::get_lead_table_name();
  379. $lead = self::get_lead($lead_id);
  380. //marking entry as "spam" or "not spam" with Akismet if the plugin is installed
  381. if($update_akismet && GFCommon::akismet_enabled($lead["form_id"]) && $property_name == "status" && in_array($property_value, array("active", "spam"))){
  382. $current_status = $lead["status"];
  383. if($current_status == "spam" && $property_value == "active"){
  384. $form = self::get_form_meta($lead["form_id"]);
  385. GFCommon::mark_akismet_spam($form, $lead, false);
  386. }
  387. else if($current_status == "active" && $property_value == "spam"){
  388. $form = self::get_form_meta($lead["form_id"]);
  389. GFCommon::mark_akismet_spam($form, $lead, true);
  390. }
  391. }
  392. //updating lead
  393. $wpdb->update($lead_table, array($property_name => $property_value ), array("id" => $lead_id));
  394. if(!$disable_hook){
  395. $previous_value = rgar($lead, $property_name);
  396. if($previous_value != $property_value) {
  397. // if property is status, prev value is spam and new value is active
  398. if($property_name == 'status' && $previous_value == 'spam' && $property_value == 'active' && !rgar($lead, 'post_id')) {
  399. $lead[$property_name] = $property_value;
  400. $lead['post_id'] = GFCommon::create_post($form, $lead);
  401. }
  402. do_action("gform_update_{$property_name}", $lead_id, $property_value, $previous_value);
  403. }
  404. }
  405. }
  406. public static function update_lead($lead){
  407. global $wpdb;
  408. $lead_table = self::get_lead_table_name();
  409. $payment_date = strtotime(rgar($lead,"payment_date")) ? "'" . gmdate( 'Y-m-d H:i:s', strtotime("{$lead["payment_date"]}") ) . "'" : "NULL";
  410. $payment_amount = !rgblank(rgar($lead, "payment_amount")) ? (float) rgar($lead, "payment_amount") : "NULL";
  411. $transaction_type = !rgempty("transaction_type", $lead) ? intval($lead["transaction_type"]) : "NULL";
  412. $status = !rgempty("status", $lead) ? $lead["status"] : "active";
  413. $sql = $wpdb->prepare("UPDATE $lead_table SET
  414. form_id=%d,
  415. post_id=%d,
  416. is_starred=%d,
  417. is_read=%d,
  418. ip=%s,
  419. source_url=%s,
  420. user_agent=%s,
  421. currency=%s,
  422. payment_status=%s,
  423. payment_date={$payment_date},
  424. payment_amount={$payment_amount},
  425. transaction_id=%s,
  426. is_fulfilled=%d,
  427. transaction_type={$transaction_type},
  428. status='{$status}'
  429. WHERE id=%d", rgar($lead,"form_id"), rgar($lead,"post_id"), rgar($lead,"is_starred"), rgar($lead,"is_read"), rgar($lead,"ip"), rgar($lead,"source_url"), rgar($lead,"user_agent"),
  430. rgar($lead,"currency"), rgar($lead,"payment_status"), rgar($lead,"transaction_id"), rgar($lead,"is_fulfilled"), rgar($lead,"id"));
  431. $wpdb->query($sql);
  432. self::set_current_lead($lead);
  433. }
  434. public static function delete_leads($leads){
  435. foreach($leads as $lead_id)
  436. self::delete_lead($lead_id);
  437. }
  438. public static function delete_forms($forms){
  439. foreach($forms as $form_id)
  440. self::delete_form($form_id);
  441. }
  442. public static function delete_leads_by_form($form_id, $status=""){
  443. global $wpdb;
  444. if(!GFCommon::current_user_can_any("gravityforms_delete_entries"))
  445. die(__("You don't have adequate permission to delete entries.", "gravityforms"));
  446. $lead_table = self::get_lead_table_name();
  447. $lead_notes_table = self::get_lead_notes_table_name();
  448. $lead_detail_table = self::get_lead_details_table_name();
  449. $lead_detail_long_table = self::get_lead_details_long_table_name();
  450. //deleting uploaded files
  451. self::delete_files_by_form($form_id, $status);
  452. $status_filter = empty($status) ? "" : $wpdb->prepare("AND status=%s", $status);
  453. //Delete from detail long
  454. $sql = $wpdb->prepare(" DELETE FROM $lead_detail_long_table
  455. WHERE lead_detail_id IN(
  456. SELECT ld.id FROM $lead_detail_table ld
  457. INNER JOIN $lead_table l ON l.id = ld.lead_id
  458. WHERE l.form_id=%d AND ld.form_id=%d {$status_filter}
  459. )", $form_id, $form_id);
  460. $wpdb->query($sql);
  461. //Delete from lead details
  462. $sql = $wpdb->prepare(" DELETE FROM $lead_detail_table
  463. WHERE lead_id IN (
  464. SELECT id FROM $lead_table WHERE form_id=%d {$status_filter}
  465. )", $form_id);
  466. $wpdb->query($sql);
  467. //Delete from lead notes
  468. $sql = $wpdb->prepare(" DELETE FROM $lead_notes_table
  469. WHERE lead_id IN (
  470. SELECT id FROM $lead_table WHERE form_id=%d {$status_filter}
  471. )", $form_id);
  472. $wpdb->query($sql);
  473. //Delete from lead
  474. $sql = $wpdb->prepare("DELETE FROM $lead_table WHERE form_id=%d {$status_filter}", $form_id);
  475. $wpdb->query($sql);
  476. }
  477. public static function delete_views($form_id){
  478. global $wpdb;
  479. $form_view_table = self::get_form_view_table_name();
  480. //Delete form view
  481. $sql = $wpdb->prepare("DELETE FROM $form_view_table WHERE form_id=%d", $form_id);
  482. $wpdb->query($sql);
  483. }
  484. public static function delete_form($form_id){
  485. global $wpdb;
  486. if(!GFCommon::current_user_can_any("gravityforms_delete_forms"))
  487. die(__("You don't have adequate permission to delete forms.", "gravityforms"));
  488. do_action("gform_before_delete_form", $form_id);
  489. $form_meta_table = self::get_meta_table_name();
  490. $form_table = self::get_form_table_name();
  491. //Deleting form Entries
  492. self::delete_leads_by_form($form_id);
  493. //Delete form meta
  494. $sql = $wpdb->prepare("DELETE FROM $form_meta_table WHERE form_id=%d", $form_id);
  495. $wpdb->query($sql);
  496. //Deleting form Views
  497. self::delete_views($form_id);
  498. //Delete form
  499. $sql = $wpdb->prepare("DELETE FROM $form_table WHERE id=%d", $form_id);
  500. $wpdb->query($sql);
  501. do_action("gform_after_delete_form", $form_id);
  502. }
  503. public static function duplicate_form($form_id){
  504. global $wpdb;
  505. if(!GFCommon::current_user_can_any("gravityforms_create_form"))
  506. die(__("You don't have adequate permission to create forms.", "gravityforms"));
  507. //finding unique title
  508. $form = self::get_form($form_id);
  509. $count = 2;
  510. $title = $form->title . " - Copy 1";
  511. while(!self::is_unique_title($title)){
  512. $title = $form->title . " - Copy $count";
  513. $count++;
  514. }
  515. //creating new form
  516. $new_id = self::insert_form($title);
  517. //copying form meta
  518. $meta = self::get_form_meta($form_id);
  519. $meta["title"] = $title;
  520. $meta["id"] = $new_id;
  521. self::update_form_meta($new_id, $meta);
  522. return $new_id;
  523. }
  524. public static function is_unique_title($title){
  525. $forms = self::get_forms();
  526. foreach($forms as $form){
  527. if(strtolower($form->title) == strtolower($title))
  528. return false;
  529. }
  530. return true;
  531. }
  532. public static function ensure_tables_exist(){
  533. global $wpdb;
  534. $form_table_name = self::get_form_table_name();
  535. $form_count = $wpdb->get_var("SELECT count(0) FROM {$form_table_name}");
  536. if($wpdb->last_error){
  537. GFForms::setup(true);
  538. }
  539. }
  540. public static function insert_form($form_title){
  541. global $wpdb;
  542. $form_table_name = $wpdb->prefix . "rg_form";
  543. //creating new form
  544. $wpdb->query($wpdb->prepare("INSERT INTO $form_table_name(title, date_created) VALUES(%s, utc_timestamp())", $form_title));
  545. //returning newly created form id
  546. return $wpdb->insert_id;
  547. }
  548. public static function update_form_meta($form_id, $form_meta, $meta_name="display_meta"){
  549. global $wpdb;
  550. $meta_table_name = self::get_meta_table_name();
  551. $form_meta = maybe_serialize($form_meta);
  552. if(intval($wpdb->get_var($wpdb->prepare("SELECT count(0) FROM $meta_table_name WHERE form_id=%d", $form_id))) > 0)
  553. $result = $wpdb->query( $wpdb->prepare("UPDATE $meta_table_name SET $meta_name=%s WHERE form_id=%d", $form_meta, $form_id) );
  554. else
  555. $result = $wpdb->query( $wpdb->prepare("INSERT INTO $meta_table_name(form_id, $meta_name) VALUES(%d, %s)", $form_id, $form_meta ) );
  556. return $result;
  557. }
  558. public static function delete_files($lead_id, $form=null){
  559. $lead = self::get_lead($lead_id);
  560. if($form == null)
  561. $form = self::get_form_meta($lead["form_id"]);
  562. $fields = GFCommon::get_fields_by_type($form, array("fileupload", "post_image"));
  563. if(is_array($fields)){
  564. foreach($fields as $field){
  565. $value = self::get_lead_field_value($lead, $field);
  566. self::delete_physical_file($value);
  567. }
  568. }
  569. }
  570. public static function delete_files_by_form($form_id, $status=""){
  571. global $wpdb;
  572. $form = self::get_form_meta($form_id);
  573. $fields = GFCommon::get_fields_by_type($form, array("fileupload", "post_image"));
  574. if(empty($fields))
  575. return;
  576. $status_filter = empty($status) ? "" : $wpdb->prepare("AND status=%s", $status);
  577. $results = $wpdb->get_results($wpdb->prepare("SELECT id FROM {$wpdb->prefix}rg_lead WHERE form_id=%d {$status_filter}", $form_id), ARRAY_A);
  578. foreach($results as $result){
  579. self::delete_files($result["id"], $form);
  580. }
  581. }
  582. public static function delete_file($lead_id, $field_id){
  583. global $wpdb;
  584. if($lead_id == 0 || $field_id == 0)
  585. return;
  586. $lead_detail_table = self::get_lead_details_table_name();
  587. //Deleting file
  588. $sql = $wpdb->prepare("SELECT value FROM $lead_detail_table WHERE lead_id=%d AND field_number BETWEEN %s AND %s", $lead_id, doubleval($field_id) - 0.001, doubleval($field_id) + 0.001);
  589. $file_path = $wpdb->get_var($sql);
  590. self::delete_physical_file($file_path);
  591. //Delete from lead details
  592. $sql = $wpdb->prepare("DELETE FROM $lead_detail_table WHERE lead_id=%d AND field_number BETWEEN %s AND %s", $lead_id, doubleval($field_id) - 0.001, doubleval($field_id) + 0.001);
  593. $wpdb->query($sql);
  594. }
  595. private static function delete_physical_file($file_url){
  596. $ary = explode("|:|", $file_url);
  597. $url = rgar($ary,0);
  598. if(empty($url))
  599. return;
  600. //Convert from url to physical path
  601. if (is_multisite()) {
  602. $file_path = preg_replace("|^(.*?)/files/gravity_forms/|", BLOGUPLOADDIR . "gravity_forms/", $url);
  603. }
  604. else {
  605. $file_path = str_replace(WP_CONTENT_URL, WP_CONTENT_DIR, $url);
  606. }
  607. if(file_exists($file_path)){
  608. unlink($file_path);
  609. }
  610. }
  611. public static function delete_field($form_id, $field_id){
  612. global $wpdb;
  613. if($form_id == 0)
  614. return;
  615. do_action("gform_before_delete_field", $form_id, $field_id);
  616. $lead_table = self::get_lead_table_name();
  617. $lead_detail_table = self::get_lead_details_table_name();
  618. $lead_detail_long_table = self::get_lead_details_long_table_name();
  619. $form = self::get_form_meta($form_id);
  620. $field_type = "";
  621. //Deleting field from form meta
  622. $count = sizeof($form["fields"]);
  623. for($i = $count-1; $i >= 0; $i--){
  624. $field = $form["fields"][$i];
  625. //Deleting associated conditional logic rules
  626. if(!empty($field["conditionalLogic"])){
  627. $rule_count = sizeof($field["conditionalLogic"]["rules"]);
  628. for($j = $rule_count-1; $j >= 0; $j--){
  629. if($field["conditionalLogic"]["rules"][$j]["fieldId"] == $field_id){
  630. unset($form["fields"][$i]["conditionalLogic"]["rules"][$j]);
  631. }
  632. }
  633. $form["fields"][$i]["conditionalLogic"]["rules"] = array_values($form["fields"][$i]["conditionalLogic"]["rules"]);
  634. //If there aren't any rules, remove the conditional logic
  635. if(sizeof($form["fields"][$i]["conditionalLogic"]["rules"]) == 0){
  636. $form["fields"][$i]["conditionalLogic"] = false;
  637. }
  638. }
  639. //Deleting field from form meta
  640. if($field["id"] == $field_id){
  641. $field_type = $field["type"];
  642. unset($form["fields"][$i]);
  643. }
  644. }
  645. //removing post content and title template if the field being deleted is a post content field or post title field
  646. if($field_type == "post_content"){
  647. $form["postContentTemplateEnabled"] = false;
  648. $form["postContentTemplate"] = "";
  649. }
  650. else if($field_type == "post_title"){
  651. $form["postTitleTemplateEnabled"] = false;
  652. $form["postTitleTemplate"] = "";
  653. }
  654. //Deleting associated routing rules
  655. if(!empty($form["notification"]["routing"])){
  656. $routing_count = sizeof($form["notification"]["routing"]);
  657. for($j = $routing_count-1; $j >= 0; $j--){
  658. if(intval($form["notification"]["routing"][$j]["fieldId"]) == $field_id){
  659. unset($form["notification"]["routing"][$j]);
  660. }
  661. }
  662. $form["notification"]["routing"] = array_values($form["notification"]["routing"]);
  663. //If there aren't any routing, remove it
  664. if(sizeof($form["notification"]["routing"]) == 0){
  665. $form["notification"]["routing"] = null;
  666. }
  667. }
  668. $form["fields"] = array_values($form["fields"]);
  669. self::update_form_meta($form_id, $form);
  670. //Delete from grid column meta
  671. $columns = self::get_grid_column_meta($form_id);
  672. $count = sizeof($columns);
  673. for($i = $count -1; $i >=0; $i--)
  674. {
  675. if(intval(rgar($columns,$i)) == intval($field_id)){
  676. unset($columns[$i]);
  677. }
  678. }
  679. self::update_grid_column_meta($form_id, $columns);
  680. //Delete from detail long
  681. $sql = $wpdb->prepare(" DELETE FROM $lead_detail_long_table
  682. WHERE lead_detail_id IN(
  683. SELECT id FROM $lead_detail_table WHERE form_id=%d AND field_number >= %d AND field_number < %d
  684. )", $form_id, $field_id, $field_id + 1);
  685. $wpdb->query($sql);
  686. //Delete from lead details
  687. $sql = $wpdb->prepare("DELETE FROM $lead_detail_table WHERE form_id=%d AND field_number >= %d AND field_number < %d", $form_id, $field_id, $field_id + 1);
  688. $wpdb->query($sql);
  689. //Delete leads with no details
  690. $sql = $wpdb->prepare(" DELETE FROM $lead_table
  691. WHERE form_id=%d
  692. AND id NOT IN(
  693. SELECT DISTINCT(lead_id) FROM $lead_detail_table WHERE form_id=%d
  694. )", $form_id, $form_id);
  695. $wpdb->query($sql);
  696. do_action("gform_after_delete_field", $form_id, $field_id);
  697. }
  698. public static function delete_lead($lead_id){
  699. global $wpdb;
  700. if(!GFCommon::current_user_can_any("gravityforms_delete_entries"))
  701. die(__("You don't have adequate permission to delete entries.", "gravityforms"));
  702. do_action("gform_delete_lead", $lead_id);
  703. $lead_table = self::get_lead_table_name();
  704. $lead_notes_table = self::get_lead_notes_table_name();
  705. $lead_detail_table = self::get_lead_details_table_name();
  706. $lead_detail_long_table = self::get_lead_details_long_table_name();
  707. //deleting uploaded files
  708. self::delete_files($lead_id);
  709. //Delete from detail long
  710. $sql = $wpdb->prepare(" DELETE FROM $lead_detail_long_table
  711. WHERE lead_detail_id IN(
  712. SELECT id FROM $lead_detail_table WHERE lead_id=%d
  713. )", $lead_id);
  714. $wpdb->query($sql);
  715. //Delete from lead details
  716. $sql = $wpdb->prepare("DELETE FROM $lead_detail_table WHERE lead_id=%d", $lead_id);
  717. $wpdb->query($sql);
  718. //Delete from lead notes
  719. $sql = $wpdb->prepare("DELETE FROM $lead_notes_table WHERE lead_id=%d", $lead_id);
  720. $wpdb->query($sql);
  721. //Delete from lead meta
  722. gform_delete_meta($lead_id);
  723. //Delete from lead
  724. $sql = $wpdb->prepare("DELETE FROM $lead_table WHERE id=%d", $lead_id);
  725. $wpdb->query($sql);
  726. }
  727. public static function add_note($lead_id, $user_id, $user_name, $note){
  728. global $wpdb;
  729. $table_name = self::get_lead_notes_table_name();
  730. $sql = $wpdb->prepare("INSERT INTO $table_name(lead_id, user_id, user_name, value, date_created) values(%d, %d, %s, %s, utc_timestamp())", $lead_id, $user_id, $user_name, $note);
  731. $wpdb->query($sql);
  732. }
  733. public static function delete_note($note_id){
  734. global $wpdb;
  735. if(!GFCommon::current_user_can_any("gravityforms_edit_entry_notes"))
  736. die(__("You don't have adequate permission to delete notes.", "gravityforms"));
  737. $table_name = self::get_lead_notes_table_name();
  738. $sql = $wpdb->prepare("DELETE FROM $table_name WHERE id=%d", $note_id);
  739. $wpdb->query($sql);
  740. }
  741. public static function delete_notes($notes){
  742. if(!is_array($notes))
  743. return;
  744. foreach($notes as $note_id){
  745. self::delete_note($note_id);
  746. }
  747. }
  748. public static function get_ip(){
  749. $ip = rgget("HTTP_X_FORWARDED_FOR", $_SERVER);
  750. if (!$ip)
  751. $ip = rgget("REMOTE_ADDR", $_SERVER);
  752. $ip_array = explode(",", $ip); //HTTP_X_FORWARDED_FOR can return a comma separated list of IPs. Using the first one.
  753. return $ip_array[0];
  754. }
  755. public static function save_lead($form, &$lead){
  756. global $wpdb;
  757. GFCommon::log_debug("Saving entry.");
  758. if(IS_ADMIN && !GFCommon::current_user_can_any("gravityforms_edit_entries"))
  759. die(__("You don't have adequate permission to edit entries.", "gravityforms"));
  760. $lead_detail_table = self::get_lead_details_table_name();
  761. //Inserting lead if null
  762. if($lead == null){
  763. global $current_user;
  764. $user_id = $current_user && $current_user->ID ? $current_user->ID : 'NULL';
  765. $lead_table = RGFormsModel::get_lead_table_name();
  766. $user_agent = strlen($_SERVER["HTTP_USER_AGENT"]) > 250 ? substr($_SERVER["HTTP_USER_AGENT"], 0, 250) : $_SERVER["HTTP_USER_AGENT"];
  767. $currency = GFCommon::get_currency();
  768. $wpdb->query($wpdb->prepare("INSERT INTO $lead_table(form_id, ip, source_url, date_created, user_agent, currency, created_by) VALUES(%d, %s, %s, utc_timestamp(), %s, %s, {$user_id})", $form["id"], self::get_ip(), self::get_current_page_url(), $user_agent, $currency));
  769. //reading newly created lead id
  770. $lead_id = $wpdb->insert_id;
  771. $lead = array("id" => $lead_id);
  772. GFCommon::log_debug("Entry record created in the database. ID: {$lead_id}");
  773. }
  774. $current_fields = $wpdb->get_results($wpdb->prepare("SELECT id, field_number FROM $lead_detail_table WHERE lead_id=%d", $lead["id"]));
  775. $original_post_id = rgget("post_id", $lead);
  776. $total_field = null;
  777. $calculation_fields = array();
  778. $recalculate_total = false;
  779. GFCommon::log_debug("Saving entry fields.");
  780. foreach($form["fields"] as $field){
  781. //Ignore fields that are marked as display only
  782. if(rgget("displayOnly", $field) && $field["type"] != "password"){
  783. continue;
  784. }
  785. //ignore pricing fields in the entry detail
  786. if(RG_CURRENT_VIEW == "entry" && GFCommon::is_pricing_field($field["type"])){
  787. continue;
  788. }
  789. //process total field after all fields have been saved
  790. if($field["type"] == "total"){
  791. $total_field = $field;
  792. continue;
  793. }
  794. //only save fields that are not hidden (except on entry screen)
  795. if(RG_CURRENT_VIEW == "entry" || !RGFormsModel::is_field_hidden($form, $field, array()) ){
  796. // process calculation fields after all fields have been saved (moved after the is hidden check)
  797. if( GFCommon::has_field_calculation($field) ) {
  798. $calculation_fields[] = $field;
  799. continue;
  800. }
  801. GFCommon::log_debug("Saving field {$field["label"]}");
  802. if($field['type'] == 'post_category')
  803. $field = GFCommon::add_categories_as_choices($field, '');
  804. if(isset($field["inputs"]) && is_array($field["inputs"])){
  805. foreach($field["inputs"] as $input)
  806. self::save_input($form, $field, $lead, $current_fields, $input["id"]);
  807. }
  808. else{
  809. self::save_input($form, $field, $lead, $current_fields, $field["id"]);
  810. }
  811. }
  812. }
  813. if(!empty($calculation_fields)) {
  814. foreach($calculation_fields as $calculation_field) {
  815. GFCommon::log_debug("Saving calculated field {$calculation_field["label"]}");
  816. if(isset($calculation_field["inputs"]) && is_array($calculation_field["inputs"])){
  817. foreach($calculation_field["inputs"] as $input) {
  818. self::save_input($form, $calculation_field, $lead, $current_fields, $input["id"]);
  819. }
  820. }
  821. else{
  822. self::save_input($form, $calculation_field, $lead, $current_fields, $calculation_field["id"]);
  823. }
  824. }
  825. self::refresh_product_cache($form, $lead = RGFormsModel::get_lead($lead['id']));
  826. }
  827. //saving total field as the last field of the form.
  828. if($total_field) {
  829. GFCommon::log_debug("Saving total field.");
  830. self::save_input($form, $total_field, $lead, $current_fields, $total_field["id"]);
  831. }
  832. }
  833. public static function create_lead($form) {
  834. global $current_user;
  835. $calculation_fields = array();
  836. $lead = array();
  837. $lead['id'] = null;
  838. $lead['post_id'] = null;
  839. $lead['date_created'] = null;
  840. $lead['form_id'] = $form['id'];
  841. $lead['ip'] = self::get_ip();
  842. $lead['source_url'] = self::get_current_page_url();
  843. $lead['user_agent'] = strlen($_SERVER['HTTP_USER_AGENT']) > 250 ? substr($_SERVER['HTTP_USER_AGENT'], 0, 250) : $_SERVER['HTTP_USER_AGENT'];
  844. $lead['currency'] = GFCommon::get_currency();
  845. $lead['created_by'] = $current_user && $current_user->ID ? $current_user->ID : 'NULL';
  846. foreach($form['fields'] as $field) {
  847. // ignore fields that are marked as display only
  848. if(rgget('displayOnly', $field) && $field['type'] != 'password'){
  849. continue;
  850. }
  851. // process total field after all fields have been saved
  852. if($field['type'] == 'total'){
  853. $total_field = $field;
  854. continue;
  855. }
  856. // process calculation fields after all fields have been saved
  857. if(GFCommon::has_field_calculation($field)) {
  858. $calculation_fields[] = $field;
  859. continue;
  860. }
  861. // only save fields that are not hidden
  862. if(!RGFormsModel::is_field_hidden($form, $field, array()) ){
  863. if($field['type'] == 'post_category')
  864. $field = GFCommon::add_categories_as_choices($field, '');
  865. if(isset($field['inputs']) && is_array($field['inputs'])){
  866. foreach($field['inputs'] as $input) {
  867. $lead[(string)$input['id']] = self::get_prepared_input_value($form, $field, $lead, $input["id"]);
  868. }
  869. }
  870. else {
  871. $lead[$field['id']] = self::get_prepared_input_value($form, $field, $lead, $field["id"]);
  872. }
  873. }
  874. }
  875. if(!empty($calculation_fields)) {
  876. foreach($calculation_fields as $field) {
  877. if(isset($field["inputs"]) && is_array($field["inputs"])){
  878. foreach($field["inputs"] as $input) {
  879. $lead[(string)$input['id']] = self::get_prepared_input_value($form, $field, $lead, $input["id"]);
  880. }
  881. }
  882. else{
  883. $lead[$field['id']] = self::get_prepared_input_value($form, $field, $lead, $field["id"]);
  884. }
  885. }
  886. self::refresh_product_cache($form, $lead);
  887. }
  888. // saving total field as the last field of the form.
  889. if(isset($total_field)) {
  890. $lead[$total_field['id']] = self::get_prepared_input_value($form, $total_field, $lead, $total_field["id"]);
  891. }
  892. return $lead;
  893. }
  894. public static function get_prepared_input_value($form, $field, $lead, $input_id) {
  895. $input_name = "input_" . str_replace('.', '_', $input_id);
  896. $value = rgpost($input_name);
  897. if(empty($value) && rgar($field, "adminOnly") && !IS_ADMIN){
  898. $value = self::get_default_value($field, $input_id);
  899. }
  900. switch(self::get_input_type($field)) {
  901. case "post_image":
  902. $file_info = self::get_temp_filename($form['id'], $input_name);
  903. $file_path = self::get_file_upload_path($form['id'], $file_info["uploaded_filename"]);
  904. $url = $file_path['url'];
  905. $image_title = isset($_POST["{$input_name}_1"]) ? strip_tags($_POST["{$input_name}_1"]) : "";
  906. $image_caption = isset($_POST["{$input_name}_4"]) ? strip_tags($_POST["{$input_name}_4"]) : "";
  907. $image_description = isset($_POST["{$input_name}_7"]) ? strip_tags($_POST["{$input_name}_7"]) : "";
  908. $value = !empty($url) ? $url . "|:|" . $image_title . "|:|" . $image_caption . "|:|" . $image_description : "";
  909. break;
  910. case "fileupload" :
  911. $file_info = self::get_temp_filename($form['id'], $input_name);
  912. $file_path = self::get_file_upload_path($form['id'], $file_info["uploaded_filename"]);
  913. $value = $file_path['url'];
  914. break;
  915. default:
  916. // processing values so that they are in the correct format for each input type
  917. $value = self::prepare_value($form, $field, $value, $input_name, rgar($lead, 'id'), $lead);
  918. }
  919. return apply_filters("gform_save_field_value", $value, $lead, $field, $form);
  920. }
  921. public static function refresh_product_cache($form, $lead, $use_choice_text = false, $use_admin_label = false) {
  922. $cache_options = array(
  923. array(false, false),
  924. array(false, true),
  925. array(true, false),
  926. array(true, true)
  927. );
  928. foreach($form["fields"] as $field){
  929. if(GFCommon::has_field_calculation($field)){
  930. //deleting field value cache for calculated fields
  931. $cache_key = "GFFormsModel::get_lead_field_value_" . $lead["id"] . "_" . $field["id"];
  932. GFCache::delete($cache_key);
  933. }
  934. }
  935. foreach($cache_options as $cache_option) {
  936. list($use_choice_text, $use_admin_label) = $cache_option;
  937. if( gform_get_meta( rgar($lead,'id'), "gform_product_info_{$use_choice_text}_{$use_admin_label}") ) {
  938. gform_delete_meta(rgar($lead,'id'), "gform_product_info_{$use_choice_text}_{$use_admin_label}");
  939. GFCommon::get_product_fields($form, $lead, $use_choice_text, $use_admin_label);
  940. }
  941. }
  942. }
  943. /**
  944. * Check whether a field is hidden via conditional logic.
  945. *
  946. * @param array $form Form object.
  947. * @param array $field Field object.
  948. * @param array $field_values Default field values for this form. Used when form has not yet been submitted. Pass an array if no default field values are avilable/required.
  949. * @return array $lead Optional, default is null. If lead object is available, pass the lead.
  950. */
  951. public static function is_field_hidden($form, $field, $field_values, $lead=null){
  952. $cache_key = "GFFormsModel::is_field_hidden_" . $form["id"] . "_" . $field["id"];
  953. $display = GFCache::get($cache_key);
  954. if($display !== false)
  955. return $display;
  956. $section = self::get_section($form, $field["id"]);
  957. $section_display = self::get_field_display($form, $section, $field_values, $lead);
  958. //if section is hidden, hide field no matter what. if section is visible, see if field is supposed to be visible
  959. if($section_display == "hide"){
  960. $display = "hide";
  961. }
  962. else if(self::is_page_hidden($form, rgar($field,"pageNumber"), $field_values, $lead)){
  963. $display = "hide";
  964. }
  965. else{
  966. $display = self::get_field_display($form, $field, $field_values, $lead);
  967. return $display == "hide";
  968. }
  969. GFCache::set($cache_key, $display);
  970. return $display == "hide";
  971. }
  972. public static function is_page_hidden($form, $page_number, $field_values, $lead=null){
  973. $page = self::get_page_by_number($form, $page_number);
  974. if(!$page)
  975. return false;
  976. $display = self::get_field_display($form, $page, $field_values, $lead);
  977. return $display == "hide";
  978. }
  979. public static function get_page_by_number($form, $page_number){
  980. foreach($form["fields"] as $field){
  981. if($field["type"] == "page" && $field["pageNumber"] == $page_number)
  982. return $field;
  983. }
  984. return null;
  985. }
  986. public static function get_page_by_field($form, $field){
  987. return get_page_by_number($field["pageNumber"]);
  988. }
  989. //gets the section that the specified field belongs to, or null if none
  990. public static function get_section($form, $field_id){
  991. $current_section = null;
  992. foreach($form["fields"] as $field){
  993. if($field["type"] == "section")
  994. $current_section = $field;
  995. //stop section at a page break (sections don't go cross page)
  996. if($field["type"] == "page")
  997. $current_section = null;
  998. if($field["id"] == $field_id)
  999. return $current_section;
  1000. }
  1001. return null;
  1002. }
  1003. public static function is_value_match($field_value, $target_value, $operation="is", $source_field=null){
  1004. if($source_field && $source_field["type"] == "post_category"){
  1005. $field_value = GFCommon::prepare_post_category_value($field_value, $source_field, "conditional_logic");
  1006. }
  1007. if (!empty($field_value) && !is_array($field_value) && $source_field["type"] == "multiselect")
  1008. {
  1009. //convert the comma-delimited string into an array
  1010. $field_value = explode(",", $field_value);
  1011. }
  1012. if(is_array($field_value)){
  1013. $field_value = array_values($field_value); //returning array values, ignoring keys if array is associative
  1014. $match_count = 0;
  1015. foreach($field_value as $val){
  1016. if(self::matches_operation(GFCommon::get_selection_value($val), $target_value, $operation)){
  1017. $match_count++;
  1018. }
  1019. }
  1020. //If operation is Is Not, none of the values in the array can match the target value.
  1021. return $operation == "isnot" ? $match_count == count($field_value) : $match_count > 0;
  1022. }
  1023. else if(self::matches_operation(GFCommon::get_selection_value($field_value), $target_value, $operation)){
  1024. return true;
  1025. }
  1026. return false;
  1027. }
  1028. private static function try_convert_float($text){
  1029. global $wp_locale;
  1030. $number_format = $wp_locale->number_format['decimal_point'] == "," ? "decimal_comma" : "decimal_dot";
  1031. if(GFCommon::is_numeric($text, $number_format))
  1032. return GFCommon::clean_number($text, $number_format);
  1033. return $text;
  1034. }
  1035. public static function matches_operation($val1, $val2, $operation){
  1036. $val1 = !rgblank($val1) ? strtolower($val1) : "";
  1037. $val2 = !rgblank($val2) ? strtolower($val2) : "";
  1038. switch($operation){
  1039. case "is" :
  1040. return $val1 == $val2;
  1041. break;
  1042. case "isnot" :
  1043. return $val1 != $val2;
  1044. break;
  1045. case "greater_than":
  1046. case ">" :
  1047. $val1 = self::try_convert_float($val1);
  1048. $val2 = self::try_convert_float($val2);
  1049. return $val1 > $val2;
  1050. break;
  1051. case "less_than":
  1052. case "<" :
  1053. $val1 = self::try_convert_float($val1);
  1054. $val2 = self::try_convert_float($val2);
  1055. return $val1 < $val2;
  1056. break;
  1057. case "contains" :
  1058. return !empty($val2) && strpos($val1, $val2) !== false;
  1059. break;
  1060. case "starts_with" :
  1061. return !empty($val2) && strpos($val1, $val2) === 0;
  1062. break;
  1063. case "ends_with" :
  1064. $start = strlen($val1) - strlen($val2);
  1065. if($start < 0)
  1066. return false;
  1067. $tail = substr($val1, $start);
  1068. return $val2 == $tail;
  1069. break;
  1070. }
  1071. return false;
  1072. }
  1073. private static function get_field_display($form, $field, $field_values, $lead=null){
  1074. $logic = rgar($field, "conditionalLogic");
  1075. //if this field does not have any conditional logic associated with it, it won't be hidden
  1076. if(empty($logic))
  1077. return "show";
  1078. $match_count = 0;
  1079. foreach($logic["rules"] as $rule){
  1080. $source_field = RGFormsModel::get_field($form, $rule["fieldId"]);
  1081. $field_value = empty($lead) ? self::get_field_value($source_field, $field_values) : self::get_lead_field_value($lead, $source_field);
  1082. $is_value_match = self::is_value_match($field_value, $rule["value"], $rule["operator"], $source_field);
  1083. if($is_value_match)
  1084. $match_count++;
  1085. }
  1086. $do_action = ($logic["logicType"] == "all" && $match_count == sizeof($logic["rules"]) ) || ($logic["logicType"] == "any" && $match_count > 0);
  1087. $is_hidden = ($do_action && $logic["actionType"] == "hide") || (!$do_action && $logic["actionType"] == "show");
  1088. return $is_hidden ? "hide" : "show";
  1089. }
  1090. public static function get_custom_choices(){
  1091. $choices = get_option("gform_custom_choices");
  1092. if(!$choices)
  1093. $choices = array();
  1094. return $choices;
  1095. }
  1096. public static function delete_custom_choice($name){
  1097. $choices = self::get_custom_choices();
  1098. if(array_key_exists($name, $choices))
  1099. unset($choices[$name]);
  1100. update_option("gform_custom_choices", $choices);
  1101. }
  1102. public static function save_custom_choice($previous_name, $new_name, $choices){
  1103. $all_choices = self::get_custom_choices();
  1104. if(array_key_exists($previous_name, $all_choices))
  1105. unset($all_choices[$previous_name]);
  1106. $all_choices[$new_name] = $choices;
  1107. update_option("gform_custom_choices", $all_choices);
  1108. }
  1109. public static function get_field_value(&$field, $field_values = array(), $get_from_post=true){
  1110. if($field['type'] == 'post_category')
  1111. $field = GFCommon::add_categories_as_choices($field, '');
  1112. $value = array();
  1113. switch(RGFormsModel::get_input_type($field)){
  1114. case "post_image" :
  1115. $value[$field["id"] . ".1"] = self::get_input_value($field, "input_" . $field["id"] . "_1", $get_from_post);
  1116. $value[$field["id"] . ".4"] = self::get_input_value($field, "input_" . $field["id"] . "_4", $get_from_post);
  1117. $value[$field["id"] . ".7"] = self::get_input_value($field, "input_" . $field["id"] . "_7", $get_from_post);
  1118. break;
  1119. case "checkbox" :
  1120. $parameter_values = self::get_parameter_value($field["inputName"], $field_values, $field);
  1121. if(!empty($parameter_values) && !is_array($parameter_values)){
  1122. $parameter_values = explode(",", $parameter_values);
  1123. }
  1124. if(!is_array($field["inputs"]))
  1125. return "";
  1126. $choice_index = 0;
  1127. foreach($field["inputs"] as $input){
  1128. if(!empty($_POST["is_submit_" . $field["formId"]]) && $get_from_post){
  1129. $value[strval($input["id"])] = rgpost("input_" . str_replace('.', '_', strval($input["id"])));
  1130. }
  1131. else{
  1132. if(is_array($parameter_values)){
  1133. foreach($parameter_values as $item){
  1134. $item = trim($item);
  1135. if(self::choice_value_match($field, $field["choices"][$choice_index], $item))
  1136. {
  1137. $value[$input["id"] . ""] = $item;
  1138. break;
  1139. }
  1140. }
  1141. }
  1142. }
  1143. $choice_index++;
  1144. }
  1145. break;
  1146. case "list" :
  1147. $value = self::get_input_value($field, "input_" . $field["id"], rgar($field, "inputName"), $field_values, $get_from_post);
  1148. $value = self::create_list_array($field, $value);
  1149. break;
  1150. case "number" :
  1151. $value = self::get_input_value($field, "input_" . $field["id"], rgar($field, "inputName"), $field_values, $get_from_post);
  1152. $value = trim($value);
  1153. break;
  1154. default:
  1155. if(isset($field["inputs"]) && is_array($field["inputs"])){
  1156. foreach($field["inputs"] as $input){
  1157. $value[strval($input["id"])] = self::get_input_value($field, "input_" . str_replace('.', '_', strval($input["id"])), RGForms::get("name", $input), $field_values, $get_from_post);
  1158. }
  1159. }
  1160. else{
  1161. $value = self::get_input_value($field, "input_" . $field["id"], rgar($field, "inputName"), $field_values, $get_from_post);
  1162. }
  1163. break;
  1164. }
  1165. return $value;
  1166. }
  1167. private static function get_input_value($field, $standard_name, $custom_name = "", $field_values=array(), $get_from_post=true){
  1168. if(!empty($_POST["is_submit_" . rgar($field,"formId")]) && $get_from_post){
  1169. return rgpost($standard_name);
  1170. }
  1171. else if(rgar($field, "allowsPrepopulate")){
  1172. return self::get_parameter_value($custom_name, $field_values, $field);
  1173. }
  1174. }
  1175. public static function get_parameter_value($name, $field_values, $field){
  1176. $value = stripslashes(rgget($name));
  1177. if(empty($value))
  1178. $value = rgget($name, $field_values);
  1179. //converting list format
  1180. if(RGFormsModel::get_input_type($field) == "list"){
  1181. //transforms this: col1|col2,col1b|col2b into this: col1,col2,col1b,col2b
  1182. $column_count = count(rgar($field,"choices"));
  1183. $rows = explode(",", $value);
  1184. $ary_rows = array();
  1185. if(!empty($rows)){
  1186. foreach($rows as $row)
  1187. $ary_rows = array_merge($ary_rows, rgexplode("|", $row, $column_count));
  1188. $value = $ary_rows;
  1189. }
  1190. }
  1191. return apply_filters("gform_field_value_$name", $value);
  1192. }
  1193. public static function get_default_value($field, $input_id){
  1194. if(!is_array(rgar($field,"choices"))){
  1195. if(is_array(rgar($field, "inputs"))){
  1196. $input = RGFormsModel::get_input($field, $input_id);
  1197. return rgar($input, "defaultValue");
  1198. }
  1199. else{
  1200. return IS_ADMIN ? $field["defaultValue"] : GFCommon::replace_variables_prepopulate($field["defaultValue"]);
  1201. }
  1202. }
  1203. else if($field["type"] == "checkbox"){
  1204. for($i=0, $count=sizeof($field["inputs"]); $i<$count; $i++){
  1205. $input = $field["inputs"][$i];
  1206. $choice = $field["choices"][$i];
  1207. if($input["id"] == $input_id && $choice["isSelected"]){
  1208. return $choice["value"];
  1209. }
  1210. }
  1211. return "";
  1212. }
  1213. else{
  1214. foreach($field["choices"] as $choice){
  1215. if(rgar($choice,"isSelected") || $field["type"] == "post_category")
  1216. return $choice["value"];
  1217. }
  1218. return "";
  1219. }
  1220. }
  1221. public static function get_input_type($field){
  1222. return empty($field["inputType"]) ? rgar($field,"type") : $field["inputType"];
  1223. }
  1224. private static function get_post_field_value($field, $lead){
  1225. if(is_array($field["inputs"])){
  1226. $value = array();
  1227. foreach($field["inputs"] as $input){
  1228. $val = isset($lead[strval($input["id"])]) ? $lead[strval($input["id"])] : "";
  1229. if(!empty($val)) {
  1230. // replace commas in individual values to prevent individual value from being split into multiple values (checkboxes, multiselects)
  1231. if( in_array(RGFormsModel::get_input_type($field), array('checkbox', 'multiselect')) )
  1232. $val = str_replace(',', '&#44;', $val);
  1233. $value[] = $val;
  1234. }
  1235. }
  1236. $value = implode(",", $value);
  1237. }
  1238. else{
  1239. $value = isset($lead[$field["id"]]) ? $lead[$field["id"]] : "";
  1240. }
  1241. return $value;
  1242. }
  1243. private static function get_post_fields($form, $lead) {
  1244. $post_data = array();
  1245. $post_data["post_custom_fields"] = array();
  1246. $post_data["tags_input"] = array();
  1247. $categories = array();
  1248. $images = array();
  1249. foreach($form["fields"] as $field){
  1250. if($field['type'] == 'post_category')
  1251. $field = GFCommon::add_categories_as_choices($field, '');
  1252. $value = self::get_post_field_value($field, $lead);
  1253. switch($field["type"]){
  1254. case "post_title" :
  1255. case "post_excerpt" :
  1256. case "post_content" :
  1257. $post_data[$field["type"]] = $value;
  1258. break;
  1259. case "post_tags" :
  1260. $tags = explode(",", $value);
  1261. if(is_array($tags) && sizeof($tags) > 0)
  1262. $post_data["tags_input"] = array_merge($post_data["tags_input"], $tags) ;
  1263. break;
  1264. case "post_custom_field" :
  1265. $meta_name = $field["postCustomFieldName"];
  1266. if(!isset($post_data["post_custom_fields"][$meta_name])){
  1267. $post_data["post_custom_fields"][$meta_name] = $value;
  1268. }
  1269. else if(!is_array($post_data["post_custom_fields"][$meta_name])){
  1270. $post_data["post_custom_fields"][$meta_name] = array($post_data["post_custom_fields"][$meta_name], $value);
  1271. }
  1272. else{
  1273. $post_data["post_custom_fields"][$meta_name][] = $value;
  1274. }
  1275. break;
  1276. case "post_category" :
  1277. foreach(explode(',', $value) as $cat_string) {
  1278. list($cat_name, $cat_id) = rgexplode(":", $cat_string, 2);
  1279. array_push($categories, $cat_id);
  1280. }
  1281. break;
  1282. case "post_image" :
  1283. $ary = !empty($value) ? explode("|:|", $value) : array();
  1284. $url = count($ary) > 0 ? $ary[0] : "";
  1285. $title = count($ary) > 1 ? $ary[1] : "";
  1286. $caption = count($ary) > 2 ? $ary[2] : "";
  1287. $description = count($ary) > 3 ? $ary[3] : "";
  1288. array_push($images, array("field_id" => $field["id"], "url" => $url, "title" => $title, "description" => $description, "caption" => $caption));
  1289. break;
  1290. }
  1291. }
  1292. $post_data["post_status"] = rgar($form, "postStatus");
  1293. $post_data["post_category"] = !empty($categories) ? $categories : array(rgar($form, 'postCategory'));
  1294. $post_data["images"] = $images;
  1295. //setting current user as author depending on settings
  1296. $post_data["post_author"] = $form["useCurrentUserAsAuthor"] && !empty($lead["created_by"]) ? $lead["created_by"] : $form["postAuthor"];
  1297. return $post_data;
  1298. }
  1299. public static function get_custom_field_names(){
  1300. global $wpdb;
  1301. $keys = $wpdb->get_col( "
  1302. SELECT meta_key
  1303. FROM $wpdb->postmeta
  1304. WHERE meta_key NOT LIKE '\_%'
  1305. GROUP BY meta_key
  1306. ORDER BY meta_id DESC");
  1307. if ( $keys )
  1308. natcasesort($keys);
  1309. return $keys;
  1310. }
  1311. public static function get_input_masks(){
  1312. $masks = array(
  1313. 'US Phone' => '(999) 999-9999',
  1314. 'US Phone + Ext' => '(999) 999-9999? x99999',
  1315. 'Date' => '99/99/9999',
  1316. 'Tax ID' => '99-9999999',
  1317. 'SSN' => '999-99-9999',
  1318. 'Zip Code' => '99999',
  1319. 'Full Zip Code' => '99999?-9999'
  1320. );
  1321. return apply_filters('gform_input_masks', $masks);
  1322. }
  1323. private static function get_default_post_title(){
  1324. global $wpdb;
  1325. $title = "Untitled";
  1326. $count = 1;
  1327. $titles = $wpdb->get_col("SELECT post_title FROM $wpdb->posts WHERE post_title like '%Untitled%'");
  1328. $titles = array_values($titles);
  1329. while(in_array($title, $titles)){
  1330. $title = "Untitled_$count";
  1331. $count++;
  1332. }
  1333. return $title;
  1334. }
  1335. public static function prepare_date($date_format, $value){
  1336. $format = empty($date_format) ? "mdy" : $date_format;
  1337. $date_info = GFCommon::parse_date($value, $format);
  1338. if(!empty($date_info) && !GFCommon::is_empty_array($date_info))
  1339. $value = sprintf("%s-%02d-%02d", $date_info["year"], $date_info["month"], $date_info["day"]);
  1340. else
  1341. $value = "";
  1342. return $value;
  1343. }
  1344. /**
  1345. * Prepare the value before saving it to the lead.
  1346. *
  1347. * @param mixed $form
  1348. * @param mixed $field
  1349. * @param mixed $value
  1350. * @param mixed $input_name
  1351. * @param mixed $lead_id the current lead ID, used for fields that are processed after other fields have been saved (ie Total, Calculations)
  1352. * @param mixed $lead passed by the RGFormsModel::create_lead() method, lead ID is not available for leads created by this function
  1353. */
  1354. public static function prepare_value($form, $field, $value, $input_name, $lead_id, $lead = array()){
  1355. $form_id = $form["id"];
  1356. $input_type = self::get_input_type($field);
  1357. switch($input_type)
  1358. {
  1359. case "total" :
  1360. $lead = empty($lead) ? RGFormsModel::get_lead($lead_id) : $lead;
  1361. $value = GFCommon::get_order_total($form, $lead);
  1362. break;
  1363. case "calculation" :
  1364. // ignore submitted value and recalculate price in backend
  1365. list(,,$input_id) = rgexplode("_", $input_name, 3);
  1366. if($input_id == 2) {
  1367. require_once(GFCommon::get_base_path() . '/currency.php');
  1368. $currency = new RGCurrency(GFCommon::get_currency());
  1369. $lead = empty($lead) ? RGFormsModel::get_lead($lead_id) : $lead;
  1370. $value = $currency->to_money(GFCommon::calculate($field, $form, $lead));
  1371. }
  1372. break;
  1373. case "phone" :
  1374. if($field["phoneFormat"] == "standard" && preg_match('/^\D?(\d{3})\D?\D?(\d{3})\D?(\d{4})$/', $value, $matches))
  1375. $value = sprintf("(%s)%s-%s", $matches[1], $matches[2], $matches[3]);
  1376. break;
  1377. case "time":
  1378. if(!is_array($value) && !empty($value)){
  1379. preg_match('/^(\d*):(\d*) ?(.*)$/', $value, $matches);
  1380. $value = array();
  1381. $value[0] = $matches[1];
  1382. $value[1] = $matches[2];
  1383. $value[2] = rgar($matches,3);
  1384. }
  1385. $hour = empty($value[0]) ? "0" : strip_tags($value[0]);
  1386. $minute = empty($value[1]) ? "0" : strip_tags($value[1]);
  1387. $ampm = strip_tags(rgar($value,2));
  1388. if(!empty($ampm))
  1389. $ampm = " $ampm";
  1390. if(!(empty($hour) && empty($minute)))
  1391. $value = sprintf("%02d:%02d%s", $hour, $minute, $ampm);
  1392. else
  1393. $value = "";
  1394. break;
  1395. case "date" :
  1396. $value = self::prepare_date($field["dateFormat"], $value);
  1397. break;
  1398. case "post_image":
  1399. $url = self::get_fileupload_value($form_id, $input_name);
  1400. $image_title = isset($_POST["{$input_name}_1"]) ? strip_tags($_POST["{$input_name}_1"]) : "";
  1401. $image_caption = isset($_POST["{$input_name}_4"]) ? strip_tags($_POST["{$input_name}_4"]) : "";
  1402. $image_description = isset($_POST["{$input_name}_7"]) ? strip_tags($_POST["{$input_name}_7"]) : "";
  1403. $value = !empty($url) ? $url . "|:|" . $image_title . "|:|" . $image_caption . "|:|" . $image_description : "";
  1404. break;
  1405. case "fileupload" :
  1406. $value = self::get_fileupload_value($form_id, $input_name);
  1407. break;
  1408. case "number" :
  1409. $is_hidden = RGFormsModel::is_field_hidden($form, $field, array());
  1410. $lead = empty($lead) ? RGFormsModel::get_lead($lead_id) : $lead;
  1411. $value = GFCommon::has_field_calculation($field) ? GFCommon::round_number(GFCommon::calculate($field, $form, $lead), rgar($field, "calculationRounding")) : GFCommon::clean_number($value, rgar($field, "numberFormat"));
  1412. //return the value as a string when it is zero and a calc so that the "==" comparison done when checking if the field has changed isn't treated as false
  1413. if (GFCommon::has_field_calculation($field) && $value == 0){
  1414. $value = "0";
  1415. }
  1416. break;
  1417. case "website" :
  1418. if($value == "http://")
  1419. $value = "";
  1420. break;
  1421. case "list" :
  1422. if(GFCommon::is_empty_array($value))
  1423. $value = "";
  1424. else{
  1425. $value = self::create_list_array($field, $value);
  1426. $value = serialize($value);
  1427. }
  1428. break;
  1429. case "radio" :
  1430. if(rgar($field, 'enableOtherChoice') && $value == 'gf_other_choice')
  1431. $value = rgpost("input_{$field['id']}_other");
  1432. break;
  1433. case "multiselect" :
  1434. $value = empty($value) ? "" : implode(",", $value);
  1435. break;
  1436. case "creditcard" :
  1437. //saving last 4 digits of credit card
  1438. list($input_token, $field_id_token, $input_id) = rgexplode("_", $input_name, 3);
  1439. if($input_id == "1"){
  1440. $value = str_replace(" ", "", $value);
  1441. $card_number_length = strlen($value);
  1442. $value = substr($value, -4, 4);
  1443. $value = str_pad($value, $card_number_length, "X", STR_PAD_LEFT);
  1444. }
  1445. else if($input_id == "4")
  1446. {
  1447. $card_number = rgpost("input_{$field_id_token}_1");
  1448. $card_type = GFCommon::get_card_type($card_number);
  1449. $value = $card_type ? $card_type["name"] : "";
  1450. }
  1451. else{
  1452. $value = "";
  1453. }
  1454. break;
  1455. default:
  1456. //allow HTML for certain field types
  1457. $allow_html = in_array($field["type"], array("post_custom_field", "post_title", "post_content", "post_excerpt", "post_tags")) || in_array($input_type, array("checkbox", "radio")) ? true : false;
  1458. $allowable_tags = apply_filters("gform_allowable_tags_{$form_id}", apply_filters("gform_allowable_tags", $allow_html, $field, $form_id), $field, $form_id);
  1459. if($allowable_tags !== true)
  1460. $value = strip_tags($value, $allowable_tags);
  1461. break;
  1462. }
  1463. // special format for Post Category fields
  1464. if($field['type'] == 'post_category') {
  1465. $full_values = array();
  1466. if(!is_array($value))
  1467. $value = explode(',', $value);
  1468. foreach($value as $cat_id) {
  1469. $cat = get_term($cat_id, 'category');
  1470. $full_values[] = !is_wp_error($cat) && is_object($cat) ? $cat->name . ":" . $cat_id : "";
  1471. }
  1472. $value = implode(',', $full_values);
  1473. }
  1474. //do not save price fields with blank price
  1475. if(rgar($field, "enablePrice")){
  1476. $ary = explode("|", $value);
  1477. $label = count($ary) > 0 ? $ary[0] : "";
  1478. $price = count($ary) > 1 ? $ary[1] : "";
  1479. $is_empty = (strlen(trim($price)) <= 0);
  1480. if($is_empty)
  1481. $value = "";
  1482. }
  1483. return $value;
  1484. }
  1485. private static function create_list_array($field, $value){
  1486. if(!rgar($field,"enableColumns")){
  1487. return $value;
  1488. }
  1489. else{
  1490. $col_count = count(rgar($field, "choices"));
  1491. $rows = array();
  1492. $row_count = count($value)/$col_count;
  1493. $col_index = 0;
  1494. for($i=0; $i<$row_count; $i++){
  1495. $row = array();
  1496. foreach($field["choices"] as $column){
  1497. $row[$column["text"]] = $value[$col_index];
  1498. $col_index++;
  1499. }
  1500. $rows[] = $row;
  1501. }
  1502. return $rows;
  1503. }
  1504. }
  1505. private static function get_fileupload_value($form_id, $input_name){
  1506. global $_gf_uploaded_files;
  1507. if(empty($_gf_uploaded_files))
  1508. $_gf_uploaded_files = array();
  1509. if(!isset($_gf_uploaded_files[$input_name])){
  1510. //check if file has already been uploaded by previous step
  1511. $file_info = self::get_temp_filename($form_id, $input_name);
  1512. $temp_filepath = self::get_upload_path($form_id) . "/tmp/" . $file_info["temp_filename"];
  1513. if($file_info && file_exists($temp_filepath)){
  1514. $_gf_uploaded_files[$input_name] = self::move_temp_file($form_id, $file_info);
  1515. }
  1516. else if (!empty($_FILES[$input_name]["name"])){
  1517. $_gf_uploaded_files[$input_name] = self::upload_file($form_id, $_FILES[$input_name]);
  1518. }
  1519. }
  1520. return rgget($input_name, $_gf_uploaded_files);
  1521. }
  1522. public static function get_form_unique_id($form_id) {
  1523. $unique_id = "";
  1524. if (rgpost("gform_submit") == $form_id) {
  1525. $posted_uid = rgpost("gform_unique_id");
  1526. if (false === empty($posted_uid)) {
  1527. $unique_id = $posted_uid;
  1528. self::$unique_ids[$form_id] = $unique_id;
  1529. } elseif (isset(self::$unique_ids[$form_id])) {
  1530. $unique_id = self::$unique_ids[$form_id];
  1531. } else {
  1532. $unique_id = uniqid();
  1533. self::$unique_ids[$form_id] = $unique_id;
  1534. }
  1535. }
  1536. return $unique_id;
  1537. }
  1538. public static function get_temp_filename($form_id, $input_name){
  1539. $uploaded_filename = !empty($_FILES[$input_name]["name"]) ? $_FILES[$input_name]["name"] : "";
  1540. if(empty($uploaded_filename) && isset(self::$uploaded_files[$form_id]))
  1541. $uploaded_filename = rgget($input_name, self::$uploaded_files[$form_id]);
  1542. if(empty($uploaded_filename))
  1543. return false;
  1544. $pathinfo = pathinfo($uploaded_filename);
  1545. return array("uploaded_filename" => $uploaded_filename, "temp_filename" => "{$form_id}_{$input_name}.{$pathinfo["extension"]}");
  1546. }
  1547. public static function get_choice_text($field, $value, $input_id=0){
  1548. if(!is_array(rgar($field, "choices")))
  1549. return $value;
  1550. foreach($field["choices"] as $choice){
  1551. if(is_array($value) && self::choice_value_match($field, $choice, $value[$input_id])){
  1552. return $choice["text"];
  1553. }
  1554. else if(!is_array($value) && self::choice_value_match($field, $choice, $value)){
  1555. return $choice["text"];
  1556. }
  1557. }
  1558. return is_array($value) ? "" : $value;
  1559. }
  1560. public static function choice_value_match($field, $choice, $value){
  1561. if($choice["value"] == $value){
  1562. return true;
  1563. }
  1564. else if(rgget("enablePrice", $field)){
  1565. $ary = explode("|", $value);
  1566. $val = count($ary) > 0 ? $ary[0] : "";
  1567. $price = count($ary) > 1 ? $ary[1] : "";
  1568. if($val == $choice["value"])
  1569. return true;
  1570. }
  1571. // add support for prepopulating multiselects @alex
  1572. else if(RGFormsModel::get_input_type($field) == 'multiselect') {
  1573. $values = explode(',', $value);
  1574. if(in_array($choice['value'], $values))
  1575. return true;
  1576. }
  1577. return false;
  1578. }
  1579. public static function choices_value_match($field, $choices, $value) {
  1580. foreach($choices as $choice){
  1581. if(self::choice_value_match($field, $choice, $value))
  1582. return true;
  1583. }
  1584. return false;
  1585. }
  1586. public static function create_post($form, &$lead){
  1587. $has_post_field = false;
  1588. foreach($form["fields"] as $field){
  1589. $is_hidden = self::is_field_hidden($form, $field, array(), $lead);
  1590. if(!$is_hidden && in_array($field["type"], array("post_category","post_title","post_content","post_excerpt","post_tags","post_custom_field","post_image"))){
  1591. $has_post_field = true;
  1592. break;
  1593. }
  1594. }
  1595. //if this form does not have any post fields, don't create a post
  1596. if(!$has_post_field)
  1597. return $lead;
  1598. //processing post fields
  1599. $post_data = self::get_post_fields($form, $lead);
  1600. //allowing users to change post fields before post gets created
  1601. $post_data = apply_filters("gform_post_data_{$form["id"]}", apply_filters("gform_post_data", $post_data , $form, $lead), $form, $lead);
  1602. //adding default title if none of the required post fields are in the form (will make sure wp_insert_post() inserts the post)
  1603. if(empty($post_data["post_title"]) && empty($post_data["post_content"]) && empty($post_data["post_excerpt"])){
  1604. $post_data["post_title"] = self::get_default_post_title();
  1605. }
  1606. //inserting post
  1607. if (GFCommon::is_bp_active()){
  1608. //disable buddy press action so save_post is not called because the post data is not yet complete at this point
  1609. remove_action("save_post", "bp_blogs_record_post");
  1610. }
  1611. $post_id = wp_insert_post($post_data);
  1612. //adding form id and entry id hidden custom fields
  1613. add_post_meta($post_id, "_gform-form-id", $form["id"]);
  1614. add_post_meta($post_id, "_gform-entry-id", $lead["id"]);
  1615. //creating post images
  1616. $post_images = array();
  1617. foreach($post_data["images"] as $image){
  1618. $image_meta= array( "post_excerpt" => $image["caption"],
  1619. "post_content" => $image["description"]);
  1620. //adding title only if it is not empty. It will default to the file name if it is not in the array
  1621. if(!empty($image["title"]))
  1622. $image_meta["post_title"] = $image["title"];
  1623. if(!empty($image["url"])){
  1624. $media_id = self::media_handle_upload($image["url"], $post_id, $image_meta);
  1625. if($media_id){
  1626. //save media id for post body/title template variable replacement (below)
  1627. $post_images[$image["field_id"]] = $media_id;
  1628. $lead[$image["field_id"]] .= "|:|$media_id";
  1629. // set featured image
  1630. $field = RGFormsModel::get_field($form, $image["field_id"]);
  1631. if(rgar($field, 'postFeaturedImage'))
  1632. set_post_thumbnail($post_id, $media_id);
  1633. }
  1634. }
  1635. }
  1636. //adding custom fields
  1637. foreach($post_data["post_custom_fields"] as $meta_name => $meta_value) {
  1638. if(!is_array($meta_value))
  1639. $meta_value = array($meta_value);
  1640. $meta_index = 0;
  1641. foreach($meta_value as $value){
  1642. $custom_field = self::get_custom_field($form, $meta_name, $meta_index);
  1643. //replacing template variables if template is enabled
  1644. if($custom_field && rgget("customFieldTemplateEnabled", $custom_field)){
  1645. //replacing post image variables
  1646. $value = GFCommon::replace_variables_post_image($custom_field["customFieldTemplate"], $post_images, $lead);
  1647. //replacing all other variables
  1648. $value = GFCommon::replace_variables($value, $form, $lead, false, false, false);
  1649. // replace conditional shortcodes
  1650. $value = do_shortcode($value);
  1651. }
  1652. switch(RGFormsModel::get_input_type($custom_field)){
  1653. case "list" :
  1654. $value = maybe_unserialize($value);
  1655. if(is_array($value)){
  1656. foreach($value as $item){
  1657. if(is_array($item))
  1658. $item = implode("|", $item);
  1659. if(!rgblank($item))
  1660. add_post_meta($post_id, $meta_name, $item);
  1661. }
  1662. }
  1663. break;
  1664. case "multiselect" :
  1665. case "checkbox" :
  1666. $value = explode(",", $value);
  1667. if(is_array($value)){
  1668. foreach($value as $item){
  1669. if(!rgblank($item)) {
  1670. // add post meta and replace HTML symbol in $item with real comma
  1671. add_post_meta($post_id, $meta_name, str_replace('&#44;', ',', $item));
  1672. }
  1673. }
  1674. }
  1675. break;
  1676. case "date" :
  1677. $value = GFCommon::date_display($value, rgar($custom_field, "dateFormat"));
  1678. if(!rgblank($value))
  1679. add_post_meta($post_id, $meta_name, $value);
  1680. break;
  1681. default :
  1682. if(!rgblank($value))
  1683. add_post_meta($post_id, $meta_name, $value);
  1684. break;
  1685. }
  1686. $meta_index++;
  1687. }
  1688. }
  1689. $has_content_field = sizeof(GFCommon::get_fields_by_type($form, array("post_content"))) > 0;
  1690. $has_title_field = sizeof(GFCommon::get_fields_by_type($form, array("post_title"))) > 0;
  1691. //if a post field was configured with a content or title template, process template
  1692. if( (rgar($form, "postContentTemplateEnabled") && $has_content_field) || (rgar($form, "postTitleTemplateEnabled") && $has_title_field) ){
  1693. $post = get_post($post_id);
  1694. if($form["postContentTemplateEnabled"] && $has_content_field){
  1695. //replacing post image variables
  1696. $post_content = GFCommon::replace_variables_post_image($form["postContentTemplate"], $post_images, $lead);
  1697. //replacing all other variables
  1698. $post_content = GFCommon::replace_variables($post_content, $form, $lead, false, false, false);
  1699. //updating post content
  1700. $post->post_content = $post_content;
  1701. }
  1702. if($form["postTitleTemplateEnabled"] && $has_title_field){
  1703. //replacing post image variables
  1704. $post_title = GFCommon::replace_variables_post_image($form["postTitleTemplate"], $post_images, $lead);
  1705. //replacing all other variables
  1706. $post_title = GFCommon::replace_variables($post_title, $form, $lead, false, false, false);
  1707. // replace conditional shortcodes
  1708. $post_title = do_shortcode($post_title);
  1709. //updating post
  1710. $post->post_title = $post_title;
  1711. $post->post_name = $post_title;
  1712. }
  1713. if (GFCommon::is_bp_active()){
  1714. //re-enable buddy press action for save_post since the post data is complete at this point
  1715. add_action( 'save_post', 'bp_blogs_record_post', 10, 2 );
  1716. }
  1717. wp_update_post($post);
  1718. }
  1719. //adding post format
  1720. if(current_theme_supports('post-formats') && rgar($form, 'postFormat')) {
  1721. $formats = get_theme_support('post-formats');
  1722. $post_format = rgar($form, 'postFormat');
  1723. if(is_array($formats)) {
  1724. $formats = $formats[0];
  1725. if(in_array( $post_format, $formats)) {
  1726. set_post_format($post_id, $post_format);
  1727. } else if('0' == $post_format) {
  1728. set_post_format($post_id, false);
  1729. }
  1730. }
  1731. }
  1732. //update post_id field if a post was created
  1733. $lead["post_id"] = $post_id;
  1734. self::update_lead($lead);
  1735. return $post_id;
  1736. }
  1737. private static function get_custom_field($form, $meta_name, $meta_index){
  1738. $custom_fields = GFCommon::get_fields_by_type($form, array("post_custom_field"));
  1739. $index = 0;
  1740. foreach($custom_fields as $field){
  1741. if($field["postCustomFieldName"] == $meta_name){
  1742. if($meta_index == $index){
  1743. return $field;
  1744. }
  1745. $index++;
  1746. }
  1747. }
  1748. return false;
  1749. }
  1750. private static function copy_post_image($url, $post_id){
  1751. $time = current_time('mysql');
  1752. if ( $post = get_post($post_id) ) {
  1753. if ( substr( $post->post_date, 0, 4 ) > 0 )
  1754. $time = $post->post_date;
  1755. }
  1756. //making sure there is a valid upload folder
  1757. if ( ! ( ( $uploads = wp_upload_dir($time) ) && false === $uploads['error'] ) )
  1758. return false;
  1759. $name = basename($url);
  1760. $filename = wp_unique_filename($uploads['path'], $name);
  1761. // Move the file to the uploads dir
  1762. $new_file = $uploads['path'] . "/$filename";
  1763. $uploaddir = wp_upload_dir();
  1764. $path = str_replace($uploaddir["baseurl"], $uploaddir["basedir"], $url);
  1765. if(!copy($path, $new_file))
  1766. return false;
  1767. // Set correct file permissions
  1768. $stat = stat( dirname( $new_file ));
  1769. $perms = $stat['mode'] & 0000666;
  1770. @ chmod( $new_file, $perms );
  1771. // Compute the URL
  1772. $url = $uploads['url'] . "/$filename";
  1773. if ( is_multisite() )
  1774. delete_transient( 'dirsize_cache' );
  1775. $type = wp_check_filetype($new_file);
  1776. return array("file" => $new_file, "url" => $url, "type" => $type["type"]);
  1777. }
  1778. private static function media_handle_upload($url, $post_id, $post_data = array()) {
  1779. //WordPress Administration API required for the media_handle_upload() function
  1780. require_once(ABSPATH . 'wp-admin/includes/image.php');
  1781. $name = basename($url);
  1782. $file = self::copy_post_image($url, $post_id);
  1783. if(!$file)
  1784. return false;
  1785. $name_parts = pathinfo($name);
  1786. $name = trim( substr( $name, 0, -(1 + strlen($name_parts['extension'])) ) );
  1787. $url = $file['url'];
  1788. $type = $file['type'];
  1789. $file = $file['file'];
  1790. $title = $name;
  1791. $content = '';
  1792. // use image exif/iptc data for title and caption defaults if possible
  1793. if ( $image_meta = @wp_read_image_metadata($file) ) {
  1794. if ( trim( $image_meta['title'] ) && ! is_numeric( sanitize_title( $image_meta['title'] ) ) )
  1795. $title = $image_meta['title'];
  1796. if ( trim( $image_meta['caption'] ) )
  1797. $content = $image_meta['caption'];
  1798. }
  1799. // Construct the attachment array
  1800. $attachment = array_merge( array(
  1801. 'post_mime_type' => $type,
  1802. 'guid' => $url,
  1803. 'post_parent' => $post_id,
  1804. 'post_title' => $title,
  1805. 'post_content' => $content,
  1806. ), $post_data );
  1807. // Save the data
  1808. $id = wp_insert_attachment($attachment, $file, $post_id);
  1809. if ( !is_wp_error($id) ) {
  1810. wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $file ) );
  1811. }
  1812. return $id;
  1813. }
  1814. public static function save_input($form, $field, &$lead, $current_fields, $input_id){
  1815. global $wpdb;
  1816. $lead_detail_table = self::get_lead_details_table_name();
  1817. $lead_detail_long_table = self::get_lead_details_long_table_name();
  1818. $input_name = "input_" . str_replace('.', '_', $input_id);
  1819. $value = rgpost($input_name);
  1820. //ignore file upload when nothing was sent in the admin
  1821. //ignore post fields in the admin
  1822. if(RG_CURRENT_VIEW == "entry" && self::get_input_type($field) == "fileupload" && empty($_FILES[$input_name]["name"]))
  1823. return;
  1824. else if(RG_CURRENT_VIEW == "entry" && in_array($field["type"], array("post_category","post_title","post_content","post_excerpt","post_tags","post_custom_field","post_image")))
  1825. return;
  1826. if(empty($value) && rgar($field, "adminOnly") && !IS_ADMIN){
  1827. $value = self::get_default_value($field, $input_id);
  1828. }
  1829. //processing values so that they are in the correct format for each input type
  1830. $value = self::prepare_value($form, $field, $value, $input_name, rgar($lead, "id"));
  1831. //ignore fields that have not changed
  1832. if($lead != null && $value == rgget($input_id, $lead)){
  1833. return;
  1834. }
  1835. if(!empty($value) || $value === "0"){
  1836. $value = apply_filters("gform_save_field_value", $value, $lead, $field, $form);
  1837. $truncated_value = substr($value, 0, GFORMS_MAX_FIELD_LENGTH);
  1838. $lead_detail_id = self::get_lead_detail_id($current_fields, $input_id);
  1839. if($lead_detail_id > 0){
  1840. $wpdb->update($lead_detail_table, array("value" => $truncated_value), array("id" => $lead_detail_id), array("%s"), array("%d"));
  1841. //insert, update or delete long value
  1842. $sql = $wpdb->prepare("SELECT count(0) FROM $lead_detail_long_table WHERE lead_detail_id=%d", $lead_detail_id);
  1843. $has_long_field = intval($wpdb->get_var($sql)) > 0;
  1844. //delete long field if value has been shortened
  1845. if($has_long_field && strlen($value) <= GFORMS_MAX_FIELD_LENGTH){
  1846. $sql = $wpdb->prepare("DELETE FROM $lead_detail_long_table WHERE lead_detail_id=%d", $lead_detail_id);
  1847. $wpdb->query($sql);
  1848. }
  1849. //update long field
  1850. else if($has_long_field){
  1851. $wpdb->update($lead_detail_long_table, array("value" => $value), array("lead_detail_id" => $lead_detail_id), array("%s"), array("%d"));
  1852. }
  1853. //insert long field (value has been increased)
  1854. else if(strlen($value) > GFORMS_MAX_FIELD_LENGTH){
  1855. $wpdb->insert($lead_detail_long_table, array("lead_detail_id" => $lead_detail_id, "value" => $value), array("%d", "%s"));
  1856. }
  1857. }
  1858. else{
  1859. $wpdb->insert($lead_detail_table, array("lead_id" => $lead["id"], "form_id" => $form["id"], "field_number" => $input_id, "value" => $truncated_value), array("%d", "%d", "%F", "%s"));
  1860. if(strlen($value) > GFORMS_MAX_FIELD_LENGTH){
  1861. //read newly created lead detal id
  1862. $lead_detail_id = $wpdb->insert_id;
  1863. //insert long value
  1864. $wpdb->insert($lead_detail_long_table, array("lead_detail_id" => $lead_detail_id, "value" => $value), array("%d", "%s"));
  1865. }
  1866. }
  1867. }
  1868. else{
  1869. //Deleting details for this field
  1870. $sql = $wpdb->prepare("DELETE FROM $lead_detail_table WHERE lead_id=%d AND field_number BETWEEN %s AND %s ", $lead["id"], doubleval($input_id) - 0.001, doubleval($input_id) + 0.001);
  1871. $wpdb->query($sql);
  1872. //Deleting long field if there is one
  1873. $sql = $wpdb->prepare("DELETE FROM $lead_detail_long_table
  1874. WHERE lead_detail_id IN(
  1875. SELECT id FROM $lead_detail_table WHERE lead_id=%d AND field_number BETWEEN %s AND %s
  1876. )",
  1877. $lead["id"], doubleval($input_id) - 0.001, doubleval($input_id) + 0.001);
  1878. $wpdb->query($sql);
  1879. }
  1880. }
  1881. private static function move_temp_file($form_id, $tempfile_info){
  1882. $target = self::get_file_upload_path($form_id, $tempfile_info["uploaded_filename"]);
  1883. $source = self::get_upload_path($form_id) . "/tmp/" . $tempfile_info["temp_filename"];
  1884. if(rename($source, $target["path"])){
  1885. self::set_permissions($target["path"]);
  1886. return $target["url"];
  1887. }
  1888. else{
  1889. return "FAILED (Temporary file could not be moved.)";
  1890. }
  1891. }
  1892. private static function set_permissions($path){
  1893. $permission = apply_filters("gform_file_permission", 0644, $path);
  1894. if($permission){
  1895. chmod($path, $permission);
  1896. }
  1897. }
  1898. public static function upload_file($form_id, $file){
  1899. $target = self::get_file_upload_path($form_id, $file["name"]);
  1900. if(!$target)
  1901. return "FAILED (Upload folder could not be created.)";
  1902. if(move_uploaded_file($file['tmp_name'], $target["path"])){
  1903. self::set_permissions($target["path"]);
  1904. return $target["url"];
  1905. }
  1906. else{
  1907. return "FAILED (Temporary file could not be copied.)";
  1908. }
  1909. }
  1910. public static function get_upload_root(){
  1911. $dir = wp_upload_dir();
  1912. if($dir["error"])
  1913. return null;
  1914. return $dir["basedir"] . "/gravity_forms/";
  1915. }
  1916. public static function get_upload_url_root(){
  1917. $dir = wp_upload_dir();
  1918. if($dir["error"])
  1919. return null;
  1920. return $dir["baseurl"] . "/gravity_forms/";
  1921. }
  1922. public static function get_upload_path($form_id){
  1923. return self::get_upload_root() . $form_id . "-" . wp_hash($form_id);
  1924. }
  1925. public static function get_upload_url($form_id){
  1926. $dir = wp_upload_dir();
  1927. return $dir["baseurl"] . "/gravity_forms/$form_id" . "-" . wp_hash($form_id);
  1928. }
  1929. public static function get_file_upload_path($form_id, $file_name){
  1930. if (get_magic_quotes_gpc())
  1931. $file_name = stripslashes($file_name);
  1932. // Where the file is going to be placed
  1933. // Generate the yearly and monthly dirs
  1934. $time = current_time( 'mysql' );
  1935. $y = substr( $time, 0, 4 );
  1936. $m = substr( $time, 5, 2 );
  1937. $target_root = self::get_upload_path($form_id) . "/$y/$m/";
  1938. $target_root_url = self::get_upload_url($form_id) . "/$y/$m/";
  1939. //adding filter to upload root path and url
  1940. $upload_root_info = array("path" => $target_root, "url" => $target_root_url);
  1941. $upload_root_info = apply_filters("gform_upload_path_{$form_id}", apply_filters("gform_upload_path", $upload_root_info, $form_id), $form_id);
  1942. $target_root = $upload_root_info["path"];
  1943. $target_root_url = $upload_root_info["url"];
  1944. if(!is_dir($target_root)){
  1945. if(!wp_mkdir_p($target_root))
  1946. return false;
  1947. //adding index.html files to all subfolders
  1948. if(!file_exists(self::get_upload_root() . "/index.html")){
  1949. GFCommon::recursive_add_index_file(self::get_upload_root());
  1950. }
  1951. else if(!file_exists(self::get_upload_path($form_id) . "/index.html")){
  1952. GFCommon::recursive_add_index_file(self::get_upload_path($form_id));
  1953. }
  1954. else if(!file_exists(self::get_upload_path($form_id) . "/$y/index.html")){
  1955. GFCommon::recursive_add_index_file(self::get_upload_path($form_id) . "/$y");
  1956. }
  1957. else{
  1958. GFCommon::recursive_add_index_file(self::get_upload_path($form_id) . "/$y/$m");
  1959. }
  1960. }
  1961. //Add the original filename to our target path.
  1962. //Result is "uploads/filename.extension"
  1963. $file_info = pathinfo($file_name);
  1964. $extension = rgar($file_info, 'extension');
  1965. $file_name = basename($file_info["basename"], "." . $extension);
  1966. $file_name = sanitize_file_name($file_name);
  1967. $counter = 1;
  1968. $target_path = $target_root . $file_name . "." . $extension;
  1969. while(file_exists($target_path)){
  1970. $target_path = $target_root . $file_name . "$counter" . "." . $extension;
  1971. $counter++;
  1972. }
  1973. //creating url
  1974. $target_url = str_replace($target_root, $target_root_url, $target_path);
  1975. return array("path" => $target_path, "url" => $target_url);
  1976. }
  1977. public static function get_tables() {
  1978. return array(
  1979. self::get_lead_details_long_table_name(),
  1980. self::get_lead_notes_table_name(),
  1981. self::get_lead_details_table_name(),
  1982. self::get_lead_table_name(),
  1983. self::get_form_view_table_name(),
  1984. self::get_meta_table_name(),
  1985. self::get_form_table_name(),
  1986. self::get_lead_meta_table_name()
  1987. );
  1988. }
  1989. public static function drop_tables(){
  1990. global $wpdb;
  1991. foreach(self::get_tables() as $table) {
  1992. $wpdb->query("DROP TABLE IF EXISTS $table");
  1993. }
  1994. }
  1995. public static function mu_drop_tables($drop_tables) {
  1996. return array_merge($drop_tables, self::get_tables());
  1997. }
  1998. public static function insert_form_view($form_id, $ip){
  1999. global $wpdb;
  2000. $table_name = self::get_form_view_table_name();
  2001. $sql = $wpdb->prepare(" SELECT id FROM $table_name
  2002. WHERE form_id=%d
  2003. AND year(date_created) = year(utc_timestamp())
  2004. AND month(date_created) = month(utc_timestamp())
  2005. AND day(date_created) = day(utc_timestamp())
  2006. AND hour(date_created) = hour(utc_timestamp())", $form_id);
  2007. $id = $wpdb->get_var($sql, 0, 0);
  2008. if(empty($id))
  2009. $wpdb->query($wpdb->prepare("INSERT INTO $table_name(form_id, date_created, ip) values(%d, utc_timestamp(), %s)", $form_id, $ip));
  2010. else
  2011. $wpdb->query($wpdb->prepare("UPDATE $table_name SET count = count+1 WHERE id=%d", $id));
  2012. }
  2013. public static function is_duplicate($form_id, $field, $value){
  2014. global $wpdb;
  2015. $lead_detail_table_name = self::get_lead_details_table_name();
  2016. $lead_table_name = self::get_lead_table_name();
  2017. $sql_comparison = "ld.value=%s";
  2018. switch(RGFormsModel::get_input_type($field)){
  2019. case "time" :
  2020. $value = sprintf("%02d:%02d %s", $value[0], $value[1], $value[2]);
  2021. break;
  2022. case "date" :
  2023. $value = self::prepare_date(rgar($field, "dateFormat"), $value);
  2024. break;
  2025. case "number" :
  2026. $value = GFCommon::clean_number($value, rgar($field, 'numberFormat'));
  2027. break;
  2028. case "phone" :
  2029. $value = str_replace(array(")", "(", "-", " "), array("", "", "", ""), $value);
  2030. $sql_comparison = 'replace(replace(replace(replace(ld.value, ")", ""), "(", ""), "-", ""), " ", "") = %s';
  2031. break;
  2032. }
  2033. $inner_sql_template = " SELECT %s as input, ld.lead_id
  2034. FROM $lead_detail_table_name ld
  2035. INNER JOIN $lead_table_name l ON l.id = ld.lead_id
  2036. WHERE l.form_id=%d AND ld.form_id=%d
  2037. AND ld.field_number between %s AND %s
  2038. AND status='active' AND {$sql_comparison}";
  2039. $sql = "SELECT count(distinct input) as match_count FROM ( ";
  2040. $input_count = 1;
  2041. if(is_array($field["inputs"])){
  2042. $input_count = sizeof($field["inputs"]);
  2043. foreach($field["inputs"] as $input){
  2044. $union = empty($inner_sql) ? "" : " UNION ALL ";
  2045. $inner_sql .= $union . $wpdb->prepare($inner_sql_template, $input["id"], $form_id, $form_id, $input["id"] - 0.001, $input["id"] + 0.001, $value[$input["id"]]);
  2046. }
  2047. }
  2048. else{
  2049. $inner_sql = $wpdb->prepare($inner_sql_template, $field["id"], $form_id, $form_id, doubleval($field["id"]) - 0.001, doubleval($field["id"]) + 0.001, $value);
  2050. }
  2051. $sql .= $inner_sql . "
  2052. ) as count
  2053. GROUP BY lead_id
  2054. ORDER BY match_count DESC";
  2055. $count = apply_filters("gform_is_duplicate_{$form_id}", apply_filters('gform_is_duplicate', $wpdb->get_var($sql), $form_id, $field, $value), $form_id, $field, $value);
  2056. return $count != null && $count >= $input_count;
  2057. }
  2058. public static function get_lead($lead_id){
  2059. global $wpdb;
  2060. $lead_detail_table_name = self::get_lead_details_table_name();
  2061. $lead_table_name = self::get_lead_table_name();
  2062. $results = $wpdb->get_results($wpdb->prepare(" SELECT l.*, field_number, value
  2063. FROM $lead_table_name l
  2064. INNER JOIN $lead_detail_table_name ld ON l.id = ld.lead_id
  2065. WHERE l.id=%d", $lead_id));
  2066. $leads = self::build_lead_array($results, true);
  2067. return sizeof($leads) == 1 ? $leads[0] : false;
  2068. }
  2069. public static function get_lead_notes($lead_id){
  2070. global $wpdb;
  2071. $notes_table = self::get_lead_notes_table_name();
  2072. return $wpdb->get_results($wpdb->prepare(" SELECT n.id, n.user_id, n.date_created, n.value, ifnull(u.display_name,n.user_name) as user_name, u.user_email
  2073. FROM $notes_table n
  2074. LEFT OUTER JOIN $wpdb->users u ON n.user_id = u.id
  2075. WHERE lead_id=%d ORDER BY id", $lead_id));
  2076. }
  2077. public static function get_lead_field_value($lead, $field){
  2078. if(empty($lead))
  2079. return;
  2080. //returning cache entry if available
  2081. $cache_key = "GFFormsModel::get_lead_field_value_" . $lead["id"] . "_" . $field["id"];
  2082. $cache_value = GFCache::get($cache_key);
  2083. if($cache_value !== false)
  2084. return $cache_value;
  2085. $max_length = GFORMS_MAX_FIELD_LENGTH;
  2086. $value = array();
  2087. if(is_array(rgar($field, "inputs"))){
  2088. //making sure values submitted are sent in the value even if
  2089. //there isn't an input associated with it
  2090. $lead_field_keys = array_keys($lead);
  2091. foreach($lead_field_keys as $input_id){
  2092. if(is_numeric($input_id) && absint($input_id) == absint($field["id"])){
  2093. $val = $lead[$input_id];
  2094. if(strlen($val) >= ($max_length-10)) {
  2095. if(empty($form))
  2096. $form = RGFormsModel::get_form_meta($lead["form_id"]);
  2097. $long_choice = self::get_field_value_long($lead, $input_id, $form);
  2098. }
  2099. else{
  2100. $long_choice = $val;
  2101. }
  2102. $value[$input_id] = !empty($long_choice) ? $long_choice : $val;
  2103. }
  2104. }
  2105. }
  2106. else{
  2107. $val = rgget($field["id"], $lead);
  2108. //To save a database call to get long text, only getting long text if regular field is "somewhat" large (i.e. max - 50)
  2109. if(strlen($val) >= ($max_length - 50)){
  2110. if(empty($form))
  2111. $form = RGFormsModel::get_form_meta($lead["form_id"]);
  2112. $long_text = self::get_field_value_long($lead, $field["id"], $form);
  2113. }
  2114. $value = !empty($long_text) ? $long_text : $val;
  2115. }
  2116. //filtering lead value
  2117. $value = apply_filters("gform_get_field_value", $value, $lead, $field);
  2118. //saving value in global variable to optimize performance
  2119. GFCache::set($cache_key, $value);
  2120. return $value;
  2121. }
  2122. public static function get_field_value_long($lead, $field_number, $form, $apply_filter=true){
  2123. global $wpdb;
  2124. $detail_table_name = self::get_lead_details_table_name();
  2125. $long_table_name = self::get_lead_details_long_table_name();
  2126. $sql = $wpdb->prepare(" SELECT l.value FROM $detail_table_name d
  2127. INNER JOIN $long_table_name l ON l.lead_detail_id = d.id
  2128. WHERE lead_id=%d AND field_number BETWEEN %s AND %s", $lead["id"], doubleval($field_number) - 0.001, doubleval($field_number) + 0.001);
  2129. $val = $wpdb->get_var($sql);
  2130. //running aform_get_input_value when needed
  2131. if($apply_filter){
  2132. $field = RGFormsModel::get_field($form, $field_number);
  2133. $input_id = (string)$field_number == (string)$field["id"] ? "" : $field_number;
  2134. $val = apply_filters("gform_get_input_value", $val, $lead, $field, $input_id);
  2135. }
  2136. return $val;
  2137. }
  2138. public static function get_leads_by_meta($meta_key, $meta_value){
  2139. global $wpdb;
  2140. $sql = $wpdb->prepare( " SELECT l.*, d.field_number, d.value
  2141. FROM {$wpdb->prefix}rg_lead l
  2142. INNER JOIN {$wpdb->prefix}rg_lead_detail d ON l.id = d.lead_id
  2143. INNER JOIN {$wpdb->prefix}rg_lead_meta m ON l.id = m.lead_id
  2144. WHERE m.meta_key=%s AND m.meta_value=%s", $meta_key, $meta_value);
  2145. //getting results
  2146. $results = $wpdb->get_results($sql);
  2147. $leads = self::build_lead_array($results);
  2148. return $leads;
  2149. }
  2150. public static function get_leads($form_id, $sort_field_number=0, $sort_direction='DESC', $search='', $offset=0, $page_size=30, $star=null, $read=null, $is_numeric_sort = false, $start_date=null, $end_date=null, $status='active', $payment_status = false){
  2151. global $wpdb;
  2152. if(empty($sort_field_number))
  2153. $sort_field_number = "date_created";
  2154. if(is_numeric($sort_field_number)) {
  2155. $sql = self::sort_by_custom_field_query($form_id, $sort_field_number, $sort_direction, $search, $offset, $page_size, $star, $read, $is_numeric_sort, $status, $payment_status);
  2156. } else {
  2157. $sql = self::sort_by_default_field_query($form_id, $sort_field_number, $sort_direction, $search, $offset, $page_size, $star, $read, $is_numeric_sort, $start_date, $end_date, $status, $payment_status);
  2158. }
  2159. //initializing rownum
  2160. $wpdb->query("select @rownum:=0");
  2161. GFCommon::log_debug($sql);
  2162. //getting results
  2163. $results = $wpdb->get_results($sql);
  2164. $leads = self::build_lead_array($results);
  2165. return $leads;
  2166. }
  2167. public static function get_leads_count($form_id) { }
  2168. private static function sort_by_custom_field_query($form_id, $sort_field_number=0, $sort_direction='DESC', $search='', $offset=0, $page_size=30, $star=null, $read=null, $is_numeric_sort = false, $status='active', $payment_status = false){
  2169. global $wpdb;
  2170. if(!is_numeric($form_id) || !is_numeric($sort_field_number)|| !is_numeric($offset)|| !is_numeric($page_size))
  2171. return "";
  2172. $lead_detail_table_name = self::get_lead_details_table_name();
  2173. $lead_table_name = self::get_lead_table_name();
  2174. $orderby = $is_numeric_sort ? "ORDER BY query, (value+0) $sort_direction" : "ORDER BY query, value $sort_direction";
  2175. $is_default = false;
  2176. $search_sql = self::get_leads_where_sql(compact('form_id', 'search', 'status', 'star', 'read', 'start_date', 'end_date', 'payment_status', 'is_default'));
  2177. $field_number_min = $sort_field_number - 0.001;
  2178. $field_number_max = $sort_field_number + 0.001;
  2179. $sql = "
  2180. SELECT filtered.sort, l.*, d.field_number, d.value
  2181. FROM $lead_table_name l
  2182. INNER JOIN $lead_detail_table_name d ON d.lead_id = l.id
  2183. INNER JOIN (
  2184. SELECT distinct sorted.sort, l.id
  2185. FROM $lead_table_name l
  2186. INNER JOIN $lead_detail_table_name d ON d.lead_id = l.id
  2187. INNER JOIN (
  2188. SELECT @rownum:=@rownum+1 as sort, id FROM (
  2189. SELECT 0 as query, lead_id as id, value
  2190. FROM $lead_detail_table_name
  2191. WHERE form_id=$form_id
  2192. AND field_number between $field_number_min AND $field_number_max
  2193. UNION ALL
  2194. SELECT 1 as query, l.id, d.value
  2195. FROM $lead_table_name l
  2196. LEFT OUTER JOIN $lead_detail_table_name d ON d.lead_id = l.id AND field_number between $field_number_min AND $field_number_max
  2197. WHERE l.form_id=$form_id
  2198. AND d.lead_id IS NULL
  2199. ) sorted1
  2200. $orderby
  2201. ) sorted ON d.lead_id = sorted.id
  2202. $search_sql
  2203. LIMIT $offset,$page_size
  2204. ) filtered ON filtered.id = l.id
  2205. ORDER BY filtered.sort";
  2206. return $sql;
  2207. }
  2208. private static function sort_by_default_field_query($form_id, $sort_field, $sort_direction='DESC', $search='', $offset=0, $page_size=30, $star=null, $read=null, $is_numeric_sort = false, $start_date=null, $end_date=null, $status='active', $payment_status = false){
  2209. global $wpdb;
  2210. if(!is_numeric($form_id) || !is_numeric($offset)|| !is_numeric($page_size)){
  2211. return "";
  2212. }
  2213. $lead_detail_table_name = self::get_lead_details_table_name();
  2214. $lead_table_name = self::get_lead_table_name();
  2215. $lead_meta_table_name = self::get_lead_meta_table_name();
  2216. $where = self::get_leads_where_sql(compact('form_id', 'search', 'status', 'star', 'read', 'start_date', 'end_date', 'payment_status'));
  2217. $entry_meta = self::get_entry_meta($form_id);
  2218. $entry_meta_sql_join = "";
  2219. if ( false === empty( $entry_meta ) && array_key_exists( $sort_field, $entry_meta ) ) {
  2220. $entry_meta_sql_join = $wpdb->prepare("INNER JOIN
  2221. (
  2222. SELECT
  2223. lead_id, meta_value as $sort_field
  2224. from $lead_meta_table_name
  2225. WHERE meta_key = '$sort_field'
  2226. ) lead_meta_data ON lead_meta_data.lead_id = l.id
  2227. ");
  2228. $is_numeric_sort = $entry_meta[$sort_field]['is_numeric'];
  2229. }
  2230. $grid_columns = RGFormsModel::get_grid_columns($form_id);
  2231. if ( $sort_field != "date_created" && false === array_key_exists($sort_field, $grid_columns) )
  2232. $sort_field = "date_created";
  2233. $orderby = $is_numeric_sort ? "ORDER BY ($sort_field+0) $sort_direction" : "ORDER BY $sort_field $sort_direction";
  2234. $sql = "
  2235. SELECT filtered.sort, l.*, d.field_number, d.value
  2236. FROM $lead_table_name l
  2237. INNER JOIN $lead_detail_table_name d ON d.lead_id = l.id
  2238. INNER JOIN
  2239. (
  2240. SELECT @rownum:=@rownum + 1 as sort, id
  2241. FROM
  2242. (
  2243. SELECT distinct l.id
  2244. FROM $lead_table_name l
  2245. INNER JOIN $lead_detail_table_name d ON d.lead_id = l.id
  2246. $entry_meta_sql_join
  2247. $where
  2248. $orderby
  2249. LIMIT $offset,$page_size
  2250. ) page
  2251. ) filtered ON filtered.id = l.id
  2252. ORDER BY filtered.sort";
  2253. return $sql;
  2254. }
  2255. public static function get_leads_where_sql($args) {
  2256. global $wpdb;
  2257. extract(wp_parse_args($args, array(
  2258. 'form_id' => false,
  2259. 'search' => '',
  2260. 'status' => 'active',
  2261. 'star' => null,
  2262. 'read' => null,
  2263. 'start_date' => null,
  2264. 'end_date' => null,
  2265. 'payment_status' => null,
  2266. 'is_default' => true
  2267. )));
  2268. $where = array();
  2269. if($is_default)
  2270. $where[] = "l.form_id = $form_id";
  2271. if($search && $is_default) {
  2272. $where[] = $wpdb->prepare("value LIKE %s", "%$search%");
  2273. } else if($search) {
  2274. $where[] = $wpdb->prepare("d.value LIKE %s", "%$search%");
  2275. }
  2276. if($star !== null && $status == 'active')
  2277. $where[] = $wpdb->prepare("is_starred = %d AND status = 'active'", $star);
  2278. if($read !== null && $status == 'active')
  2279. $where[] = $wpdb->prepare("is_read = %d AND status = 'active'", $read);
  2280. if($payment_status)
  2281. $where[] = $wpdb->prepare("payment_status = '%s'", $payment_status);
  2282. if ($status !== null)
  2283. $where[] = $wpdb->prepare("status = %s", $status);
  2284. if(!empty($start_date))
  2285. $where[] = "timestampdiff(SECOND, '$start_date', date_created) >= 0";
  2286. if(!empty($end_date))
  2287. $where[] = "timestampdiff(SECOND, '$end_date', date_created) <= 0";
  2288. return 'WHERE ' . implode(' AND ', $where);
  2289. }
  2290. public static function build_lead_array($results, $use_long_values = false){
  2291. $leads = array();
  2292. $lead = array();
  2293. $form_id = 0;
  2294. if(is_array($results) && sizeof($results) > 0){
  2295. $form_id = $results[0]->form_id;
  2296. $lead = array("id" => $results[0]->id, "form_id" => $results[0]->form_id, "date_created" => $results[0]->date_created, "is_starred" => intval($results[0]->is_starred), "is_read" => intval($results[0]->is_read), "ip" => $results[0]->ip, "source_url" => $results[0]->source_url, "post_id" => $results[0]->post_id, "currency" => $results[0]->currency, "payment_status" => $results[0]->payment_status, "payment_date" => $results[0]->payment_date, "transaction_id" => $results[0]->transaction_id, "payment_amount" => $results[0]->payment_amount, "is_fulfilled" => $results[0]->is_fulfilled, "created_by" => $results[0]->created_by, "transaction_type" => $results[0]->transaction_type, "user_agent" => $results[0]->user_agent, "status" => $results[0]->status);
  2297. $form = RGFormsModel::get_form_meta($form_id);
  2298. $prev_lead_id=0;
  2299. foreach($results as $result){
  2300. if($prev_lead_id <> $result->id && $prev_lead_id > 0){
  2301. array_push($leads, $lead);
  2302. $lead = array("id" => $result->id, "form_id" => $result->form_id, "date_created" => $result->date_created, "is_starred" => intval($result->is_starred), "is_read" => intval($result->is_read), "ip" => $result->ip, "source_url" => $result->source_url, "post_id" => $result->post_id, "currency" => $result->currency, "payment_status" => $result->payment_status, "payment_date" => $result->payment_date, "transaction_id" => $result->transaction_id, "payment_amount" => $result->payment_amount, "is_fulfilled" => $result->is_fulfilled, "created_by" => $result->created_by, "transaction_type" => $result->transaction_type, "user_agent" => $result->user_agent, "status" => $result->status);
  2303. }
  2304. $field_value = $result->value;
  2305. //using long values if specified
  2306. if($use_long_values && strlen($field_value) >= (GFORMS_MAX_FIELD_LENGTH-10)){
  2307. $field = RGFormsModel::get_field($form, $result->field_number);
  2308. $long_text = RGFormsModel::get_field_value_long($lead, $result->field_number, $form, false);
  2309. $field_value = !empty($long_text) ? $long_text : $field_value;
  2310. }
  2311. $lead[$result->field_number] = $field_value;
  2312. $prev_lead_id = $result->id;
  2313. }
  2314. }
  2315. //adding last lead.
  2316. if(sizeof($lead) > 0)
  2317. array_push($leads, $lead);
  2318. //running entry through gform_get_field_value filter
  2319. foreach($leads as &$lead){
  2320. foreach($form["fields"] as $field){
  2321. if(isset($field["inputs"]) && is_array($field["inputs"])){
  2322. foreach($field["inputs"] as $input){
  2323. $lead[(string)$input["id"]] = apply_filters("gform_get_input_value", rgar($lead, (string)$input["id"]), $lead, $field, $input["id"]);
  2324. }
  2325. }
  2326. else{
  2327. $lead[$field["id"]] = apply_filters("gform_get_input_value", rgar($lead, (string)$field["id"]), $lead, $field, "");
  2328. }
  2329. }
  2330. }
  2331. //add custom entry properties
  2332. $entry_ids = array();
  2333. foreach($leads as $l){
  2334. $entry_ids[] = $l["id"];
  2335. }
  2336. $entry_meta = GFFormsModel::get_entry_meta($form_id);
  2337. $meta_keys = array_keys($entry_meta);
  2338. $entry_meta_data_rows = gform_get_meta_values_for_entries($entry_ids, $meta_keys);
  2339. foreach($leads as &$lead){
  2340. foreach($entry_meta_data_rows as $entry_meta_data_row){
  2341. if($entry_meta_data_row->lead_id == $lead["id"]){
  2342. foreach($meta_keys as $meta_key){
  2343. $lead[$meta_key] = $entry_meta_data_row->$meta_key;
  2344. }
  2345. }
  2346. }
  2347. }
  2348. return $leads;
  2349. }
  2350. public static function save_key($key){
  2351. $current_key = get_option("rg_gforms_key");
  2352. if(empty($key)){
  2353. delete_option("rg_gforms_key");
  2354. }
  2355. else if($current_key != $key){
  2356. $key = trim($key);
  2357. update_option("rg_gforms_key", md5($key));
  2358. }
  2359. }
  2360. public static function get_lead_count($form_id, $search, $star=null, $read=null, $start_date=null, $end_date=null, $status=null, $payment_status = null){
  2361. global $wpdb;
  2362. if(!is_numeric($form_id))
  2363. return "";
  2364. $detail_table_name = self::get_lead_details_table_name();
  2365. $lead_table_name = self::get_lead_table_name();
  2366. $where = self::get_leads_where_sql(compact('form_id', 'search', 'status', 'star', 'read', 'start_date', 'end_date', 'payment_status', 'is_default'));
  2367. $sql = "SELECT count(distinct l.id)
  2368. FROM $lead_table_name l
  2369. INNER JOIN $detail_table_name ld ON l.id = ld.lead_id
  2370. $where";
  2371. return $wpdb->get_var($sql);
  2372. }
  2373. public static function get_grid_columns($form_id, $input_label_only=false){
  2374. $form = self::get_form_meta($form_id);
  2375. $field_ids = self::get_grid_column_meta($form_id);
  2376. if(!is_array($field_ids)){
  2377. $field_ids = array();
  2378. for($i=0, $count=sizeof($form["fields"]); $i<$count && $i<5; $i++){
  2379. $field = $form["fields"][$i];
  2380. //loading post category fields with choices and inputs
  2381. if($field["type"] == "post_category")
  2382. $field = GFCommon::add_categories_as_choices($field, "");
  2383. if(RGForms::get("displayOnly",$field) || self::get_input_type($field) == "list")
  2384. continue;
  2385. if(isset($field["inputs"]) && is_array($field["inputs"])){
  2386. if($field["type"] == "name"){
  2387. $field_ids[] = $field["id"] . '.3'; //adding first name
  2388. $field_ids[] = $field["id"] . '.6'; //adding last name
  2389. }
  2390. else{
  2391. $field_ids[] = $field["inputs"][0]["id"]; //getting first input
  2392. }
  2393. }
  2394. else{
  2395. $field_ids[] = $field["id"];
  2396. }
  2397. }
  2398. //adding default entry meta columns
  2399. $entry_metas = GFFormsModel::get_entry_meta($form_id);
  2400. foreach ($entry_metas as $key => $entry_meta){
  2401. if (rgar($entry_meta,"is_default_column"))
  2402. $field_ids[] = $key;
  2403. }
  2404. }
  2405. $columns = array();
  2406. $entry_meta = self::get_entry_meta($form_id);
  2407. foreach($field_ids as $field_id){
  2408. switch($field_id){
  2409. case "id" :
  2410. $columns[$field_id] = array("label" => "Entry Id", "type" => "id");
  2411. break;
  2412. case "ip" :
  2413. $columns[$field_id] = array("label" => "User IP", "type" => "ip");
  2414. break;
  2415. case "date_created" :
  2416. $columns[$field_id] = array("label" => "Entry Date", "type" => "date_created");
  2417. break;
  2418. case "source_url" :
  2419. $columns[$field_id] = array("label" => "Source Url", "type" => "source_url");
  2420. break;
  2421. case "payment_status" :
  2422. $columns[$field_id] = array("label" => "Payment Status", "type" => "payment_status");
  2423. break;
  2424. case "transaction_id" :
  2425. $columns[$field_id] = array("label" => "Transaction Id", "type" => "transaction_id");
  2426. break;
  2427. case "payment_date" :
  2428. $columns[$field_id] = array("label" => "Payment Date", "type" => "payment_date");
  2429. break;
  2430. case "payment_amount" :
  2431. $columns[$field_id] = array("label" => "Payment Amount", "type" => "payment_amount");
  2432. break;
  2433. case "created_by" :
  2434. $columns[$field_id] = array("label" => "User", "type" => "created_by");
  2435. break;
  2436. case ((is_string($field_id) || is_int($field_id)) && array_key_exists($field_id, $entry_meta)) :
  2437. $columns[$field_id] = array("label" => $entry_meta[$field_id]["label"], "type" => $field_id);
  2438. break;
  2439. default :
  2440. $field = self::get_field($form, $field_id);
  2441. if($field)
  2442. $columns[strval($field_id)] = array("label" => self::get_label($field, $field_id, $input_label_only), "type" => rgget("type", $field), "inputType" => rgget("inputType", $field));
  2443. }
  2444. }
  2445. return $columns;
  2446. }
  2447. public static function get_label($field, $input_id = 0, $input_only = false){
  2448. $field_label = (IS_ADMIN || RG_CURRENT_PAGE == "select_columns.php" || RG_CURRENT_PAGE == "print-entry.php" || rgget("gf_page", $_GET) == "select_columns" || rgget("gf_page", $_GET) == "print-entry") && !rgempty("adminLabel", $field) ? rgar($field,"adminLabel") : rgar($field,"label");
  2449. $input = self::get_input($field, $input_id);
  2450. if(rgget("type", $field) == "checkbox" && $input != null)
  2451. return $input["label"];
  2452. else if($input != null)
  2453. return $input_only ? $input["label"] : $field_label . ' (' . $input["label"] . ')';
  2454. else
  2455. return $field_label;
  2456. }
  2457. public static function get_input($field, $id){
  2458. if(isset($field["inputs"]) && is_array($field["inputs"])){
  2459. foreach($field["inputs"] as $input)
  2460. {
  2461. if($input["id"] == $id)
  2462. return $input;
  2463. }
  2464. }
  2465. return null;
  2466. }
  2467. public static function has_input($field, $input_id){
  2468. if(!is_array($field["inputs"]))
  2469. return false;
  2470. else{
  2471. foreach($field["inputs"] as $input)
  2472. {
  2473. if($input["id"] == $input_id)
  2474. return true;
  2475. }
  2476. return false;
  2477. }
  2478. }
  2479. public static function get_current_page_url($force_ssl=false) {
  2480. $pageURL = 'http';
  2481. if (RGForms::get("HTTPS",$_SERVER) == "on" || $force_ssl)
  2482. $pageURL .= "s";
  2483. $pageURL .= "://";
  2484. $pageURL .= RGForms::get("HTTP_HOST", $_SERVER) . rgget("REQUEST_URI", $_SERVER);
  2485. return $pageURL;
  2486. }
  2487. public static function get_submitted_fields($form_id){
  2488. global $wpdb;
  2489. $lead_detail_table_name = self::get_lead_details_table_name();
  2490. $field_list = "";
  2491. $fields = $wpdb->get_results($wpdb->prepare("SELECT DISTINCT field_number FROM $lead_detail_table_name WHERE form_id=%d", $form_id));
  2492. foreach($fields as $field)
  2493. $field_list .= intval($field->field_number) . ',';
  2494. if(!empty($field_list))
  2495. $field_list = substr($field_list, 0, strlen($field_list) -1);
  2496. return $field_list;
  2497. }
  2498. public static function get_field($form, $field_id){
  2499. if(is_numeric($field_id))
  2500. $field_id = intval($field_id); //removing floating part of field (i.e 1.3 -> 1) to return field by input id
  2501. if(!is_array($form["fields"]))
  2502. return null;
  2503. global $_fields;
  2504. $key = $form["id"] . "_" . $field_id;
  2505. if(!isset($_fields[$key])){
  2506. $_fields[$key] = null;
  2507. foreach($form["fields"] as $field){
  2508. if($field["id"] == $field_id){
  2509. $_fields[$key] = $field;
  2510. break;
  2511. }
  2512. }
  2513. }
  2514. return $_fields[$key];
  2515. }
  2516. public static function is_html5_enabled(){
  2517. return get_option("rg_gforms_enable_html5");
  2518. }
  2519. /**
  2520. * Return the current lead being processed. Should only be called when a form has been submitted.
  2521. * If called before the "real" lead has been saved to the database, uses self::create_lead() to create
  2522. * a temporary lead to work with.
  2523. */
  2524. public static function get_current_lead() {
  2525. // if a GF submission is not in process, always return false
  2526. if(!rgpost('gform_submit'))
  2527. return false;
  2528. if(!self::$_current_lead) {
  2529. $form = self::get_form_meta(rgpost('gform_submit'));
  2530. self::$_current_lead = self::create_lead($form);
  2531. }
  2532. return self::$_current_lead;
  2533. }
  2534. /**
  2535. * Set RGFormsModel::$lead for use in hooks where $lead is not explicitly passed.
  2536. *
  2537. * @param mixed $lead
  2538. */
  2539. public static function set_current_lead($lead) {
  2540. GFCache::flush();
  2541. self::$_current_lead = $lead;
  2542. }
  2543. /**
  2544. * v1.7 introduces conditional confirmations. If the form's "confirmations" key is empty, grab the existing confirmation
  2545. * and populate it in the form's "confirmations" property.
  2546. *
  2547. * @param mixed $form
  2548. */
  2549. public static function convert_confirmation($form) {
  2550. $id = uniqid();
  2551. // convert confirmation to new confirmations format
  2552. $confirmation = $form['confirmation'];
  2553. $confirmation['id'] = $id;
  2554. $confirmation['name'] = __('Default Confirmation', 'gravityforms');
  2555. $confirmation['isDefault'] = true;
  2556. $form['confirmations'] = array($id => $confirmation);
  2557. self::save_form_confirmations($form['id'], $form['confirmations']);
  2558. return $form;
  2559. }
  2560. public static function load_confirmations($form) {
  2561. $confirmations = self::get_form_confirmations($form['id']);
  2562. // if there are no confirmations, convert existing (singular) confirmation (prior to 1.7) to new (plural) confirmations format
  2563. if(empty($confirmations)) {
  2564. $form = self::convert_confirmation($form);
  2565. } else {
  2566. $form['confirmations'] = $confirmations;
  2567. }
  2568. return $form;
  2569. }
  2570. public static function get_form_confirmations($form_id) {
  2571. global $wpdb;
  2572. if(isset($_confirmations[$form_id]))
  2573. return $_confirmations[$form_id];
  2574. $tablename = GFFormsModel::get_meta_table_name();
  2575. $sql = $wpdb->prepare("SELECT confirmations FROM $tablename WHERE form_id = %d", $form_id);
  2576. $results = $wpdb->get_results($sql, ARRAY_A);
  2577. $confirmations = rgars($results, '0/confirmations');
  2578. self::$_confirmations[$form_id] = $confirmations ? maybe_unserialize($confirmations) : array();
  2579. return self::$_confirmations[$form_id];
  2580. }
  2581. public static function save_form_confirmations($form_id, $confirmations) {
  2582. return self::update_form_meta($form_id, $confirmations, 'confirmations');
  2583. }
  2584. public static function save_form_notifications($form_id, $notifications) {
  2585. return self::update_form_meta($form_id, $notifications, 'notifications');
  2586. }
  2587. public static function get_entry_meta($form_id){
  2588. global $_entry_meta;
  2589. if(!isset($_entry_meta[$form_id])){
  2590. $_entry_meta = array();
  2591. $_entry_meta[$form_id] = apply_filters('gform_entry_meta', array(), $form_id);
  2592. }
  2593. return $_entry_meta[$form_id];
  2594. }
  2595. public static function set_entry_meta($lead, $form){
  2596. $entry_meta = self::get_entry_meta($form["id"]);
  2597. $keys = array_keys($entry_meta);
  2598. foreach ($keys as $key){
  2599. if (isset($entry_meta[$key]['update_entry_meta_callback'])){
  2600. $callback = $entry_meta[$key]['update_entry_meta_callback'];
  2601. $value = call_user_func_array($callback, array($key, $lead, $form));
  2602. gform_update_meta($lead["id"], $key, $value);
  2603. $lead[$key] = $value;
  2604. }
  2605. }
  2606. return $lead;
  2607. }
  2608. /*------- search entries ----------*/
  2609. //note: current only supports combining search criteria with AND
  2610. //search criteria examples
  2611. /*
  2612. $search_criteria[] = array('type' => 'field', 'key' => "1", 'value' => "gquiz159982170");
  2613. //note: this won't work for checkboxes if the checboxes have been re-ordered - best to use the following example below
  2614. $search_criteria[] = array('type' => 'field', 'key' => "2.2", 'value' => "gquiz246fec995");
  2615. //use to search checkbox values where values are unique - avoids missing checboxes that have been re-ordered
  2616. $search_criteria[] = array('type' => 'field', 'key' => "2", 'value' => "gquiz246fec995");
  2617. //any valid entry meta added using the gform_entry_meta hook
  2618. $search_criteria[] = array('type' => 'meta', 'key' => "gquiz_score", 'value' => "1");
  2619. $search_criteria[] = array('type' => 'meta', 'key' => "gquiz_is_pass", 'value' => "1");
  2620. //any column in the main leads table
  2621. $search_criteria[] = array("type" => "info", "key" => "status", "value"=>"active");
  2622. $search_criteria[] = array("type" => "info", "key" => "currency", "value"=>"USD");
  2623. $search_criteria[] = array('key' => 'date_created', 'type' => 'info', 'operator' => '>=', 'value' => $start_date );
  2624. $search_criteria[] = array('key' => 'date_created', 'type' => 'info', 'operator' => '<=', 'value' => $end_date );
  2625. //search values of any field
  2626. $search_criteria[] = array('type' => 'free-form', 'value' => $search_value);
  2627. //sorting: column, field or entry meta
  2628. $sorting = array('key' => $sort_field, 'direction' => $sort_direction );
  2629. //paging
  2630. $paging = array('offset' => 0, 'page_size' => 20 );
  2631. */
  2632. public static function search_leads($form_id, $search_criteria, $sorting = null, $paging = null) {
  2633. global $wpdb;
  2634. $sort_field = isset($sorting["key"]) ? $sorting["key"] : "date_created"; // column, field or entry meta
  2635. if (is_numeric($sort_field))
  2636. $sql = self::sort_by_field_query($form_id, $search_criteria, $sorting, $paging);
  2637. else
  2638. $sql = self::sort_by_column_query($form_id, $search_criteria, $sorting, $paging);
  2639. //initializing rownum
  2640. $wpdb->query("select @rownum:=0");
  2641. //getting results
  2642. $results = $wpdb->get_results($sql);
  2643. $leads = GFFormsModel::build_lead_array($results);
  2644. return $leads;
  2645. }
  2646. private static function sort_by_field_query($form_id, $search_criteria, $sorting, $paging) {
  2647. global $wpdb;
  2648. $sort_field_number = rgar($sorting, "key");
  2649. $sort_direction = isset($sorting["direction"]) ? $sorting["direction"] : "DESC";
  2650. $is_numeric_sort = isset($sorting["is_numeric"]) ? $sorting["is_numeric"] : false;
  2651. $offset = isset($paging["offset"]) ? $paging["offset"] : 0;
  2652. $page_size = isset($paging["page_size"]) ? $paging["page_size"] : 20;
  2653. if (!is_numeric($form_id) || !is_numeric($sort_field_number) || !is_numeric($offset) || !is_numeric($page_size))
  2654. return "";
  2655. $lead_detail_table_name = GFFormsModel::get_lead_details_table_name();
  2656. $lead_table_name = GFFormsModel::get_lead_table_name();
  2657. $orderby = $is_numeric_sort ? "ORDER BY query, (value+0) $sort_direction" : "ORDER BY query, value $sort_direction";
  2658. $search_where = self::get_search_where($form_id, $search_criteria);
  2659. $info_search_where = self::get_info_search_where($search_criteria);
  2660. if(!empty($search_where))
  2661. $info_search_where = " AND " . $info_search_where;
  2662. $where = empty($where) && empty($info_search_where) ? "" : "WHERE " . $search_where . $info_search_where;
  2663. $form_id_where = $form_id > 0 ? $wpdb->prepare(" AND form_id=%d", $form_id) : "";
  2664. $field_number_min = $sort_field_number - 0.001;
  2665. $field_number_max = $sort_field_number + 0.001;
  2666. $sql = "
  2667. SELECT filtered.sort, l.*, d.field_number, d.value
  2668. FROM $lead_table_name l
  2669. INNER JOIN $lead_detail_table_name d ON d.lead_id = l.id
  2670. INNER JOIN (
  2671. SELECT distinct sorted.sort, l.id
  2672. FROM $lead_table_name l
  2673. INNER JOIN $lead_detail_table_name d ON d.lead_id = l.id
  2674. INNER JOIN (
  2675. SELECT @rownum:=@rownum+1 as sort, id FROM (
  2676. SELECT 0 as query, lead_id as id, value
  2677. FROM $lead_detail_table_name
  2678. WHERE field_number between $field_number_min AND $field_number_max
  2679. $form_id_where
  2680. UNION ALL
  2681. SELECT 1 as query, l.id, d.value
  2682. FROM $lead_table_name l
  2683. LEFT OUTER JOIN $lead_detail_table_name d ON d.lead_id = l.id AND field_number between $field_number_min AND $field_number_max
  2684. WHERE d.lead_id IS NULL
  2685. $form_id_where
  2686. ) sorted1
  2687. $orderby
  2688. ) sorted ON d.lead_id = sorted.id
  2689. $where
  2690. LIMIT $offset,$page_size
  2691. ) filtered ON filtered.id = l.id
  2692. ORDER BY filtered.sort";
  2693. return $sql;
  2694. }
  2695. private static function sort_by_column_query($form_id, $search_criteria, $sorting, $paging) {
  2696. global $wpdb;
  2697. $sort_field = isset($sorting["key"]) ? $sorting["key"] : "date_created";
  2698. $sort_direction = isset($sorting["direction"]) ? $sorting["direction"] : "DESC";
  2699. $is_numeric_sort = isset($sorting["is_numeric"]) ? $sorting["is_numeric"] : false;
  2700. $offset = isset($paging["offset"]) ? $paging["offset"] : 0;
  2701. $page_size = isset($paging["page_size"]) ? $paging["page_size"] : 20;
  2702. if (!is_numeric($form_id) || !is_numeric($offset) || !is_numeric($page_size)) {
  2703. return "";
  2704. }
  2705. $lead_detail_table_name = GFFormsModel::get_lead_details_table_name();
  2706. $lead_table_name = GFFormsModel::get_lead_table_name();
  2707. $lead_meta_table_name = GFFormsModel::get_lead_meta_table_name();
  2708. $entry_meta = GFFormsModel::get_entry_meta($form_id);
  2709. $entry_meta_sql_join = "";
  2710. if (false === empty($entry_meta) && array_key_exists($sort_field, $entry_meta)) {
  2711. $entry_meta_sql_join = $wpdb->prepare("INNER JOIN
  2712. (
  2713. SELECT
  2714. lead_id, meta_value as $sort_field
  2715. from $lead_meta_table_name
  2716. WHERE meta_key=%s
  2717. ) lead_meta_data ON lead_meta_data.lead_id = l.id
  2718. ", $sort_field);
  2719. $is_numeric_sort = $entry_meta[$sort_field]['is_numeric'];
  2720. }
  2721. $grid_columns = RGFormsModel::get_grid_columns($form_id);
  2722. if ($sort_field != "date_created" && false === array_key_exists($sort_field, $grid_columns))
  2723. $sort_field = "date_created";
  2724. $orderby = $is_numeric_sort ? "ORDER BY ($sort_field+0) $sort_direction" : "ORDER BY $sort_field $sort_direction";
  2725. $where_arr = array();
  2726. $search_where = self::get_search_where($form_id, $search_criteria);
  2727. if (!empty($search_where))
  2728. $where_arr[]=$search_where;
  2729. $info_search_where = self::get_info_search_where($search_criteria);
  2730. if(!empty($info_search_where))
  2731. $where_arr[] = $info_search_where;
  2732. $form_id_where = $form_id > 0 ? $wpdb->prepare("l.form_id=%d", $form_id) : "";
  2733. if(!empty($form_id_where))
  2734. $where_arr[] = $form_id_where;
  2735. $where = empty($where_arr) ? "" : "WHERE " . join($where_arr, " AND ") ;
  2736. $sql = "
  2737. SELECT filtered.sort, l.*, d.field_number, d.value
  2738. FROM $lead_table_name l
  2739. INNER JOIN $lead_detail_table_name d ON d.lead_id = l.id
  2740. INNER JOIN
  2741. (
  2742. SELECT @rownum:=@rownum + 1 as sort, id
  2743. FROM
  2744. (
  2745. SELECT distinct l.id
  2746. FROM $lead_table_name l
  2747. INNER JOIN $lead_detail_table_name d ON d.lead_id = l.id
  2748. $entry_meta_sql_join
  2749. $where
  2750. $orderby
  2751. LIMIT $offset,$page_size
  2752. ) page
  2753. ) filtered ON filtered.id = l.id
  2754. ORDER BY filtered.sort";
  2755. return $sql;
  2756. }
  2757. private static function get_search_where($form_id, $search_criteria) {
  2758. global $wpdb;
  2759. $sql_array = array();
  2760. $lead_details_table_name = GFFormsModel::get_lead_details_table_name();
  2761. $lead_meta_table_name = GFFormsModel::get_lead_meta_table_name();
  2762. $form_id_where = $form_id > 0 ? $wpdb->prepare("WHERE form_id=%d", $form_id) : "";
  2763. foreach ($search_criteria as $search) {
  2764. $key = rgar($search, "key");
  2765. $val = rgar($search, "value");
  2766. switch (rgar($search, "type")) {
  2767. case "field":
  2768. $upper_field_number_limit = (string)(int)$key === $key ? (float)$key + 0.9999 : (float)$key + 0.0001;
  2769. $operator = isset($search["operator"]) ? $search["operator"] : "=";
  2770. $search_term = "LIKE" == $operator ? "%$val%" : $val;
  2771. /* doesn't support "<>" for checkboxes */
  2772. $sql_array[] = $wpdb->prepare("l.id IN
  2773. (
  2774. SELECT
  2775. lead_id
  2776. from $lead_details_table_name
  2777. $form_id_where
  2778. AND (field_number BETWEEN %s AND %s AND value $operator %s)
  2779. )
  2780. ", (float)$key - 0.0001, $upper_field_number_limit, $search_term);
  2781. /*
  2782. //supports "<>" for checkboxes but it doesn't scale
  2783. $sql_array[] = $wpdb->prepare("l.id IN
  2784. (SELECT lead_id
  2785. FROM
  2786. (
  2787. SELECT lead_id, value
  2788. FROM $lead_details_table_name
  2789. WHERE form_id = %d
  2790. AND (field_number BETWEEN %s AND %s)
  2791. GROUP BY lead_id
  2792. HAVING value $operator %s
  2793. ) ld
  2794. )
  2795. ", $form_id, (float)$key - 0.0001, $upper_field_number_limit, $val );
  2796. */
  2797. break;
  2798. case "meta":
  2799. /* doesn't support "<>" for multiple values of the same key */
  2800. $operator = isset($search["operator"]) ? $search["operator"] : "=";
  2801. $search_term = "LIKE" == $operator ? "%$val%" : $val;
  2802. $sql_array[] = $wpdb->prepare("l.id IN
  2803. (
  2804. SELECT
  2805. lead_id
  2806. FROM $lead_meta_table_name
  2807. WHERE meta_key=%s AND meta_value $operator %s
  2808. )
  2809. ", $search["key"], $search_term);
  2810. break;
  2811. }
  2812. }
  2813. $sql = empty($sql_array) ? "" : join(" AND ", $sql_array);
  2814. return $sql;
  2815. }
  2816. private static function get_info_search_where($search_criteria) {
  2817. global $wpdb;
  2818. $where_array = array();
  2819. foreach ($search_criteria as $search) {
  2820. switch (rgar($search, "type")) {
  2821. case "free-form":
  2822. $val = $search["value"];
  2823. $operator = isset($search["operator"]) ? $search["operator"] : "LIKE";
  2824. $search_term = "LIKE" == $operator ? "%$val%" : $val;
  2825. $where_array[] = $wpdb->prepare("value $operator %s", $search_term);
  2826. break;
  2827. case "info":
  2828. $col = $search["key"];
  2829. $val = $search["value"];
  2830. $operator = isset($search["operator"]) ? $search["operator"] : "=";
  2831. $search_term = "LIKE" == $operator ? "%$val%" : $val;
  2832. if ("date_created" === $col)
  2833. $where_array[] = $wpdb->prepare("datediff(date_created, %s) $operator 0", $val);
  2834. else
  2835. $where_array[] = $wpdb->prepare("{$col} $operator %s", $search_term);
  2836. break;
  2837. }
  2838. }
  2839. $sql = empty($where_array) ? "" : join(" AND ", $where_array);
  2840. return $sql;
  2841. }
  2842. public static function count_search_leads($form_id, $search_criteria) {
  2843. global $wpdb;
  2844. if (!is_numeric($form_id))
  2845. return "";
  2846. $detail_table_name = GFFormsModel::get_lead_details_table_name();
  2847. $lead_table_name = GFFormsModel::get_lead_table_name();
  2848. $where_arr = array();
  2849. $search_where = self::get_search_where($form_id, $search_criteria);
  2850. if (!empty($search_where))
  2851. $where_arr[]=$search_where;
  2852. $info_search_where = self::get_info_search_where($search_criteria);
  2853. if(!empty($info_search_where))
  2854. $where_arr[] = $info_search_where;
  2855. $form_id_where = $form_id > 0 ? $wpdb->prepare("l.form_id=%d", $form_id) : "";
  2856. if(!empty($form_id_where))
  2857. $where_arr[] = $form_id_where;
  2858. $where = empty($where_arr) ? "" : "WHERE " . join($where_arr, " AND ") ;
  2859. $sql = "SELECT count(distinct l.id)
  2860. FROM $lead_table_name l
  2861. INNER JOIN $detail_table_name ld ON l.id = ld.lead_id
  2862. $where
  2863. ";
  2864. return $wpdb->get_var($sql);
  2865. }
  2866. }
  2867. class RGFormsModel extends GFFormsModel { }
  2868. global $_gform_lead_meta;
  2869. $_gform_lead_meta = array();
  2870. //functions to handle lead meta
  2871. function gform_get_meta($entry_id, $meta_key){
  2872. global $wpdb, $_gform_lead_meta;
  2873. //get from cache if available
  2874. $cache_key = $entry_id . "_" . $meta_key;
  2875. if(array_key_exists($cache_key, $_gform_lead_meta))
  2876. return $_gform_lead_meta[$cache_key];
  2877. $table_name = RGFormsModel::get_lead_meta_table_name();
  2878. $results = $wpdb->get_results($wpdb->prepare("SELECT meta_value FROM {$table_name} WHERE lead_id=%d AND meta_key=%s", $entry_id, $meta_key));
  2879. $value = isset($results[0]) ? $results[0]->meta_value : null;
  2880. $meta_value = $value == null ? false : maybe_unserialize($value);
  2881. $_gform_lead_meta[$cache_key] = $meta_value;
  2882. return $meta_value;
  2883. }
  2884. function gform_get_meta_values_for_entries($entry_ids, $meta_keys){
  2885. global $wpdb;
  2886. if (empty($meta_keys) || empty($entry_ids))
  2887. return array();
  2888. $table_name = RGFormsModel::get_lead_meta_table_name();
  2889. $meta_value_array = array();
  2890. $select_meta_keys = join(",", $meta_keys);
  2891. $meta_key_select_array = array();
  2892. foreach($meta_keys as $meta_key){
  2893. $meta_key_select_array[] = "max(case when meta_key = '$meta_key' then meta_value end) as $meta_key";
  2894. }
  2895. $entry_ids_str = join(",", $entry_ids);
  2896. $meta_key_select = join(",", $meta_key_select_array);
  2897. $sql_query = " SELECT
  2898. lead_id, $meta_key_select
  2899. FROM $table_name
  2900. WHERE lead_id IN ($entry_ids_str)
  2901. GROUP BY lead_id";
  2902. $results = $wpdb->get_results($sql_query);
  2903. foreach($results as $result){
  2904. foreach($meta_keys as $meta_key){
  2905. $result->$meta_key = $result->$meta_key == null ? false : maybe_unserialize($result->$meta_key);
  2906. }
  2907. }
  2908. $meta_value_array = $results;
  2909. return $meta_value_array;
  2910. }
  2911. function gform_update_meta($entry_id, $meta_key, $meta_value){
  2912. global $wpdb, $_gform_lead_meta;
  2913. $table_name = RGFormsModel::get_lead_meta_table_name();
  2914. if (false === $meta_value)
  2915. $meta_value = "0";
  2916. $meta_value = maybe_serialize($meta_value);
  2917. $meta_exists = gform_get_meta($entry_id, $meta_key) !== false;
  2918. if($meta_exists){
  2919. $wpdb->update($table_name, array("meta_value" => $meta_value), array("lead_id" => $entry_id, "meta_key" => $meta_key),array("%s"), array("%d", "%s"));
  2920. }
  2921. else{
  2922. $lead_table_name = RGFormsModel::get_lead_table_name();
  2923. $form_id = $wpdb->get_var($wpdb->prepare("SELECT form_id from $lead_table_name WHERE id=%d", $entry_id));
  2924. $wpdb->insert($table_name, array("form_id" => $form_id, "lead_id" => $entry_id, "meta_key" => $meta_key, "meta_value" => $meta_value), array("%d", "%d", "%s", "%s"));
  2925. }
  2926. //updates cache
  2927. $cache_key = $entry_id . "_" . $meta_key;
  2928. if(array_key_exists($cache_key, $_gform_lead_meta))
  2929. $_gform_lead_meta[$cache_key] = maybe_unserialize($meta_value);
  2930. }
  2931. function gform_delete_meta($entry_id, $meta_key=""){
  2932. global $wpdb, $_gform_lead_meta;
  2933. $table_name = RGFormsModel::get_lead_meta_table_name();
  2934. $meta_filter = empty($meta_key) ? "" : $wpdb->prepare("AND meta_key=%s", $meta_key);
  2935. $wpdb->query($wpdb->prepare("DELETE FROM {$table_name} WHERE lead_id=%d {$meta_filter}", $entry_id));
  2936. //clears cache.
  2937. $_gform_lead_meta = array();
  2938. }
  2939. ?>