Overview

Classes

  • GF_Personal_Data
  • GFAddOn
  • GFAddOnFeedsTable
  • GFAPI
  • GFFeedAddOn
  • GFPaymentAddOn
  • GFPaymentStatsTable
  • Overview
  • Class
   1: <?php
   2: 
   3: if ( ! class_exists( 'GFForms' ) ) {
   4:     die();
   5: }
   6: 
   7: /**
   8:  * API for standard Gravity Forms functionality.
   9:  *
  10:  * Supports:
  11:  * - Forms
  12:  * - Entries
  13:  *
  14:  * @package    Gravity Forms
  15:  * @subpackage GFAPI
  16:  * @since      1.8
  17:  * @access     public
  18:  */
  19: class GFAPI {
  20: 
  21:     // FORMS ----------------------------------------------------
  22: 
  23:     /**
  24:      * Returns the form object for a given Form ID.
  25:      *
  26:      * @since  1.8
  27:      * @access public
  28:      *
  29:      * @uses GFFormsModel::get_form_meta()
  30:      * @uses GFFormsModel::get_form()
  31:      *
  32:      * @param int $form_id The ID of the Form.
  33:      *
  34:      * @return mixed The form meta array or false.
  35:      */
  36:     public static function get_form( $form_id ) {
  37: 
  38:         $form_id = absint( $form_id );
  39: 
  40:         $form = GFFormsModel::get_form_meta( $form_id );
  41:         if ( ! $form ) {
  42:             return false;
  43:         }
  44: 
  45:         // Loading form columns into meta.
  46:         $form_info            = GFFormsModel::get_form( $form_id, true );
  47:         $form['is_active']    = $form_info->is_active;
  48:         $form['date_created'] = $form_info->date_created;
  49:         $form['is_trash']     = $form_info->is_trash;
  50: 
  51:         return $form;
  52: 
  53:     }
  54: 
  55:     /**
  56:      * Returns all the form objects.
  57:      *
  58:      * @since  1.8.11.5
  59:      * @access public
  60:      *
  61:      * @uses GFFormsModel::get_form_ids()
  62:      * @uses GFAPI::get_form()
  63:      *
  64:      * @param bool $active True if active forms are returned. False to get inactive forms. Defaults to true.
  65:      * @param bool $trash  True if trashed forms are returned. False to exclude trash. Defaults to false.
  66:      *
  67:      * @return array The array of Form Objects.
  68:      */
  69:     public static function get_forms( $active = true, $trash = false ) {
  70: 
  71:         $form_ids = GFFormsModel::get_form_ids( $active, $trash );
  72:         if ( empty( $form_ids ) ) {
  73:             return array();
  74:         }
  75: 
  76:         $forms = array();
  77:         foreach ( $form_ids as $form_id ) {
  78:             $forms[] = GFAPI::get_form( $form_id );
  79:         }
  80: 
  81:         return $forms;
  82:     }
  83: 
  84:     /**
  85:      * Deletes the forms with the given Form IDs.
  86:      *
  87:      * @since  1.8
  88:      * @access public
  89:      *
  90:      * @uses GFFormsModel::delete_forms()
  91:      *
  92:      * @param array $form_ids An array of form IDs to delete.
  93:      *
  94:      * @return void
  95:      */
  96:     public static function delete_forms( $form_ids ) {
  97: 
  98:         if ( gf_upgrade()->get_submissions_block() ) {
  99:             return;
 100:         }
 101: 
 102:         GFFormsModel::delete_forms( $form_ids );
 103:     }
 104: 
 105:     /**
 106:      * Deletes the form with the given Form ID.
 107:      *
 108:      * @since  1.8
 109:      * @access public
 110:      *
 111:      * @uses GFAPI::get_form()
 112:      * @uses GFAPI::delete_forms()
 113:      *
 114:      * @param int $form_id The ID of the Form to delete.
 115:      *
 116:      * @return mixed True for success, or a WP_Error instance.
 117:      */
 118:     public static function delete_form( $form_id ) {
 119: 
 120:         if ( gf_upgrade()->get_submissions_block() ) {
 121:             return new WP_Error( 'submissions_blocked', __( 'Submissions are currently blocked due to an upgrade in progress', 'gravityforms' ) );
 122:         }
 123: 
 124:         $form = self::get_form( $form_id );
 125:         if ( empty( $form ) ) {
 126:             return new WP_Error( 'not_found', sprintf( __( 'Form with id: %s not found', 'gravityforms' ), $form_id ), $form_id );
 127:         }
 128:         self::delete_forms( array( $form_id ) );
 129: 
 130:         return true;
 131:     }
 132: 
 133:     /**
 134:      * Duplicates the form with the given Form ID.
 135:      *
 136:      * @since  2.2
 137:      * @access public
 138:      *
 139:      * @uses GFFormsModel::duplicate_form()
 140:      *
 141:      * @param int $form_id The ID of the Form to delete.
 142:      *
 143:      * @return mixed True for success, or a WP_Error instance
 144:      */
 145:     public static function duplicate_form( $form_id ) {
 146: 
 147:         if ( gf_upgrade()->get_submissions_block() ) {
 148:             return new WP_Error( 'submissions_blocked', __( 'Submissions are currently blocked due to an upgrade in progress', 'gravityforms' ) );
 149:         }
 150: 
 151:         return GFFormsModel::duplicate_form( $form_id );
 152: 
 153:     }
 154: 
 155:     /**
 156:      * Updates the forms with an array of form objects.
 157:      *
 158:      * @since  1.8
 159:      * @access public
 160:      *
 161:      * @uses GFAPI::update_form()
 162:      *
 163:      * @param array $forms Array of form objects.
 164:      *
 165:      * @return mixed True for success, or a WP_Error instance.
 166:      */
 167:     public static function update_forms( $forms ) {
 168: 
 169:         if ( gf_upgrade()->get_submissions_block() ) {
 170:             return new WP_Error( 'submissions_blocked', __( 'Submissions are currently blocked due to an upgrade in progress', 'gravityforms' ) );
 171:         }
 172: 
 173:         foreach ( $forms as $form ) {
 174:             $result = self::update_form( $form );
 175:             if ( is_wp_error( $result ) ) {
 176:                 return $result;
 177:             }
 178:         }
 179: 
 180:         return true;
 181:     }
 182: 
 183:     /**
 184:      * Updates the form with a given form object.
 185:      *
 186:      * @since  1.8
 187:      * @access public
 188:      * @global $wpdb
 189:      *
 190:      * @uses \GFFormsModel::get_meta_table_name()
 191:      * @uses \GFFormsModel::update_form_meta()
 192:      *
 193:      * @param array $form The Form object
 194:      * @param int   $form_id  Optional. If specified, then the ID in the Form Object will be ignored.
 195:      *
 196:      * @return bool|WP_Error True for success, or a WP_Error instance.
 197:      */
 198:     public static function update_form( $form, $form_id = null ) {
 199:         global $wpdb;
 200: 
 201:         if ( gf_upgrade()->get_submissions_block() ) {
 202:             return new WP_Error( 'submissions_blocked', __( 'Submissions are currently blocked due to an upgrade in progress', 'gravityforms' ) );
 203:         }
 204: 
 205:         if ( ! $form ) {
 206:             return new WP_Error( 'invalid', __( 'Invalid form object', 'gravityforms' ) );
 207:         }
 208: 
 209:         $form_table_name = GFFormsModel::get_form_table_name();
 210:         if ( empty( $form_id ) ) {
 211:             $form_id = $form['id'];
 212:         } else {
 213:             // Make sure the form object has the right form ID.
 214:             $form['id'] = $form_id;
 215:         }
 216: 
 217:         if ( empty( $form_id ) ) {
 218:             return new WP_Error( 'missing_form_id', __( 'Missing form id', 'gravityforms' ) );
 219:         }
 220: 
 221:         if ( isset( $form['fields'] ) ) {
 222: 
 223:             // Make sure the formId is correct.
 224:             $form = GFFormsModel::convert_field_objects( $form );
 225: 
 226:             $next_field_id = GFFormsModel::get_next_field_id( $form['fields'] );
 227: 
 228:             $form['fields'] = self::add_missing_ids( $form['fields'], $next_field_id );
 229:         }
 230: 
 231:         $meta_table_name = GFFormsModel::get_meta_table_name();
 232: 
 233:         if ( intval( $wpdb->get_var( $wpdb->prepare( "SELECT count(0) FROM {$meta_table_name} WHERE form_id=%d", $form_id ) ) ) == 0 ) {
 234:             return new WP_Error( 'not_found', __( 'Form not found', 'gravityforms' ) );
 235:         }
 236: 
 237:         // Strip confirmations and notifications.
 238:         $form_display_meta = $form;
 239:         unset( $form_display_meta['confirmations'] );
 240:         unset( $form_display_meta['notifications'] );
 241: 
 242:         $result = GFFormsModel::update_form_meta( $form_id, $form_display_meta );
 243:         if ( false === $result ) {
 244:             return new WP_Error( 'error_updating_form', __( 'Error updating form', 'gravityforms' ), $wpdb->last_error );
 245:         }
 246: 
 247:         if ( isset( $form['confirmations'] ) && is_array( $form['confirmations'] ) ) {
 248:             $confirmations = self::set_property_as_key( $form['confirmations'], 'id' );
 249:             $result        = GFFormsModel::update_form_meta( $form_id, $confirmations, 'confirmations' );
 250:             if ( false === $result ) {
 251:                 return new WP_Error( 'error_updating_confirmations', __( 'Error updating form confirmations', 'gravityforms' ), $wpdb->last_error );
 252:             }
 253:         }
 254: 
 255:         if ( isset( $form['notifications'] ) && is_array( $form['notifications'] ) ) {
 256:             $notifications = self::set_property_as_key( $form['notifications'], 'id' );
 257:             $result        = GFFormsModel::update_form_meta( $form_id, $notifications, 'notifications' );
 258:             if ( false === $result ) {
 259:                 return new WP_Error( 'error_updating_notifications', __( 'Error updating form notifications', 'gravityforms' ), $wpdb->last_error );
 260:             }
 261:         }
 262: 
 263:         // Updating form title and is_active flag.
 264:         $is_active = rgar( $form, 'is_active' ) ? '1' : '0';
 265:         $result    = $wpdb->query( $wpdb->prepare( "UPDATE {$form_table_name} SET title=%s, is_active=%s WHERE id=%d", $form['title'], $is_active, $form['id'] ) );
 266:         if ( false === $result ) {
 267:             return new WP_Error( 'error_updating_title', __( 'Error updating title', 'gravityforms' ), $wpdb->last_error );
 268:         }
 269: 
 270:         return true;
 271:     }
 272: 
 273:     /**
 274:      * Adds missing IDs to field objects.
 275:      *
 276:      * @since 2.4.6.12
 277:      *
 278:      * @param GF_Field[] $fields
 279:      * @param $next_field_id
 280:      *
 281:      * @return GF_Field[]
 282:      */
 283:     private static function add_missing_ids( $fields, $next_field_id ) {
 284:         foreach ( $fields as &$field ) {
 285:             if ( empty( $field->id ) ) {
 286:                 $field->id = $next_field_id ++;
 287:             }
 288:             if ( is_array( $field->fields ) ) {
 289:                 $field->fields = self::add_missing_ids( $field->fields, $next_field_id );
 290:             }
 291:         }
 292:         return $fields;
 293:     }
 294: 
 295:     /**
 296:      * Updates a form property - a column in the main forms table. e.g. is_trash, is_active, title
 297:      *
 298:      * @since  1.8.3.15
 299:      * @access public
 300:      *
 301:      * @uses GFFormsModel::get_form_table_name()
 302:      * @uses GFFormsModel::get_form_db_columns()
 303:      *
 304:      * @param array  $form_ids     The IDs of the forms to update.
 305:      * @param string $property_key The name of the column in the database e.g. is_trash, is_active, title.
 306:      * @param mixed  $value        The new value.
 307:      *
 308:      * @return mixed Either a WP_Error instance or the result of the query
 309:      */
 310:     public static function update_forms_property( $form_ids, $property_key, $value ) {
 311:         global $wpdb;
 312: 
 313:         if ( gf_upgrade()->get_submissions_block() ) {
 314:             return new WP_Error( 'submissions_blocked', __( 'Submissions are currently blocked due to an upgrade in progress', 'gravityforms' ) );
 315:         }
 316: 
 317:         $table        = GFFormsModel::get_form_table_name();
 318: 
 319:         $db_columns = GFFormsModel::get_form_db_columns();
 320: 
 321:         if ( ! in_array( strtolower( $property_key ), $db_columns ) ) {
 322:             return new WP_Error( 'property_key_incorrect', __( 'Property key incorrect', 'gravityforms' ) );
 323:         }
 324: 
 325:         $value = esc_sql( $value );
 326:         if ( ! is_numeric( $value ) ) {
 327:             $value = sprintf( "'%s'", $value );
 328:         }
 329:         $in_str_arr = array_fill( 0, count( $form_ids ), '%d' );
 330:         $in_str     = join( $in_str_arr, ',' );
 331:         $result     = $wpdb->query(
 332:             $wpdb->prepare(
 333:                 "
 334:                 UPDATE $table
 335:                 SET {$property_key} = {$value}
 336:                 WHERE id IN ($in_str)
 337:                 ", $form_ids
 338:             )
 339:         );
 340: 
 341:         return $result;
 342:     }
 343: 
 344:     /**
 345:      * Updates the property of one form - columns in the main forms table. e.g. is_trash, is_active, title.
 346:      *
 347:      * @since  1.8.3.15
 348:      * @access public
 349:      *
 350:      * @uses GFAPI::update_forms_property()
 351:      *
 352:      * @param array|int $form_id      The ID of the forms to update.
 353:      * @param string    $property_key The name of the column in the database e.g. is_trash, is_active, title.
 354:      * @param string    $value        The new value.
 355:      *
 356:      * @return mixed Either a WP_Error instance or the result of the query
 357:      */
 358:     public static function update_form_property( $form_id, $property_key, $value ) {
 359:         if ( gf_upgrade()->get_submissions_block() ) {
 360:             return new WP_Error( 'submissions_blocked', __( 'Submissions are currently blocked due to an upgrade in progress', 'gravityforms' ) );
 361:         }
 362:         return self::update_forms_property( array( $form_id ), $property_key, $value );
 363:     }
 364: 
 365: 
 366:     /**
 367:      * Adds multiple form objects.
 368:      *
 369:      * @since  1.8
 370:      * @access public
 371:      *
 372:      * @uses GFAPI::add_form()
 373:      *
 374:      * @param array $forms The Form Objects.
 375:      *
 376:      * @return array|WP_Error Either an array of new form IDs or a WP_Error instance.
 377:      */
 378:     public static function add_forms( $forms ) {
 379: 
 380:         if ( gf_upgrade()->get_submissions_block() ) {
 381:             return new WP_Error( 'submissions_blocked', __( 'Submissions are currently blocked due to an upgrade in progress', 'gravityforms' ) );
 382:         }
 383: 
 384:         if ( ! $forms || ! is_array( $forms ) ) {
 385:             return new WP_Error( 'invalid', __( 'Invalid form objects', 'gravityforms' ) );
 386:         }
 387:         $form_ids = array();
 388:         foreach ( $forms as $form ) {
 389:             $result = self::add_form( $form );
 390:             if ( is_wp_error( $result ) ) {
 391:                 return $result;
 392:             }
 393:             $form_ids[] = $result;
 394:         }
 395: 
 396:         return $form_ids;
 397:     }
 398: 
 399:     /**
 400:      * Adds a new form using the given Form object. Warning, little checking is done to make sure it's a valid Form object.
 401:      *
 402:      * @since  1.8
 403:      * @access public
 404:      * @global $wpdb
 405:      *
 406:      * @uses GFFormsModel::is_unique_title()
 407:      * @uses GFFormsModel::insert_form()
 408:      * @uses GFAPI::set_property_as_key()
 409:      * @uses GFFormsModel::update_form_meta()
 410:      *
 411:      * @param array $form_meta The Form object.
 412:      *
 413:      * @return int|WP_Error Either the new Form ID or a WP_Error instance.
 414:      */
 415:     public static function add_form( $form_meta ) {
 416:         global $wpdb;
 417: 
 418:         if ( gf_upgrade()->get_submissions_block() ) {
 419:             return new WP_Error( 'submissions_blocked', __( 'Submissions are currently blocked due to an upgrade in progress', 'gravityforms' ) );
 420:         }
 421: 
 422:         if ( ! $form_meta || ! is_array( $form_meta ) ) {
 423:             return new WP_Error( 'invalid', __( 'Invalid form object', 'gravityforms' ) );
 424:         }
 425: 
 426:         if ( rgar( $form_meta, 'title' ) == '' ) {
 427:             return new WP_Error( 'missing_title', __( 'The form title is missing', 'gravityforms' ) );
 428:         }
 429: 
 430:         if ( ! isset( $form_meta['fields'] ) || ! is_array( $form_meta['fields'] ) ) {
 431:             return new WP_Error( 'missing_fields', __( 'The form fields are missing', 'gravityforms' ) );
 432:         }
 433: 
 434:         // Making sure title is not duplicate.
 435:         $title = $form_meta['title'];
 436:         $count = 2;
 437:         while ( ! RGFormsModel::is_unique_title( $title ) ) {
 438:             $title = $form_meta['title'] . "($count)";
 439:             $count ++;
 440:         }
 441: 
 442:         // Inserting form.
 443:         $form_id = RGFormsModel::insert_form( $title );
 444: 
 445:         // Updating form meta.
 446:         $form_meta['title'] = $title;
 447: 
 448:         // Updating object's id property.
 449:         $form_meta['id'] = $form_id;
 450: 
 451:         // Add default confirmation if form has no confirmations.
 452:         if ( ! isset( $form_meta['confirmations'] ) || empty( $form_meta['confirmations'] ) ) {
 453: 
 454:             // Generate confirmation ID.
 455:             $confirmation_id = uniqid();
 456: 
 457:             // Add default confirmation to form.
 458:             $form_meta['confirmations'][ $confirmation_id ] = array(
 459:                 'id'          => $confirmation_id,
 460:                 'name'        => __( 'Default Confirmation', 'gravityforms' ),
 461:                 'isDefault'   => true,
 462:                 'type'        => 'message',
 463:                 'message'     => __( 'Thanks for contacting us! We will get in touch with you shortly.', 'gravityforms' ),
 464:                 'url'         => '',
 465:                 'pageId'      => '',
 466:                 'queryString' => '',
 467:             );
 468: 
 469:         }
 470: 
 471:         if ( isset( $form_meta['confirmations'] ) ) {
 472:             $form_meta['confirmations'] = self::set_property_as_key( $form_meta['confirmations'], 'id' );
 473:             GFFormsModel::update_form_meta( $form_id, $form_meta['confirmations'], 'confirmations' );
 474:             unset( $form_meta['confirmations'] );
 475:         }
 476: 
 477:         if ( isset( $form_meta['notifications'] ) ) {
 478:             $form_meta['notifications'] = self::set_property_as_key( $form_meta['notifications'], 'id' );
 479:             GFFormsModel::update_form_meta( $form_id, $form_meta['notifications'], 'notifications' );
 480:             unset( $form_meta['notifications'] );
 481:         }
 482: 
 483:         // Make sure the formId is correct.
 484:         $form_meta = GFFormsModel::convert_field_objects( $form_meta );
 485: 
 486:         $next_field_id = GFFormsModel::get_next_field_id( $form_meta['fields'] );
 487: 
 488:         $form_meta['fields'] = self::add_missing_ids( $form_meta['fields'], $next_field_id );
 489: 
 490:         // Updating form meta.
 491:         $result = GFFormsModel::update_form_meta( $form_id, $form_meta );
 492: 
 493:         if ( false === $result ) {
 494:             return new WP_Error( 'insert_form_error', __( 'There was a problem while inserting the form', 'gravityforms' ), $wpdb->last_error );
 495:         }
 496: 
 497:         return $form_id;
 498:     }
 499: 
 500:     /**
 501:      * Private.
 502:      *
 503:      * @since  1.8
 504:      * @access private
 505:      * @ignore
 506:      */
 507:     private static function set_property_as_key( $array, $property ) {
 508:         $new_array = array();
 509:         foreach ( $array as $item ) {
 510:             $new_array[ $item[ $property ] ] = $item;
 511:         }
 512: 
 513:         return $new_array;
 514:     }
 515: 
 516:     // ENTRIES ----------------------------------------------------
 517: 
 518:     /**
 519:      * Returns an array of Entry objects for the given search criteria. The search criteria array is constructed as follows:
 520:      *
 521:      *  Filter by status
 522:      *     $search_criteria['status'] = 'active';
 523:      *
 524:      *  Filter by date range
 525:      *     $search_criteria['start_date'] = $start_date; // Using the time zone in the general settings.
 526:      *     $search_criteria['end_date'] =  $end_date;    // Using the time zone in the general settings.
 527:      *
 528:      *  Filter by any column in the main table
 529:      *     $search_criteria['field_filters'][] = array("key" => 'currency', value => 'USD');
 530:      *     $search_criteria['field_filters'][] = array("key" => 'is_read', value => true);
 531:      *
 532:      *  Filter by Field Values
 533:      *     $search_criteria['field_filters'][] = array('key' => '1', 'value' => 'gquiz159982170');
 534:      *
 535:      *  Filter Operators
 536:      *     Supported operators for scalar values: is/=, isnot/<>, contains
 537:      *     $search_criteria['field_filters'][] = array('key' => '1', 'operator' => 'contains', value' => 'Steve');
 538:      *     Supported operators for array values: in/=, not in/<>/!=
 539:      *     $search_criteria['field_filters'][] = array('key' => '1', 'operator' => 'not in', value' => array( 'Alex', 'David', 'Dana' );
 540:      *
 541:      *  Filter by a checkbox value - input ID search keys
 542:      *     $search_criteria['field_filters'][] = array('key' => '2.2', 'value' => 'gquiz246fec995');
 543:      *     NOTES:
 544:      *          - Using input IDs as search keys will work for checkboxes but it won't work if the checkboxes have been re-ordered since the first submission.
 545:      *          - the 'not in' operator is not currently supported for checkbox values.
 546:      *
 547:      *  Filter by a checkbox value - field ID keys
 548:      *     Using the field ID as the search key is recommended for checkboxes.
 549:      *     $search_criteria['field_filters'][] = array('key' => '2', 'value' => 'gquiz246fec995');
 550:      *     $search_criteria['field_filters'][] = array('key' => '2', 'operator' => 'in', 'value' => array( 'First Choice', 'Third Choice' );
 551:      *     NOTE: Neither 'not in' nor '<>' operators are not currently supported for checkboxes using field IDs as search keys.
 552:      *
 553:      *  Filter by a global search of values of any form field
 554:      *     $search_criteria['field_filters'][] = array('value' => $search_value);
 555:      *  OR
 556:      *     $search_criteria['field_filters'][] = array('key' => 0, 'value' => $search_value);
 557:      *
 558:      *  Filter entries by Entry meta (added using the gform_entry_meta hook)
 559:      *     $search_criteria['field_filters'][] = array('key' => 'gquiz_score', 'value' => '1');
 560:      *     $search_criteria['field_filters'][] = array('key' => 'gquiz_is_pass', 'value' => '1');
 561:      *
 562:      *  Filter by ALL / ANY of the field filters
 563:      *     $search_criteria['field_filters']['mode'] = 'all'; // default
 564:      *     $search_criteria['field_filters']['mode'] = 'any';
 565:      *
 566:      *  Sorting: column, field or entry meta
 567:      *     $sorting = array('key' => $sort_field, 'direction' => 'ASC' );
 568:      *
 569:      *  Paging
 570:      *     $paging = array('offset' => 0, 'page_size' => 20 );
 571:      *
 572:      * @since  1.8
 573:      * @access public
 574:      *
 575:      *
 576:      * @param int|array $form_ids        The ID of the form or an array IDs of the Forms. Zero for all forms.
 577:      * @param array     $search_criteria Optional. An array containing the search criteria. Defaults to empty array.
 578:      * @param array     $sorting         Optional. An array containing the sorting criteria. Defaults to null.
 579:      * @param array     $paging          Optional. An array containing the paging criteria. Defaults to null.
 580:      * @param int       $total_count     Optional. An output parameter containing the total number of entries. Pass a non-null value to get the total count. Defaults to null.
 581:      *
 582:      * @return array|WP_Error Either an array of the Entry objects or a WP_Error instance.
 583:      */
 584:     public static function get_entries( $form_ids, $search_criteria = array(), $sorting = null, $paging = null, &$total_count = null ) {
 585: 
 586:         if ( empty( $sorting ) ) {
 587:             $sorting = array( 'key' => 'id', 'direction' => 'DESC', 'is_numeric' => true );
 588:         }
 589: 
 590:         if ( version_compare( GFFormsModel::get_database_version(), '2.3-dev-1', '<' ) ) {
 591:             $entries = GF_Forms_Model_Legacy::search_leads( $form_ids, $search_criteria, $sorting, $paging );
 592:             if ( ! is_null( $total_count ) ) {
 593:                 $total_count = self::count_entries( $form_ids, $search_criteria );
 594:             }
 595:             return $entries;
 596:         }
 597: 
 598:         $q = new GF_Query( $form_ids, $search_criteria, $sorting, $paging );
 599:         $entries = $q->get();
 600:         $total_count = $q->total_found;
 601: 
 602:         return $entries;
 603:     }
 604: 
 605:     /**
 606:      * Returns an array of Entry IDs for the given search criteria.
 607:      *
 608:      * @since  2.3     Added $sorting and $paging parameters.
 609:      * @since  Unknown
 610:      * @access public
 611:      *
 612:      * @param int|array $form_id         The ID of the form or an array IDs of the Forms. Zero for all forms.
 613:      * @param array     $search_criteria Optional. An array containing the search criteria. Defaults to empty array.
 614:      * @param array     $sorting         Optional. An array containing the sorting criteria. Defaults to null.
 615:      * @param array     $paging          Optional. An array containing the paging criteria. Defaults to null.
 616:      * @param null|int  $total_count     Optional. An output parameter containing the total number of entries. Pass a non-null value to get the total count. Defaults to null.
 617:      *
 618:      * @return array An array of the Entry IDs.
 619:      */
 620:     public static function get_entry_ids( $form_id, $search_criteria = array(), $sorting = null, $paging = null, &$total_count = null ) {
 621: 
 622:         if ( version_compare( GFFormsModel::get_database_version(), '2.3-dev-1', '<' ) ) {
 623:             $entry_ids = GF_Forms_Model_Legacy::search_lead_ids( $form_id, $search_criteria );
 624:             return $entry_ids;
 625:         }
 626: 
 627:         if ( ! $paging ) {
 628:             $paging = array( 'page_size' => 0 );
 629:         }
 630: 
 631:         $the_query = new GF_Query( $form_id, $search_criteria, $sorting, $paging  );
 632:         $entry_ids = $the_query->get_ids();
 633:         $total_count = $the_query->total_found;
 634:         return $entry_ids;
 635:     }
 636: 
 637:     /**
 638:      * Returns the total number of entries for the given search criteria. See get_entries() for examples of the search criteria.
 639:      *
 640:      * @since  1.8
 641:      * @access public
 642:      *
 643:      * @uses GFFormsModel::count_search_leads()
 644:      *
 645:      * @param int|array $form_ids        The ID of the Form or an array of Form IDs.
 646:      * @param array     $search_criteria Optional. An array containing the search criteria. Defaults to empty array.
 647:      *
 648:      * @return int The total count.
 649:      */
 650:     public static function count_entries( $form_ids, $search_criteria = array() ) {
 651: 
 652:         if ( version_compare( GFFormsModel::get_database_version(), '2.3-dev-1', '<' ) ) {
 653:             return GF_Forms_Model_Legacy::count_search_leads( $form_ids, $search_criteria );
 654:         }
 655: 
 656:         $q = new GF_Query( $form_ids, $search_criteria );
 657:         $ids = $q->get_ids();
 658:         return $q->total_found;
 659:     }
 660: 
 661:     /**
 662:      * Returns the Entry object for a given Entry ID.
 663:      *
 664:      * @since  1.8
 665:      * @access public
 666:      *
 667:      * @uses GFAPI::get_entries()
 668:      *
 669:      * @param int $entry_id The ID of the Entry.
 670:      *
 671:      * @return array|WP_Error The Entry object or a WP_Error instance.
 672:      */
 673:     public static function get_entry( $entry_id ) {
 674: 
 675:         if ( version_compare( GFFormsModel::get_database_version(), '2.3-dev-1', '<' ) ) {
 676:             $search_criteria['field_filters'][] = array( 'key' => 'id', 'value' => $entry_id );
 677: 
 678:             $paging  = array( 'offset' => 0, 'page_size' => 1 );
 679:             $entries = self::get_entries( 0, $search_criteria, null, $paging );
 680:             if ( empty( $entries ) ) {
 681:                 return new WP_Error( 'not_found', sprintf( __( 'Entry with id %s not found', 'gravityforms' ), $entry_id ), $entry_id );
 682:             }
 683: 
 684:             return $entries[0];
 685:         }
 686: 
 687:         $q = new GF_Query();
 688: 
 689:         $entry = $q->get_entry( $entry_id );
 690: 
 691:         if ( empty( $entry ) ) {
 692:             return new WP_Error( 'not_found', sprintf( __( 'Entry with id %s not found', 'gravityforms' ), $entry_id ), $entry_id );
 693:         }
 694: 
 695:         return $entry;
 696:     }
 697: 
 698:     /**
 699:      * Adds multiple Entry objects.
 700:      *
 701:      * @since  1.8
 702:      * @access public
 703:      *
 704:      * @uses GFAPI::add_entry()
 705:      *
 706:      * @param array $entries The Entry objects
 707:      * @param int   $form_id Optional. If specified, the form_id in the Entry objects will be ignored. Defaults to null.
 708:      *
 709:      * @return array|WP_Error Either an array of new Entry IDs or a WP_Error instance
 710:      */
 711:     public static function add_entries( $entries, $form_id = null ) {
 712: 
 713:         if ( gf_upgrade()->get_submissions_block() ) {
 714:             return new WP_Error( 'submissions_blocked', __( 'Submissions are currently blocked due to an upgrade in progress', 'gravityforms' ) );
 715:         }
 716: 
 717:         $entry_ids = array();
 718:         foreach ( $entries as $entry ) {
 719:             if ( $form_id ) {
 720:                 $entry['form_id'] = $form_id;
 721:             }
 722:             $result = self::add_entry( $entry );
 723:             if ( is_wp_error( $result ) ) {
 724:                 return $result;
 725:             }
 726:             $entry_ids[] = $result;
 727:         }
 728: 
 729:         return $entry_ids;
 730:     }
 731: 
 732:     /**
 733:      * Updates multiple Entry objects.
 734:      *
 735:      * @since  1.8
 736:      * @access public
 737:      *
 738:      * @uses GFCommon::log_debug()
 739:      * @uses GFAPI::update_entry()
 740:      *
 741:      * @param array $entries The Entry objects
 742:      *
 743:      * @return bool|WP_Error Either true for success, or a WP_Error instance
 744:      */
 745:     public static function update_entries( $entries ) {
 746: 
 747:         if ( gf_upgrade()->get_submissions_block() ) {
 748:             return new WP_Error( 'submissions_blocked', __( 'Submissions are currently blocked due to an upgrade in progress', 'gravityforms' ) );
 749:         }
 750: 
 751:         foreach ( $entries as $entry ) {
 752:             $entry_id = rgar( $entry, 'id' );
 753:             GFCommon::log_debug( __METHOD__ . '(): Updating entry ' . $entry_id );
 754:             $result = self::update_entry( $entry, $entry_id );
 755:             if ( is_wp_error( $result ) ) {
 756:                 return $result;
 757:             }
 758:         }
 759: 
 760:         return true;
 761:     }
 762: 
 763:     /**
 764:      * Updates an entire single Entry object.
 765:      *
 766:      * If the date_created value is not set then the current time UTC will be used.
 767:      * The date_created value, if set, is expected to be in 'Y-m-d H:i:s' format (UTC).
 768:      *
 769:      * @since  1.8
 770:      * @access public
 771:      * @global $wpdb
 772:      * @global $current_user
 773:      *
 774:      * @uses \GFAPI::get_entry
 775:      * @uses \GFAPI::form_id_exists
 776:      * @uses \GFFormsModel::get_ip
 777:      * @uses \GFFormsModel::get_current_page_url
 778:      * @uses \GFCommon::get_currency
 779:      * @uses \GFFormsModel::get_lead_table_name
 780:      * @uses \GFFormsModel::get_lead_details_table_name
 781:      * @uses \GFFormsModel::get_form_meta
 782:      * @uses \GFFormsModel::get_input_type
 783:      * @uses \GF_Field::get_entry_inputs
 784:      * @uses \GFFormsModel::get_lead_detail_id
 785:      * @uses \GFFormsModel::update_lead_field_value
 786:      * @uses \GFFormsModel::get_entry_meta
 787:      * @uses \GFFormsModel::get_field
 788:      *
 789:      * @param array $entry    The Entry Object.
 790:      * @param int   $entry_id Optional. If specified, the ID in the Entry Object will be ignored. Defaults to null.
 791:      *
 792:      * @return true|WP_Error Either True or a WP_Error instance
 793:      */
 794:     public static function update_entry( $entry, $entry_id = null ) {
 795:         global $wpdb;
 796: 
 797:         if ( gf_upgrade()->get_submissions_block() ) {
 798:             return new WP_Error( 'submissions_blocked', __( 'Submissions are currently blocked due to an upgrade in progress', 'gravityforms' ) );
 799:         }
 800: 
 801:         if ( version_compare( GFFormsModel::get_database_version(), '2.3-dev-1', '<' ) ) {
 802:             return GF_Forms_Model_Legacy::update_entry( $entry, $entry_id );
 803:         }
 804: 
 805:         if ( empty( $entry_id ) ) {
 806:             if ( rgar( $entry, 'id' ) ) {
 807:                 $entry_id = absint( $entry['id'] );
 808:             }
 809:         } else {
 810:             $entry['id'] = absint( $entry_id );
 811:         }
 812: 
 813:         if ( empty( $entry_id ) ) {
 814:             return new WP_Error( 'missing_entry_id', __( 'Missing entry id', 'gravityforms' ) );
 815:         }
 816: 
 817:         $current_entry = $original_entry = self::get_entry( $entry_id );
 818: 
 819:         if ( ! $current_entry ) {
 820:             return new WP_Error( 'not_found', __( 'Entry not found', 'gravityforms' ), $entry_id );
 821:         }
 822: 
 823:         if ( is_wp_error( $current_entry ) ) {
 824:             return $current_entry;
 825:         }
 826: 
 827:         // Make sure the form id exists
 828:         $form_id = rgar( $entry, 'form_id' );
 829:         if ( empty( $form_id ) ) {
 830:             $form_id          = rgar( $current_entry, 'form_id' );
 831:             $entry['form_id'] = $form_id;
 832:         }
 833: 
 834:         if ( false === self::form_id_exists( $form_id ) ) {
 835:             return new WP_Error( 'invalid_form_id', __( 'The form for this entry does not exist', 'gravityforms' ) );
 836:         }
 837: 
 838:         $form = GFFormsModel::get_form_meta( $form_id );
 839: 
 840:         /**
 841:          * Filters the entry before it is updated.
 842:          *
 843:          * @since Unknown
 844:          *
 845:          * @param array $entry          The Entry Object.
 846:          * @param array $original_entry Te original Entry Object, before changes.
 847:          */
 848:         $entry = apply_filters( 'gform_entry_pre_update', $entry, $original_entry );
 849: 
 850:         // Use values in the entry object if present.
 851:         if ( ! isset( $entry['post_id'] ) ) {
 852:             $entry['post_id'] = null;
 853:         }
 854:         $post_id = ! empty( $entry['post_id'] ) ? intval( $entry['post_id'] ) : 'NULL';
 855: 
 856:         $current_time = $wpdb->get_var( 'SELECT utc_timestamp()' );
 857: 
 858:         if ( empty( $entry['date_created'] ) ) {
 859:             $entry['date_created'] = $current_time;
 860:         }
 861:         $date_created = sprintf( "'%s'", esc_sql( $entry['date_created'] ) );
 862: 
 863:         if ( empty( $entry['date_updated'] ) ) {
 864:             $entry['date_updated'] = $current_time;
 865:         }
 866:         $date_updated = sprintf( "'%s'", esc_sql( $entry['date_updated'] ) );
 867: 
 868:         if ( ! isset( $entry['is_starred'] ) ) {
 869:             $entry['is_starred'] = 0;
 870:         }
 871:         $is_starred = intval( $entry['is_starred'] );
 872: 
 873:         if ( ! isset( $entry['is_read'] ) ) {
 874:             $entry['is_read'] = 0;
 875:         }
 876:         $is_read = intval( $entry['is_read'] );
 877: 
 878:         if ( ! isset( $entry['ip'] ) ) {
 879:             $entry['ip'] = rgars( $form, 'personalData/preventIP' ) ? '' : GFFormsModel::get_ip();
 880:         }
 881:         $ip = $entry['ip'];
 882: 
 883:         if ( ! isset( $entry['source_url'] ) ) {
 884:             $entry['source_url'] = GFFormsModel::get_current_page_url();
 885:         }
 886:         $source_url = $entry['source_url'];
 887: 
 888:         if ( ! isset( $entry['user_agent'] ) ) {
 889:             $entry['user_agent'] = 'API';
 890:         }
 891:         $user_agent = $entry['user_agent'];
 892: 
 893:         if ( empty( $entry['currency'] ) ) {
 894:             $entry['currency'] = GFCommon::get_currency();
 895:         }
 896:         $currency = $entry['currency'];
 897: 
 898:         if ( ! isset( $entry['payment_status'] ) ) {
 899:             $entry['payment_status'] = null;
 900:         }
 901:         $payment_status = ! empty( $entry['payment_status'] ) ? sprintf( "'%s'", esc_sql( $entry['payment_status'] ) ) : 'NULL';
 902: 
 903:         if ( empty( $entry['payment_date'] ) ) {
 904:             $payment_date          = null;
 905:             $entry['payment_date'] = $payment_date;
 906:         } else {
 907:             $payment_date = strtotime( $entry['payment_date'] );
 908:         }
 909:         $payment_date = $payment_date ? sprintf( "'%s'", esc_sql( gmdate( 'Y-m-d H:i:s', $payment_date ) ) ) : 'NULL';
 910: 
 911:         if ( ! isset( $entry['payment_amount'] ) ) {
 912:             $entry['payment_amount'] = null;
 913:         }
 914:         $payment_amount = ! empty( $entry['payment_amount'] ) ? (float) $entry['payment_amount'] : 'NULL';
 915: 
 916:         if ( ! isset( $entry['payment_method'] ) ) {
 917:             $entry['payment_method'] = '';
 918:         }
 919:         $payment_method = $entry['payment_method'];
 920: 
 921:         if ( ! isset( $entry['transaction_id'] ) ) {
 922:             $entry['transaction_id'] = null;
 923:         }
 924:         $transaction_id = ! empty( $entry['transaction_id'] ) ? sprintf( "'%s'", esc_sql( $entry['transaction_id'] ) ) : 'NULL';
 925: 
 926:         if ( ! isset( $entry['is_fulfilled'] ) ) {
 927:             $entry['is_fulfilled'] = null;
 928:         }
 929:         $is_fulfilled = ! empty( $entry['is_fulfilled'] ) ? intval( $entry['is_fulfilled'] ) : 'NULL';
 930: 
 931:         if ( empty( $entry['status'] ) ) {
 932:             $entry['status'] = 'active';
 933:         }
 934:         $status = $entry['status'];
 935: 
 936:         $user_id = isset( $entry['created_by'] ) ? absint( $entry['created_by'] ) : '';
 937:         if ( empty( $user_id ) ) {
 938:             global $current_user;
 939:             if ( $current_user && $current_user->ID ) {
 940:                 $user_id             = absint( $current_user->ID );
 941:                 $entry['created_by'] = $user_id;
 942:             } else {
 943:                 $user_id             = 'NULL';
 944:                 $entry['created_by'] = null;
 945:             }
 946:         }
 947: 
 948:         if ( ! isset( $entry['transaction_type'] ) ) {
 949:             $entry['transaction_type'] = null;
 950:         }
 951:         $transaction_type = ! empty( $entry['transaction_type'] ) ? intval( $entry['transaction_type'] ) : 'NULL';
 952: 
 953:         $entry_table = GFFormsModel::get_entry_table_name();
 954:         $sql = $wpdb->prepare(
 955:             "
 956:                 UPDATE $entry_table
 957:                 SET
 958:                 form_id = %d,
 959:                 post_id = {$post_id},
 960:                 date_created = {$date_created},
 961:                 date_updated = {$date_updated},
 962:                 is_starred = %d,
 963:                 is_read = %d,
 964:                 ip = %s,
 965:                 source_url = %s,
 966:                 user_agent = %s,
 967:                 currency = %s,
 968:                 payment_status = {$payment_status},
 969:                 payment_date = {$payment_date},
 970:                 payment_amount = {$payment_amount},
 971:                 transaction_id = {$transaction_id},
 972:                 is_fulfilled = {$is_fulfilled},
 973:                 created_by = {$user_id},
 974:                 transaction_type = {$transaction_type},
 975:                 status = %s,
 976:                 payment_method = %s
 977:                 WHERE
 978:                 id = %d
 979:                 ", $form_id, $is_starred, $is_read, $ip, $source_url, $user_agent, $currency, $status, $payment_method, $entry_id
 980:         );
 981:         $result     = $wpdb->query( $sql );
 982:         if ( false === $result ) {
 983:             return new WP_Error( 'update_entry_properties_failed', __( 'There was a problem while updating the entry properties', 'gravityforms' ), $wpdb->last_error );
 984:         }
 985: 
 986:         // Only save field values for fields that currently exist in the form. The rest in $entry will be ignored. The rest in $current_entry will get deleted.
 987: 
 988:         $entry_meta_table = GFFormsModel::get_entry_meta_table_name();
 989:         $current_fields    = $wpdb->get_results( $wpdb->prepare( "SELECT id, meta_key, item_index FROM $entry_meta_table WHERE entry_id=%d", $entry_id ) );
 990: 
 991:         $form = gf_apply_filters( array( 'gform_form_pre_update_entry', $form_id ), $form, $entry, $entry_id );
 992: 
 993:         GFFormsModel::begin_batch_field_operations();
 994: 
 995:         $has_product_field = false;
 996: 
 997:         foreach ( $form['fields'] as $field ) {
 998:             /* @var GF_Field $field */
 999:             $type = GFFormsModel::get_input_type( $field );
1000:             if ( in_array( $type, array( 'html', 'page', 'section' ) ) ) {
1001:                 continue;
1002:             }
1003: 
1004:             self::queue_batch_field_operation( $form, $entry, $field, '', $current_entry, $current_fields );
1005: 
1006:             if ( ! $has_product_field && GFCommon::is_product_field( $field->type ) ) {
1007:                 $has_product_field = true;
1008:             }
1009:         }
1010: 
1011:         // Save the entry meta values - only for the entry meta currently available for the form, ignore the rest.
1012:         $entry_meta = GFFormsModel::get_entry_meta( $form_id );
1013:         if ( is_array( $entry_meta ) ) {
1014:             foreach ( array_keys( $entry_meta ) as $key ) {
1015:                 if ( isset( $entry[ $key ] ) ) {
1016:                     if ( $entry[ $key ] != $current_entry[ $key ] ) {
1017:                         gform_update_meta( $entry_id, $key, $entry[ $key ] );
1018:                     }
1019:                     unset( $current_entry[ $key ] );
1020:                 }
1021:             }
1022:         }
1023: 
1024:         // Now delete remaining values from the old entry.
1025: 
1026:         if ( is_array( $entry_meta ) ) {
1027:             foreach ( array_keys( $entry_meta ) as $meta_key ) {
1028:                 if ( isset( $current_entry[ $meta_key ] ) ) {
1029:                     gform_delete_meta( $entry_id, $meta_key );
1030:                     unset( $current_entry[ $meta_key ] );
1031:                 }
1032:             }
1033:         }
1034: 
1035:         // Unset to prevent GFFormsModel::queue_batch_field_operation() setting them to empty strings in $entry during the next foreach.
1036:         $entry_columns = GFFormsModel::get_lead_db_columns();
1037:         foreach ( $entry_columns as $column ) {
1038:             unset( $current_entry[ $column ] );
1039:         }
1040: 
1041:         foreach ( $current_entry as $k => $v ) {
1042:             $lead_detail_id = GFFormsModel::get_lead_detail_id( $current_fields, $k );
1043:             $field          = self::get_field( $form, $k );
1044:             $result         = GFFormsModel::queue_batch_field_operation( $form, $entry, $field, $lead_detail_id, $k, '' );
1045:             if ( false === $result ) {
1046:                 return new WP_Error( 'update_field_values_failed', __( 'There was a problem while updating the field values', 'gravityforms' ), $wpdb->last_error );
1047:             }
1048:         }
1049: 
1050:         GFFormsModel::commit_batch_field_operations();
1051: 
1052:         if ( $has_product_field ) {
1053:             GFFormsModel::refresh_product_cache( $form, $entry );
1054:         }
1055: 
1056:         /**
1057:          * Fires after the Entry is updated.
1058:          *
1059:          * @since Unknown.
1060:          *
1061:          * @param array $lead           The entry object after being updated.
1062:          * @param array $original_entry The entry object before being updated.
1063:          */
1064:         gf_do_action( array( 'gform_post_update_entry', $form_id ), $entry, $original_entry );
1065: 
1066:         return true;
1067:     }
1068: 
1069:     private static function queue_batch_field_operation( $form, $entry, $field, $item_index = '', &$current_entry = array(), $current_fields = array() ) {
1070: 
1071:         if ( is_array( $field->fields ) ) {
1072:             $field_id = (string) $field->id;
1073:             if ( isset( $entry[ $field_id ] ) && is_array( $entry[ $field_id ] ) ) {
1074:                 foreach ( $entry[ $field_id ] as $i => $values ) {
1075:                     $new_item_index = $item_index . '_' . $i;
1076:                     $values['id']   = $entry['id'];
1077:                     foreach ( $field->fields as $sub_field ) {
1078:                         self::queue_batch_field_operation( $form, $values, $sub_field, $new_item_index, $current_entry[ $field_id ], $current_fields );
1079:                     }
1080:                 }
1081:             }
1082: 
1083:             foreach ( $field->fields as $sub_field ) {
1084:                 foreach ( $current_fields as $current_field ) {
1085:                     if ( intval( $current_field->meta_key ) == $sub_field->id && ! isset( $current_field->update ) ) {
1086:                         $current_field->delete = true;
1087:                         $result = GFFormsModel::queue_batch_field_operation( $form, $entry, $sub_field, $current_field->id, $current_field->meta_key, '', $current_field->item_index );
1088:                         GFCommon::log_debug( __METHOD__ . "(): Deleting: {$field->label}(#{$sub_field->id}{$current_field->item_index} - {$field->type}). Result: " . var_export( $result, 1 ) );
1089:                     }
1090:                 }
1091:             }
1092:         }
1093: 
1094:         $inputs = $field->get_entry_inputs();
1095:         if ( is_array( $inputs ) ) {
1096:             foreach ( $field->inputs as $input ) {
1097:                 $input_id = (string) $input['id'];
1098:                 $input_value = isset( $entry[ (string) $input_id ] ) ? $entry[ (string) $input_id ] : '';
1099:                 $current_value = isset( $current_entry[ (string) $input_id ] ) ? $current_entry[ (string) $input_id ] : '';
1100:                 if ( empty( $current_entry ) || $input_value != $current_value ) {
1101:                     $lead_detail_id = $current_fields ? GFFormsModel::get_lead_detail_id( $current_fields, $input_id, $item_index ) : 0;
1102:                     $result         = GFFormsModel::queue_batch_field_operation( $form, $entry, $field, $lead_detail_id, $input_id, $input_value, $item_index );
1103:                     if ( false === $result ) {
1104:                         return new WP_Error( 'update_input_value_failed', __( 'There was a problem while updating one of the input values for the entry', 'gravityforms' ) );
1105:                     }
1106:                     foreach ( $current_fields as $current_field ) {
1107:                         if ( $current_field->meta_key == $input_id && $current_field->item_index == $item_index ) {
1108:                             $current_field->update = true;
1109:                         }
1110:                     }
1111:                 }
1112: 
1113:                 unset( $current_entry[ $input_id ] );
1114:             }
1115: 
1116:         } else {
1117:             $field_id    = (string) $field->id;
1118:             $field_value = isset( $entry[ (string) $field_id ] ) ? $entry[ (string) $field_id ] : '';
1119:             $current_value = isset( $current_entry[ (string) $field_id ] ) ? $current_entry[ (string) $field_id ] : '';
1120:             if ( empty( $current_entry ) || $field_value != $current_value ) {
1121:                 $lead_detail_id = $current_fields ? GFFormsModel::get_lead_detail_id( $current_fields, $field_id ) : 0;
1122:                 $result         = GFFormsModel::queue_batch_field_operation( $form, $entry, $field, $lead_detail_id, $field_id, $field_value, $item_index );
1123:                 if ( false === $result ) {
1124:                     return new WP_Error( 'update_field_values_failed', __( 'There was a problem while updating the field values', 'gravityforms' ) );
1125:                 }
1126:                 foreach ( $current_fields as $current_field ) {
1127:                     if ( $current_field->meta_key == $field_id && $current_field->item_index == $item_index ) {
1128:                         $current_field->update = true;
1129:                     }
1130:                 }
1131:             }
1132:             unset( $current_entry[ $field_id ] );
1133:         }
1134: 
1135:         return $current_entry;
1136:     }
1137: 
1138:     /**
1139:      * Adds a single Entry object.
1140:      *
1141:      * Intended to be used for importing an entry object. The usual hooks that are triggered while saving entries are not fired here.
1142:      * Checks that the form id, field ids and entry meta exist and ignores legacy values (i.e. values for fields that no longer exist).
1143:      *
1144:      * @since  1.8
1145:      * @access public
1146:      * @global $wpdb
1147:      * @global $current_user
1148:      *
1149:      * @uses GFAPI::form_id_exists()
1150:      * @uses GFFormsModel::get_ip()
1151:      * @uses GFFormsModel::get_current_page_url()
1152:      * @uses GFCommon::get_currency()
1153:      * @uses GFFormsModel::get_lead_table_name()
1154:      * @uses GF_Field::get_entry_inputs()
1155:      * @uses GFFormsModel::update_lead_field_value()
1156:      * @uses GFFormsModel::get_entry_meta()
1157:      * @uses GFAPI::get_entry()
1158:      *
1159:      * @param array $entry The Entry Object.
1160:      *
1161:      * @return int|WP_Error Either the new Entry ID or a WP_Error instance.
1162:      */
1163:     public static function add_entry( $entry ) {
1164:         global $wpdb;
1165: 
1166:         if ( gf_upgrade()->get_submissions_block() ) {
1167:             return new WP_Error( 'submissions_blocked', __( 'Submissions are currently blocked due to an upgrade in progress', 'gravityforms' ) );
1168:         }
1169: 
1170:         if ( version_compare( GFFormsModel::get_database_version(), '2.3-dev-1', '<' ) ) {
1171:             return GF_Forms_Model_Legacy::add_entry( $entry );
1172:         }
1173: 
1174:         if ( ! is_array( $entry ) ) {
1175:             return new WP_Error( 'invalid_entry_object', __( 'The entry object must be an array', 'gravityforms' ) );
1176:         }
1177: 
1178:         // Make sure the form id exists.
1179:         $form_id = rgar( $entry, 'form_id' );
1180:         if ( empty( $form_id ) ) {
1181:             return new WP_Error( 'empty_form_id', __( 'The form id must be specified', 'gravityforms' ) );
1182:         }
1183: 
1184:         if ( false === self::form_id_exists( $form_id ) ) {
1185:             return new WP_Error( 'invalid_form_id', __( 'The form for this entry does not exist', 'gravityforms' ) );
1186:         }
1187: 
1188:         $form = GFFormsModel::get_form_meta( $form_id );
1189: 
1190:         // Use values in the entry object if present
1191:         $post_id        = isset( $entry['post_id'] ) ? intval( $entry['post_id'] ) : 'NULL';
1192:         $date_created   = isset( $entry['date_created'] ) && $entry['date_created'] != '' ? sprintf( "'%s'", esc_sql( $entry['date_created'] ) ) : 'utc_timestamp()';
1193:         $date_updated   = isset( $entry['date_updated'] ) && $entry['date_updated'] != '' ? sprintf( "'%s'", esc_sql( $entry['date_updated'] ) ) : 'utc_timestamp()';
1194:         $is_starred     = isset( $entry['is_starred'] ) ? $entry['is_starred'] : 0;
1195:         $is_read        = isset( $entry['is_read'] ) ? $entry['is_read'] : 0;
1196:         $request_ip     = rgars( $form, 'personalData/preventIP' ) ? '' : GFFormsModel::get_ip();
1197:         $ip             = isset( $entry['ip'] ) ? $entry['ip'] : $request_ip;
1198:         $source_url     = isset( $entry['source_url'] ) ? $entry['source_url'] : esc_url_raw( GFFormsModel::get_current_page_url() );
1199:         $user_agent     = isset( $entry['user_agent'] ) ? $entry['user_agent'] : 'API';
1200:         $currency       = isset( $entry['currency'] ) ? $entry['currency'] : GFCommon::get_currency();
1201:         $payment_status = isset( $entry['payment_status'] ) ? sprintf( "'%s'", esc_sql( $entry['payment_status'] ) ) : 'NULL';
1202:         $payment_date   = strtotime( rgar( $entry, 'payment_date' ) ) ? sprintf( "'%s'", gmdate( 'Y-m-d H:i:s', strtotime( "{$entry['payment_date']}" ) ) ) : 'NULL';
1203:         $payment_amount = isset( $entry['payment_amount'] ) ? (float) $entry['payment_amount'] : 'NULL';
1204:         $payment_method = isset( $entry['payment_method'] ) ? $entry['payment_method'] : '';
1205:         $transaction_id = isset( $entry['transaction_id'] ) ? sprintf( "'%s'", esc_sql( $entry['transaction_id'] ) ) : 'NULL';
1206:         $is_fulfilled   = isset( $entry['is_fulfilled'] ) ? intval( $entry['is_fulfilled'] ) : 'NULL';
1207:         $status         = isset( $entry['status'] ) ? $entry['status'] : 'active';
1208: 
1209:         global $current_user;
1210:         $user_id = isset( $entry['created_by'] ) ? absint( $entry['created_by'] ) : '';
1211:         if ( empty( $user_id ) ) {
1212:             $user_id = $current_user && $current_user->ID ? absint( $current_user->ID )  : 'NULL';
1213:         }
1214: 
1215:         $transaction_type = isset( $entry['transaction_type'] ) ? intval( $entry['transaction_type'] ) : 'NULL';
1216: 
1217:         $entry_table = GFFormsModel::get_entry_table_name();
1218:         $result     = $wpdb->query(
1219:             $wpdb->prepare(
1220:                 "
1221:                 INSERT INTO $entry_table
1222:                 (form_id, post_id, date_created, date_updated, is_starred, is_read, ip, source_url, user_agent, currency, payment_status, payment_date, payment_amount, transaction_id, is_fulfilled, created_by, transaction_type, status, payment_method)
1223:                 VALUES
1224:                 (%d, {$post_id}, {$date_created}, {$date_updated}, %d,  %d, %s, %s, %s, %s, {$payment_status}, {$payment_date}, {$payment_amount}, {$transaction_id}, {$is_fulfilled}, {$user_id}, {$transaction_type}, %s, %s)
1225:                 ", $form_id, $is_starred, $is_read, $ip, $source_url, $user_agent, $currency, $status, $payment_method
1226:             )
1227:         );
1228:         if ( false === $result ) {
1229:             return new WP_Error( 'insert_entry_properties_failed', __( 'There was a problem while inserting the entry properties', 'gravityforms' ), $wpdb->last_error );
1230:         }
1231:         // Reading newly created lead id.
1232:         $entry_id    = $wpdb->insert_id;
1233:         $entry['id'] = $entry_id;
1234: 
1235:         // only save field values for fields that currently exist in the form
1236:         GFFormsModel::begin_batch_field_operations();
1237: 
1238:         foreach ( $form['fields'] as $field ) {
1239:             /* @var GF_Field $field */
1240:             if ( in_array( $field->type, array( 'html', 'page', 'section' ) ) ) {
1241:                 continue;
1242:             }
1243:             self::queue_batch_field_operation( $form, $entry, $field );
1244:         }
1245: 
1246:         GFFormsModel::commit_batch_field_operations();
1247: 
1248:         // add save the entry meta values - only for the entry meta currently available for the form, ignore the rest
1249:         $entry_meta = GFFormsModel::get_entry_meta( $form_id );
1250:         if ( is_array( $entry_meta ) ) {
1251:             foreach ( array_keys( $entry_meta ) as $key ) {
1252:                 if ( isset( $entry[ $key ] ) ) {
1253:                     gform_update_meta( $entry_id, $key, $entry[ $key ], $form['id'] );
1254:                 }
1255:             }
1256:         }
1257: 
1258:         // Refresh the entry
1259:         $entry = GFAPI::get_entry( $entry['id'] );
1260: 
1261:         /**
1262:          * Fires after the Entry is added using the API.
1263:          *
1264:          * @since  1.9.14.26
1265:          *
1266:          * @param array $entry The Entry Object added.
1267:          * @param array $form  The Form Object added.
1268:          */
1269:         do_action( 'gform_post_add_entry', $entry, $form );
1270: 
1271:         return $entry_id;
1272:     }
1273: 
1274:     /**
1275:      * Deletes a single Entry.
1276:      *
1277:      * @since  1.8
1278:      * @access public
1279:      *
1280:      * @uses GFFormsModel::get_lead()
1281:      * @uses GFFormsModel::delete_lead()
1282:      *
1283:      * @param int $entry_id The ID of the Entry object.
1284:      *
1285:      * @return bool|WP_Error Either true for success or a WP_Error instance.
1286:      */
1287:     public static function delete_entry( $entry_id ) {
1288: 
1289:         if ( gf_upgrade()->get_submissions_block() ) {
1290:             return new WP_Error( 'submissions_blocked', __( 'Submissions are currently blocked due to an upgrade in progress', 'gravityforms' ) );
1291:         }
1292: 
1293:         $entry = GFFormsModel::get_entry( $entry_id );
1294:         if ( empty( $entry ) ) {
1295:             return new WP_Error( 'invalid_entry_id', sprintf( __( 'Invalid entry id: %s', 'gravityforms' ), $entry_id ), $entry_id );
1296:         }
1297:         GFFormsModel::delete_entry( $entry_id );
1298: 
1299:         return true;
1300:     }
1301: 
1302:     /**
1303:      * Updates a single property of an entry.
1304:      *
1305:      * @since  1.8.3.1
1306:      * @access public
1307:      *
1308:      * @uses GFFormsModel::update_lead_property()
1309:      *
1310:      * @param int    $entry_id The ID of the Entry object.
1311:      * @param string $property The property of the Entry object to be updated.
1312:      * @param mixed  $value    The value to which the property should be set.
1313:      *
1314:      * @return bool Whether the entry property was updated successfully.
1315:      */
1316:     public static function update_entry_property( $entry_id, $property, $value ) {
1317:         if ( gf_upgrade()->get_submissions_block() ) {
1318:             return false;
1319:         }
1320:         return GFFormsModel::update_entry_property( $entry_id, $property, $value );
1321:     }
1322: 
1323:     /**
1324:      * Updates a single field of an entry.
1325:      *
1326:      * @since  1.9
1327:      * @access public
1328:      *
1329:      * @param int    $entry_id   The ID of the Entry object.
1330:      * @param string $input_id   The id of the input to be updated. For single input fields such as text, paragraph,
1331:      *                           website, drop down etc... this will be the same as the field ID. For multi input
1332:      *                           fields such as name, address, checkboxes, etc... the input id will be in the format
1333:      *                           {FIELD_ID}.{INPUT NUMBER}. ( i.e. "1.3" ). The $input_id can be obtained by inspecting
1334:      *                           the key for the specified field in the $entry object.
1335:      * @param mixed  $value      The value to which the field should be set.
1336:      * @param string $item_index The item index if the field is inside a Repeater.
1337:      *
1338:      * @return bool|array Whether the entry property was updated successfully. If there's an error getting the entry,
1339:      *                    the entry object.
1340:      */
1341:     public static function update_entry_field( $entry_id, $input_id, $value, $item_index = '' ) {
1342:         global $wpdb;
1343: 
1344:         if ( gf_upgrade()->get_submissions_block() ) {
1345:             return false;
1346:         }
1347: 
1348:         if ( version_compare( GFFormsModel::get_database_version(), '2.3-dev-1', '<' ) ) {
1349:             return GF_Forms_Model_Legacy::update_entry_field( $entry_id, $input_id, $value );
1350:         }
1351: 
1352:         $entry = self::get_entry( $entry_id );
1353:         if ( is_wp_error( $entry ) ) {
1354:             return $entry;
1355:         }
1356: 
1357:         $form = self::get_form( $entry['form_id'] );
1358:         if ( ! $form ) {
1359:             return false;
1360:         }
1361: 
1362:         $field = self::get_field( $form, $input_id );
1363: 
1364:         $entry_meta_table_name = GFFormsModel::get_entry_meta_table_name();
1365: 
1366:         $sql = $wpdb->prepare( "SELECT id FROM {$entry_meta_table_name} WHERE entry_id=%d AND meta_key=%s", $entry_id, $input_id );
1367: 
1368:         if ( $item_index ) {
1369:             $sql .= $wpdb->prepare( ' AND item_index=%s', $item_index );
1370:         }
1371: 
1372:         $lead_detail_id = $wpdb->get_var( $sql );
1373: 
1374:         $result = true;
1375:         if ( ! isset( $entry[ $input_id ] ) || $entry[ $input_id ] != $value ) {
1376:             $result = GFFormsModel::update_entry_field_value( $form, $entry, $field, $lead_detail_id, $input_id, $value, $item_index );
1377:         }
1378: 
1379:         return $result;
1380:     }
1381: 
1382:     // FORM SUBMISSIONS -------------------------------------------
1383: 
1384:     /**
1385:      * Submits a form. Use this function to send input values through the complete form submission process.
1386:      * Supports field validation, notifications, confirmations, multiple-pages and save & continue.
1387:      *
1388:      * Example usage:
1389:      * $input_values['input_1']   = 'Single line text';
1390:      * $input_values['input_2_3'] = 'First name';
1391:      * $input_values['input_2_6'] = 'Last name';
1392:      * $input_values['input_5']   = 'A paragraph of text.';
1393:      * //$input_values['gform_save'] = true; // support for save and continue
1394:      *
1395:      * $result = GFAPI::submit_form( 52, $input_values );
1396:      *
1397:      * Example output for a successful submission:
1398:      * 'is_valid' => boolean true
1399:      * 'page_number' => int 0
1400:      * 'source_page_number' => int 1
1401:      * 'confirmation_message' => string 'confirmation message [snip]'
1402:      *
1403:      * Example output for failed validation:
1404:      * 'is_valid' => boolean false
1405:      * 'validation_messages' =>
1406:      *      array (size=1)
1407:      *          2 => string 'This field is required. Please enter the first and last name.'
1408:      *  'page_number' => int 1
1409:      *  'source_page_number' => int 1
1410:      *  'confirmation_message' => string ''
1411:      *
1412:      *
1413:      * Example output for save and continue:
1414:      * 'is_valid' => boolean true
1415:      * 'page_number' => int 1
1416:      * 'source_page_number' => int 1
1417:      * 'confirmation_message' => string 'Please use the following link to return to your form from any computer. [snip]'
1418:      * 'resume_token' => string '045f941cc4c04d479556bab1db6d3495'
1419:      *
1420:      * @since  Unknown
1421:      * @access public
1422:      *
1423:      * @uses GFAPI::get_form()
1424:      * @uses GFCommon::get_base_path()
1425:      * @uses GFFormDisplay::process_form()
1426:      * @uses GFFormDisplay::replace_save_variables()
1427:      *
1428:      * @param int $form_id The Form ID
1429:      * @param array $input_values An array of values. Not $_POST, that will be automatically merged with the $input_values.
1430:      * @param array $field_values Optional.
1431:      * @param int $target_page Optional.
1432:      * @param int $source_page Optional.
1433:      *
1434:      * @return array|WP_Error An array containing the result of the submission.
1435:      */
1436:     public static function submit_form( $form_id, $input_values, $field_values = array(), $target_page = 0, $source_page = 1 ) {
1437: 
1438:         if ( gf_upgrade()->get_submissions_block() ) {
1439:             return new WP_Error( 'submissions_blocked', __( 'Submissions are currently blocked due to an upgrade in progress', 'gravityforms' ) );
1440:         }
1441: 
1442:         $form_id = absint( $form_id );
1443:         $form    = GFAPI::get_form( $form_id );
1444: 
1445:         if ( empty( $form ) || ! $form['is_active'] || $form['is_trash'] ) {
1446:             return new WP_Error( 'form_not_found', __( 'Your form could not be found', 'gravityforms' ) );
1447:         }
1448: 
1449:         $input_values[ 'is_submit_' . $form_id ]                = true;
1450:         $input_values['gform_submit']                           = $form_id;
1451:         $input_values[ 'gform_target_page_number_' . $form_id ] = absint( $target_page );
1452:         $input_values[ 'gform_source_page_number_' . $form_id ] = absint( $source_page );
1453:         $input_values['gform_field_values']                     = $field_values;
1454: 
1455: 
1456:         require_once( GFCommon::get_base_path() . '/form_display.php' );
1457: 
1458:         if ( ! isset( $_POST ) ) {
1459:             $_POST = array();
1460:         }
1461: 
1462:         $_POST = array_merge_recursive( $_POST, $input_values );
1463: 
1464:         // Ensure that confirmation handler doesn't send a redirect header or add redirect JavaScript.
1465:         add_filter( 'gform_suppress_confirmation_redirect', '__return_true' );
1466: 
1467:         try {
1468:             GFFormDisplay::process_form( $form_id );
1469:         } catch ( Exception $ex ) {
1470:             remove_filter( 'gform_suppress_confirmation_redirect', '__return_true' );
1471:             return new WP_Error( 'error_processing_form', __( 'There was an error while processing the form:', 'gravityforms' ) . ' ' . $ex->getCode() . ' ' . $ex->getMessage() );
1472:         }
1473: 
1474:         remove_filter( 'gform_suppress_confirmation_redirect', '__return_true' );
1475: 
1476:         if ( empty( GFFormDisplay::$submission ) ) {
1477:             return new WP_Error( 'error_processing_form', __( 'There was an error while processing the form:', 'gravityforms' ) );
1478:         }
1479: 
1480:         $submissions_array = GFFormDisplay::$submission;
1481: 
1482:         $submission_details = $submissions_array[ $form_id ];
1483: 
1484:         $result = array();
1485: 
1486:         $result['is_valid'] = $submission_details['is_valid'];
1487: 
1488:         if ( $result['is_valid'] == false ) {
1489:             $validation_messages = array();
1490:             foreach ( $submission_details['form']['fields'] as $field ) {
1491:                 if ( $field->failed_validation ) {
1492:                     $validation_messages[ $field->id ] = $field->validation_message;
1493:                 }
1494:             }
1495:             $result['validation_messages'] = $validation_messages;
1496:         }
1497: 
1498:         $result['page_number']          = $submission_details['page_number'];
1499:         $result['source_page_number']   = $submission_details['source_page_number'];
1500: 
1501:         if ( $submission_details['is_valid'] ) {
1502:             $confirmation_message = $submission_details['confirmation_message'];
1503: 
1504:             if ( is_array( $confirmation_message ) ) {
1505:                 if ( isset( $confirmation_message['redirect'] ) ) {
1506:                     $result['confirmation_message'] = '';
1507:                     $result['confirmation_redirect'] = $confirmation_message['redirect'];
1508:                     $result['confirmation_type'] = 'redirect';
1509:                 } else {
1510:                     $result['confirmation_message'] = $confirmation_message;
1511:                 }
1512:             } else {
1513:                 $result['confirmation_message'] = $confirmation_message;
1514:                 $result['confirmation_type'] = 'message';
1515:             }
1516: 
1517:             $result['entry_id'] = rgars( $submission_details, 'lead/id' );
1518:         }
1519: 
1520:         if ( isset( $submission_details['resume_token'] ) ) {
1521:             $result['resume_token'] = $submission_details['resume_token'];
1522: 
1523:             $form = self::get_form( $form_id );
1524: 
1525:             $result['confirmation_message'] = GFFormDisplay::replace_save_variables( $result['confirmation_message'], $form, $result['resume_token'] );
1526:         }
1527: 
1528:         return $result;
1529:     }
1530: 
1531:     // FEEDS ------------------------------------------------------
1532: 
1533:     /**
1534:      * Returns all the feeds for the given criteria.
1535:      *
1536:      * @since  1.8
1537:      * @access public
1538:      * @global $wpdb
1539:      *
1540:      * @param mixed  $feed_ids   The ID of the Feed or an array of Feed IDs.
1541:      * @param int    $form_id    The ID of the Form to which the Feeds belong.
1542:      * @param string $addon_slug The slug of the add-on to which the Feeds belong.
1543:      * @param bool   $is_active  If the feed is active.
1544:      *
1545:      * @return array|WP_Error Either an array of Feed objects or a WP_Error instance.
1546:      */
1547:     public static function get_feeds( $feed_ids = null, $form_id = null, $addon_slug = null, $is_active = true ) {
1548:         global $wpdb;
1549: 
1550:         $table       = $wpdb->prefix . 'gf_addon_feed';
1551:         $where_arr   = array();
1552:         $where_arr[] = $wpdb->prepare( 'is_active=%d', $is_active );
1553:         if ( false === empty( $form_id ) ) {
1554:             $where_arr[] = $wpdb->prepare( 'form_id=%d', $form_id );
1555:         }
1556:         if ( false === empty( $addon_slug ) ) {
1557:             $where_arr[] = $wpdb->prepare( 'addon_slug=%s', $addon_slug );
1558:         }
1559:         if ( false === empty( $feed_ids ) ) {
1560:             if ( ! is_array( $feed_ids ) ) {
1561:                 $feed_ids = array( $feed_ids );
1562:             }
1563:             $in_str_arr  = array_fill( 0, count( $feed_ids ), '%d' );
1564:             $in_str      = join( $in_str_arr, ',' );
1565:             $where_arr[] = $wpdb->prepare( "id IN ($in_str)", $feed_ids );
1566:         }
1567: 
1568: 
1569:         $where = join( ' AND ', $where_arr );
1570: 
1571:         $sql = "SELECT id, form_id, addon_slug, meta FROM {$table} WHERE $where";
1572: 
1573:         $results = $wpdb->get_results( $sql, ARRAY_A );
1574:         if ( empty( $results ) ) {
1575:             return new WP_Error( 'not_found', __( 'Feed not found', 'gravityforms' ) );
1576:         }
1577: 
1578:         foreach ( $results as &$result ) {
1579:             $result['meta'] = json_decode( $result['meta'], true );
1580:         }
1581: 
1582:         return $results;
1583:     }
1584: 
1585:     /**
1586:      * Deletes a single Feed.
1587:      *
1588:      * @since  1.8
1589:      * @access public
1590:      * @global $wpdb
1591:      *
1592:      * @param int $feed_id The ID of the Feed to delete.
1593:      *
1594:      * @return bool|WP_Error True if successful, or a WP_Error instance.
1595:      */
1596:     public static function delete_feed( $feed_id ) {
1597:         global $wpdb;
1598: 
1599:         if ( gf_upgrade()->get_submissions_block() ) {
1600:             return new WP_Error( 'submissions_blocked', __( 'Submissions are currently blocked due to an upgrade in progress', 'gravityforms' ) );
1601:         }
1602: 
1603:         $table = $wpdb->prefix . 'gf_addon_feed';
1604: 
1605:         $sql = $wpdb->prepare( "DELETE FROM {$table} WHERE id=%d", $feed_id );
1606: 
1607:         $results = $wpdb->query( $sql );
1608:         if ( false === $results ) {
1609:             return new WP_Error( 'error_deleting', sprintf( __( 'There was an error while deleting feed id %s', 'gravityforms' ), $feed_id ), $wpdb->last_error );
1610:         }
1611: 
1612:         if ( 0 === $results ) {
1613:             return new WP_Error( 'not_found', sprintf( __( 'Feed id %s not found', 'gravityforms' ), $feed_id ) );
1614:         }
1615: 
1616:         return true;
1617:     }
1618: 
1619:     /**
1620:      * Updates a feed.
1621:      *
1622:      * @param int   $feed_id   The ID of the feed being updated.
1623:      * @param array $feed_meta The feed meta to replace the existing feed meta.
1624:      * @param null  $form_id   The ID of the form that the feed is associated with
1625:      *
1626:      * @return int|WP_Error The number of rows updated or a WP_Error instance
1627:      */
1628:     public static function update_feed( $feed_id, $feed_meta, $form_id = null ) {
1629:         global $wpdb;
1630: 
1631:         if ( gf_upgrade()->get_submissions_block() ) {
1632:             return new WP_Error( 'submissions_blocked', __( 'Submissions are currently blocked due to an upgrade in progress', 'gravityforms' ) );
1633:         }
1634: 
1635:         $lookup_result = self::get_feeds( $feed_id, $form_id );
1636: 
1637:         if ( is_wp_error( $lookup_result ) ) {
1638:             return $lookup_result;
1639:         }
1640: 
1641:         $feed_meta_json = json_encode( $feed_meta );
1642:         $table          = $wpdb->prefix . 'gf_addon_feed';
1643:         if ( empty( $form_id ) ) {
1644:             $sql = $wpdb->prepare( "UPDATE {$table} SET meta= %s WHERE id=%d", $feed_meta_json, $feed_id );
1645:         } else {
1646:             $sql = $wpdb->prepare( "UPDATE {$table} SET form_id = %d, meta= %s WHERE id=%d", $form_id, $feed_meta_json, $feed_id );
1647:         }
1648: 
1649:         $results = $wpdb->query( $sql );
1650: 
1651:         if ( false === $results ) {
1652:             return new WP_Error( 'error_updating', sprintf( __( 'There was an error while updating feed id %s', 'gravityforms' ), $feed_id ), $wpdb->last_error );
1653:         }
1654: 
1655:         return $results;
1656:     }
1657: 
1658:     /**
1659:      * Adds a feed with the given Feed object.
1660:      *
1661:      * @since  1.8
1662:      * @access public
1663:      * @global $wpdb
1664:      *
1665:      * @param int    $form_id    The ID of the form to which the feed belongs.
1666:      * @param array  $feed_meta  The Feed Object.
1667:      * @param string $addon_slug The slug of the add-on to which the feeds belong.
1668:      *
1669:      * @return int|WP_Error Either the ID of the newly created feed or a WP_Error instance.
1670:      */
1671:     public static function add_feed( $form_id, $feed_meta, $addon_slug ) {
1672:         global $wpdb;
1673: 
1674:         if ( gf_upgrade()->get_submissions_block() ) {
1675:             return new WP_Error( 'submissions_blocked', __( 'Submissions are currently blocked due to an upgrade in progress', 'gravityforms' ) );
1676:         }
1677: 
1678:         $table          = $wpdb->prefix . 'gf_addon_feed';
1679:         $feed_meta_json = json_encode( $feed_meta );
1680:         $sql            = $wpdb->prepare( "INSERT INTO {$table} (form_id, meta, addon_slug) VALUES (%d, %s, %s)", $form_id, $feed_meta_json, $addon_slug );
1681: 
1682:         $results = $wpdb->query( $sql );
1683: 
1684:         if ( false === $results ) {
1685:             return new WP_Error( 'error_inserting', __( 'There was an error while inserting a feed', 'gravityforms' ), $wpdb->last_error );
1686:         }
1687: 
1688:         return $wpdb->insert_id;
1689:     }
1690: 
1691:     // NOTIFICATIONS ----------------------------------------------
1692: 
1693:     /**
1694:      * Sends all active notifications for a form given an entry object and an event.
1695:      *
1696:      * @since  Unknown
1697:      * @access public
1698:      *
1699:      * @uses GFCommon::log_debug()
1700:      * @uses GFCommon::send_notifications()
1701:      *
1702:      * @param array  $form  The Form Object associated with the notification.
1703:      * @param array  $entry The Entry Object associated with the triggered event.
1704:      * @param string $event Optional. The event that's firing the notification. Defaults to 'form_submission'.
1705:      * @param array  $data  Optional. Array of data which can be used in the notifications via the generic {object:property} merge tag. Defaults to empty array.
1706:      *
1707:      * @return array The array of notification IDs sent.
1708:      */
1709:     public static function send_notifications( $form, $entry, $event = 'form_submission', $data = array() ) {
1710: 
1711:         if ( rgempty( 'notifications', $form ) || ! is_array( $form['notifications'] ) ) {
1712:             return array();
1713:         }
1714: 
1715:         $entry_id = rgar( $entry, 'id' );
1716:         GFCommon::log_debug( "GFAPI::send_notifications(): Gathering notifications for {$event} event for entry #{$entry_id}." );
1717: 
1718:         $notifications_to_send = array();
1719: 
1720:         // Running through filters that disable form submission notifications.
1721:         foreach ( $form['notifications'] as $notification ) {
1722:             if ( rgar( $notification, 'event' ) != $event ) {
1723:                 continue;
1724:             }
1725: 
1726:             if ( $event == 'form_submission' ) {
1727:                 /**
1728:                  * Disables user notifications.
1729:                  *
1730:                  * @since Unknown
1731:                  *
1732:                  * @param bool  false  Determines if the notification will be disabled. Set to true to disable the notification.
1733:                  * @param array $form  The Form Object that triggered the notification event.
1734:                  * @param array $entry The Entry Object that triggered the notification event.
1735:                  */
1736:                 if ( rgar( $notification, 'type' ) == 'user' && gf_apply_filters( array( 'gform_disable_user_notification', $form['id'] ), false, $form, $entry ) ) {
1737:                     GFCommon::log_debug( "GFAPI::send_notifications(): Notification is disabled by gform_disable_user_notification hook, not including notification (#{$notification['id']} - {$notification['name']})." );
1738:                     // Skip user notification if it has been disabled by a hook.
1739:                     continue;
1740:                     /**
1741:                      * Disables admin notifications.
1742:                      *
1743:                      * @since Unknown
1744:                      *
1745:                      * @param bool  false  Determines if the notification will be disabled. Set to true to disable the notification.
1746:                      * @param array $form  The Form Object that triggered the notification event.
1747:                      * @param array $entry The Entry Object that triggered the notification event.
1748:                      */
1749:                 } elseif ( rgar( $notification, 'type' ) == 'admin' && gf_apply_filters( array( 'gform_disable_admin_notification', $form['id'] ), false, $form, $entry ) ) {
1750:                     GFCommon::log_debug( "GFAPI::send_notifications(): Notification is disabled by gform_disable_admin_notification hook, not including notification (#{$notification['id']} - {$notification['name']})." );
1751:                     // Skip admin notification if it has been disabled by a hook.
1752:                     continue;
1753:                 }
1754:             }
1755: 
1756:             /**
1757:              * Disables notifications.
1758:              *
1759:              * @since 2.3.6.6 Added the $data param.
1760:              * @since Unknown
1761:              *
1762:              * @param bool  false  Determines if the notification will be disabled. Set to true to disable the notification.
1763:              * @param array $form  The Form Object that triggered the notification event.
1764:              * @param array $entry The Entry Object that triggered the notification event.
1765:              * @param array $data  Array of data which can be used in the notifications via the generic {object:property} merge tag. Defaults to empty array.
1766:              */
1767:             if ( gf_apply_filters( array( 'gform_disable_notification', $form['id'] ), false, $notification, $form, $entry, $data ) ) {
1768:                 GFCommon::log_debug( "GFAPI::send_notifications(): Notification is disabled by gform_disable_notification hook, not including notification (#{$notification['id']} - {$notification['name']})." );
1769:                 // Skip notifications if it has been disabled by a hook
1770:                 continue;
1771:             }
1772: 
1773:             $notifications_to_send[] = $notification['id'];
1774:         }
1775: 
1776:         GFCommon::send_notifications( $notifications_to_send, $form, $entry, true, $event, $data );
1777: 
1778:         return $notifications_to_send;
1779:     }
1780: 
1781: 
1782:     // PERMISSIONS ------------------------------------------------
1783:     /**
1784:      * Checks the permissions for the current user. Returns true if the current user has any of the specified capabilities.
1785:      *
1786:      * IMPORTANT: Call this before calling any of the other API Functions as permission checks are not performed at lower levels.
1787:      *
1788:      * @since  1.8.5.10
1789:      * @access public
1790:      *
1791:      * @uses GFCommon::current_user_can_any()
1792:      *
1793:      * @param array|string $capabilities An array of capabilities, or a single capability
1794:      *
1795:      * @return bool Returns true if the current user has any of the specified capabilities
1796:      */
1797:     public static function current_user_can_any( $capabilities ) {
1798:         return GFCommon::current_user_can_any( $capabilities );
1799:     }
1800: 
1801:     // FIELDS -----------------------------------------------------
1802: 
1803:     /**
1804:      * Returns an array containing the form fields of the specified type or types.
1805:      *
1806:      * @since  1.9.9.8
1807:      * @access public
1808:      *
1809:      * @param array        $form           The Form Object.
1810:      * @param array|string $types          The field types to get. Multiple field types as an array or a single type in a string.
1811:      * @param bool         $use_input_type Optional. Defaults to false.
1812:      *
1813:      * @uses GFFormsModel::get_fields_by_type()
1814:      *
1815:      * @return GF_Field[]
1816:      */
1817:     public static function get_fields_by_type( $form, $types, $use_input_type = false ) {
1818:         return GFFormsModel::get_fields_by_type( $form, $types, $use_input_type );
1819:     }
1820: 
1821:     /**
1822:      * Returns the field object for the requested field or input ID from the supplied or specified form.
1823:      *
1824:      * @since  2.3
1825:      * @access public
1826:      *
1827:      * @param array|int  $form_or_id The Form Object or ID.
1828:      * @param string|int $field_id   The field or input ID.
1829:      *
1830:      * @uses   GFFormsModel::get_field()
1831:      *
1832:      * @return GF_Field|false
1833:      */
1834:     public static function get_field( $form_or_id, $field_id ) {
1835:         $field = GFFormsModel::get_field( $form_or_id, $field_id );
1836: 
1837:         return $field ? $field : false;
1838:     }
1839: 
1840:     // HELPERS ----------------------------------------------------
1841: 
1842:     /**
1843:      * Checks whether a form ID exists.
1844:      *
1845:      * @since  1.8
1846:      */
1847:     public static function form_id_exists( $form_id ) {
1848:         global $wpdb;
1849:         $form_table_name = GFFormsModel::get_form_table_name();
1850:         $form_id         = intval( $form_id );
1851:         $result          = $wpdb->get_var(
1852:             $wpdb->prepare(
1853:                 " SELECT count(id) FROM {$form_table_name}
1854:                   WHERE id=%d", $form_id
1855:             )
1856:         );
1857: 
1858:         $result = intval( $result );
1859: 
1860:         return $result > 0;
1861:     }
1862: 
1863:     /**
1864:      * Checks if an entry exists for the supplied ID.
1865:      *
1866:      * @since 2.4.5.8
1867:      *
1868:      * @param int $entry_id The ID to be checked.
1869:      *
1870:      * @return bool
1871:      */
1872:     public static function entry_exists( $entry_id ) {
1873:         return GFFormsModel::entry_exists( $entry_id );
1874:     }
1875: 
1876: }
1877: 
Gravity Forms API API documentation generated by ApiGen 2.8.0