PageRenderTime 73ms CodeModel.GetById 19ms RepoModel.GetById 1ms 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

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

  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

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