: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* Keep track of old field ids we've used.
* Initially, we set our record array to our current submission updates array.
* When we finish updating an old field, we remove it from the record array.
* When we're done with all fields, we set the submission updates array to the record array.
$submission_updates_record = $this->submission_updates;
// Meta key update limit; How many meta keys do we want to update at a time?
// Loop through submission updates and query the postmeta table for any meta_key values of _field_{old_id}.
foreach ( $this->submission_updates as $old_id => $new_id ) {
// Make sure that we haven't reached our query limit.
if ( 1 > $this->limit ) {
$this->lock_process = true;
// This sql is designed to grab our old _field_X post meta keys so that we can replace them with new _field_X meta keys.
`{$this->db->prefix}posts` p
INNER JOIN `{$this->db->prefix}postmeta` old_field_id ON old_field_id.post_id = p.ID
AND old_field_id.meta_key = '_field_{$old_id}'
INNER JOIN `{$this->db->prefix}postmeta` form_id ON form_id.post_id = p.ID
AND form_id.meta_key = '_form_id'
WHERE old_field_id.meta_key = '_field_{$old_id}'
AND form_id.meta_value = {$this->form[ 'ID' ]}
AND p.post_type = 'nf_sub'
LIMIT {$meta_key_limit}";
// Fetch our sql results.
$meta_ids = $this->db->get_results( $sql, 'ARRAY_N' );
if ( ! empty( $meta_ids ) ) {
// Implode our meta ids so that we can use the result in our update sql.
$imploded_ids = implode( ',', call_user_func_array( 'array_merge', $meta_ids ) );
// Update all our fetched meta ids with the new _field_ meta key.
$sql = "UPDATE `{$this->db->prefix}postmeta`
SET meta_key = '_field_{$new_id}'
WHERE meta_id IN ( {$imploded_ids} )";
* Let's make sure that we're done processing all post meta for this old field ID.
* If the number of meta rows retrieved equals our limit:
* we're done with this old field, remove it from our list
* subtract from our $this->limit var
if ( $meta_key_limit === count( $meta_ids ) ) {
// Keep anything else from processing.
$this->lock_process = true;
// Exit this foreach loop.
} else { // We're done with this old field.
// Remove the field ID from our submission array.
unset( $submission_updates_record[ $old_id ] );
// Decrement our query limit.
// Set our submission updates array to our record array so that we remove any completed old ids.
$this->submission_updates = $submission_updates_record;
* If we still have field_ids in our class var, then we need to update the field table.
* If lock_process is true or we have no field_ids, we bail early.
private function maybe_update_fields()
// If we have no fields to insert OR lock_process is true, bail early.
if ( empty ( $this->field_ids ) || $this->lock_process ) {
// Store the meta items outside the loop for faster insertion.
// While we still have items to update...
while ( 0 < count( $this->field_ids ) ) {
// If we have hit our limit...
if ( 1 > $this->limit ) {
$this->lock_process = true;
// Get our item to be updated.
$updating = array_pop( $this->field_ids );
array_push( $flush_ids, $updating );
$settings = $this->fields_by_id[ $updating ];
// Update the fields table.
$sql = "UPDATE `{$this->table}` SET label = '"
. $this->prepare( $settings[ 'label' ] )
. "', `key` = '" . $this->prepare( $settings[ 'key' ] )
. "', `type` = '" . $this->prepare( $settings[ 'type' ] )
. "', field_label = '" . $this->prepare( $settings[ 'label' ] )
. "', field_key = '" . $this->prepare( $settings[ 'key' ] )
. "', `order` = " . intval( $settings[ 'order' ] );
if( isset( $settings[ 'required' ] ) ) {
$sql .= ", required = " . intval( $settings[ 'required' ] );
$sql .= ", required = 0";
if ( isset( $settings[ 'default_value' ] ) ) {
$sql .= ", default_value = '" . $this->prepare( $settings[ 'default_value' ] ) . "'";
$sql .= ", default_value = ''";
if ( isset( $settings[ 'label_pos' ] ) ) {
$sql .= ", label_pos = '" . $this->prepare( $settings[ 'label_pos' ] ) . "'";
$sql .= ", label_pos = ''";
if ( isset( $settings[ 'personally_identifiable' ] ) ) {
$sql .= ", personally_identifiable = " . intval( $settings[ 'personally_identifiable' ] );
$sql .= ", personally_identifiable = 0";;
$sql .= " WHERE id = " . intval( $updating );
// For each meta of the field...
foreach ( $settings as $meta => $value ) {
if ( ( ! empty( $value ) || '0' == $value ) ) {
// Add the data to the list.
array_push( $meta_items, "( " . intval( $updating ) . ", '" . $meta . "', '" . $this->prepare( $value ) . "', '" . $meta . "', '" . $this->prepare( $value ) . "' )" );
// Remove the item from the list of fields.
unset( $this->fields_by_id[ $updating ] );
if ( ! empty ( $flush_ids ) ) {
// Flush our existing meta.
$sql = "DELETE FROM `{$this->meta_table}` WHERE parent_id IN(" . implode( ', ', $flush_ids ) . ")";
// Insert our updated meta.
$sql = "INSERT INTO `{$this->meta_table}` ( parent_id, `key`, value, meta_key, meta_value ) VALUES " . implode( ', ', $meta_items );
* If we've inserted any fields that have changed ids, we want to update those ids in our cache.
* This method grabs the cache, updates any field ids, then updates the cache.
private function update_form_cache()
// Get a copy of the cache.
$cache = WPN_Helper::get_nf_cache($this->form[ 'ID' ] );
// For each field in the cache...
foreach( $cache[ 'fields' ] as &$field ) {
// If we have a new ID for this field...
if ( isset( $this->insert_ids[ $field[ 'id' ] ] ) ) {
$field[ 'id' ] = intval( $this->insert_ids[ $field[ 'id' ] ] );
// TODO: Might also need to append some new settings here (Label)?
// Save the cache, passing 3 as the current stage.
WPN_Helper::update_nf_cache( $this->form[ 'ID' ], $cache, 3 );
* After we've done our processing, but before we get to step cleanup, we need to store process information.
* This method updates our form class var so that it can be passed to the next step.
* If we've completed this step, it calls the cleanup method.
private function end_of_step()
// If we have locked processing...
if ( $this->lock_process ) {
// If we're continuing a process...
if ( isset( $this->form[ 'field_ids' ] ) ) {
// Reset the field_ids array.
$this->field_ids = array();
// For each field left to process...
foreach ( $this->fields_by_id as $id => $field ) {
// If we've not already processed this field...
if ( in_array( $id, $this->form[ 'field_ids' ] ) ) {
// Save a reference to its ID.
array_push( $this->field_ids, $id );
// Store our current data location.
$this->form[ 'insert' ] = $this->insert;
$this->form[ 'field_ids' ] = $this->field_ids;
$this->form[ 'submission_updates' ] = $this->submission_updates;
array_push( $this->running[ 0 ][ 'forms' ], $this->form );
} else { // Otherwise... (The step is complete.)
// Increment our step count.
$this->running[ 0 ][ 'current' ] = intval( $this->running[ 0 ][ 'current' ] ) + 1;
// Disable maintenance mode on the front end of the site.
$this->disable_maintenance_mode( $this->db->prefix, $this->form[ 'ID' ] );
// Prepare to output our number of steps and current step.
$this->response[ 'stepsTotal' ] = $this->running[ 0 ][ 'steps' ];
$this->response[ 'currentStep' ] = $this->running[ 0 ][ 'current' ];
// If all steps have been completed...
if ( empty( $this->running[ 0 ][ 'forms' ] ) ) {
// Run our cleanup method.
// Record our current location in the process.
update_option( 'ninja_forms_doing_required_updates', $this->running );
// Prepare to output the number of updates remaining.
$this->response[ 'updatesRemaining' ] = count( $this->running );