| Server IP : 68.183.124.220 / Your IP : 216.73.217.137 Web Server : Apache/2.4.18 (Ubuntu) System : Linux Sandbox-A 4.4.0-210-generic #242-Ubuntu SMP Fri Apr 16 09:57:56 UTC 2021 x86_64 User : gavin ( 1000) PHP Version : 7.0.33-0ubuntu0.16.04.16 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority, MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /var/www/html/wp-content/plugins/ninja-forms/includes/Updates/ |
Upload File : |
<?php if ( ! defined( 'ABSPATH' ) ) exit;
/**
* Class NF_Updates_CacheFieldReconcilliation
*
* This allows us to make sure that the data being saved to the database is in the fields table.
*/
class NF_Updates_CacheFieldReconcilliation extends NF_Abstracts_RequiredUpdate
{
private $data = array();
private $running = array();
/**
* Non-associatve array of field ids from the cache.
* @var array
*/
private $field_ids = array();
/**
* columns to retrieve from meta table
*/
private $meta_keys = array(
'label',
'key',
'order',
'required',
'default',
'label_pos',
'personally_identifiable'
);
/**
* The denominator object for calculating our steps.
* @var Integer
*/
private $divisor = 200;
/**
* The table names for our database queries.
*/
private $table;
private $meta_table;
/**
* Constructor
*
* @param $data (Array) The data object passed in by the AJAX call.
* @param $running (Array) The array of required updates being run.
*
* @since 3.4.0
*/
public function __construct( $data = array(), $running )
{
// Build our arguments array.
$args = array(
'slug' => 'CacheFieldReconcilliation',
'class_name' => 'NF_Updates_CacheFieldReconcilliation',
'debug' => false,
);
$this->data = $data;
$this->running = $running;
// Call the parent constructor.
parent::__construct( $args );
// Set our table names.
$this->table = $this->db->prefix . 'nf3_fields';
$this->meta_table = $this->db->prefix . 'nf3_field_meta';
// Begin processing.
$this->process();
}
/**
* Function to loop over the batch.
*
* @since 3.4.0
*/
public function process()
{
// If we've not already started...
if ( ! isset( $this->running[ 0 ][ 'running' ] ) ) {
// Run our startup method.
$this->startup();
}
/**
* Get the next round of fields to update
*/
$this->get_fields_this_step();
/**
* Update fields
*/
$this->update_fields();
/**
* Saves our current location, along with any processing data we may need for the next step.
* If we're done with our step, runs cleanup instead.
*/
$this->end_of_step();
/**
* Respond to the AJAX call.
*/
$this->respond();
}
/**
* Function to run any setup steps necessary to begin processing.
*
* @since 3.4.0
*/
public function startup()
{
// Record that we're processing the update.
$this->running[ 0 ][ 'running' ] = true;
$sql = "SELECT `id` FROM `{$this->table}`";
$fields = $this->db->get_results( $sql, 'ARRAY_A' );
// Record the total number of steps in this batch.
$this->running[ 0 ][ 'steps' ] = ceil(count( $fields ) / $this->divisor);
// Record our current step (defaulted to 0 here).
$this->running[ 0 ][ 'current' ] = 0;
}
public function get_fields_this_step() {
$offset = 0;
if( 0 < $this->running[ 0 ][ 'current' ] ) {
$offset = $this->running[ 0 ][ 'current' ] * $this->divisor;
}
// Get a list of our fields...
$sql = "SELECT `id` FROM `{$this->table}` LIMIT {$offset}, {$this->divisor}";
$this->field_ids = $this->db->get_results( $sql, 'ARRAY_A' );
$this->field_ids = $this->array_squash( $this->field_ids );
// $this->running[ 0 ][ 'fields' ] = $this->field_ids;
}
/**
* Update field table records with data from field meta
*/
public function update_fields() {
$field_meta = $this->get_field_meta();
if($field_meta) {
$update_query = $this->get_update_query( $field_meta );
if( $update_query ) {
$this->query($update_query);
}
}
}
/**
* Get meta data to use for updating
*/
public function get_field_meta() {
if(0 === count($this->field_ids)) return false;
$in_fields = implode( ', ', $this->field_ids );
$meta_keys = "'" . implode( "' , '", $this->meta_keys ) . "'";
$meta_query = $this->get_field_meta_query();
$results = $this->db->get_results( $meta_query, 'ARRAY_A');
$meta_data = $this->format_field_meta($results);
return $meta_data;
}
/**
* Construct the query to get meta data
*
* return String $meta_query
*/
public function get_field_meta_query() {
$in_fields = implode( ', ', $this->field_ids );
$meta_keys = "'" . implode( "' , '", $this->meta_keys ) . "'";
$meta_query = "SELECT `parent_id`, `key`, `meta_key`, `meta_value`, `value` FROM `{$this->meta_table}` WHERE `parent_id` IN ({$in_fields}) AND `key` IN ({$meta_keys}) ORDER BY `parent_id` ASC";
return $meta_query;
}
/**
* Format the data into format that helps us construct the insert/update query
*
* @param Array $metadata
*
* @return Array $meta_data
*/
public function format_field_meta( $metadata ) {
$meta_data = array();
foreach( $metadata as $meta ) {
$parent_id = $meta['parent_id'];
foreach( $meta as $key => $val ) {
if( 'parent_id' !== $key ) {
$meta_data[ $parent_id ][ $meta['key'] ] = $meta['value'];
$meta_data[ $parent_id ][ 'meta_' . $meta['meta_key'] ] = $meta['meta_value'];
}
}
}
return $meta_data;
}
/**
* Construct field update query
*/
public function get_update_query( $field_data ) {
if( 0 === count( $field_data) ) return false;
$sql = "INSERT INTO {$this->table}
(`id`, `label`, `key`, `field_label`, `field_key`, `order`, `required`, `default_value`, `label_pos`, `personally_identifiable`)
VALUES";
foreach( $field_data as $field_id => $meta ) {
$sql .= "({$field_id}, '{$this->db->_real_escape($meta['label'])}', '{$this->db->_real_escape($meta['key'])}', '{$this->db->_real_escape($meta['meta_label'])}', '{$this->db->_real_escape($meta['meta_key'])}', {$meta['order']},";
if( isset( $meta[ 'required' ] ) && '' !== $meta[ 'required' ]) {
$sql .= "{$meta['required']},";
} else {
$sql .= "0,";
}
if(isset( $meta[ 'meta_default' ] ) ) {
$sql .= "'{$this->db->_real_escape($meta['meta_default'])}',";
} else {
$sql .= "'',";
}
if( isset( $meta[ 'meta_label_pos' ] ) ) {
$sql .= "'{$meta['meta_label_pos']}',";
} else {
$sql .= "'',";
}
if(isset($meta['personally_identifiable'])) {
$sql .= "{$meta['personally_identifiable']}";
} else {
$sql .= "0";
}
$sql .= "),";
}
$sql = rtrim( $sql, ',' );
$sql .= "ON DUPLICATE KEY
UPDATE
`label` = VALUES(`label`),
`key` = VALUES(`key`),
`field_label` = VALUES(`field_label`),
`field_key` = VALUES(`field_key`),
`order` = VALUES(`order`),
`required` = VALUES(`required`),
`required` = VALUES(`required`),
`default_value` = VALUES(`default_value`),
`label_pos` = VALUES(`label_pos`),
`personally_identifiable` = VALUES(`personally_identifiable`)";
return $sql;
}
/**
* Function to cleanup any lingering temporary elements of a required update after completion.
*
* @since 3.4.0
*/
public function cleanup()
{
// Remove the current process from the array.
array_shift( $this->running );
// Record to our updates setting that this update is complete.
$this->confirm_complete();
// If we have no updates left to process...
if ( empty( $this->running ) ) {
// Call the parent cleanup method.
parent::cleanup();
}
}
/**
* 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.
*
* @since 3.4.0
* @return void
*/
private function end_of_step()
{
$this->running[ 0 ][ 'current' ] = intval( $this->running[ 0 ][ 'current' ] ) + 1;
// 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 ( $this->divisor > count($this->field_ids)) {
// Run our cleanup method.
$this->cleanup();
}
// 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 );
}
/**
* Function to compress our db results into a more useful format.
*
* @param $data (Array) The result to be compressed.
*
* @return (Array) Associative if our data was complex.
* Non-associative if our data was a single item.
*
* @since UPDATE_VERSION_ON_MERGE
*/
private function array_squash( $data )
{
$response = array();
// For each item in the array...
foreach ( $data as $row ) {
// If the item has more than 1 attribute...
if ( 1 < count( $row ) ) {
// Assign the data to an associated result.
$response[] = intval($row['id']);
// Unset the id setting, as that will be the key.
unset( $response[ $row[ 'id' ] ][ '' ] );
} // Otherwise... (We only have 1 attribute.)
else {
// Add the id to the stack in a non-associated result.
$response[] = intval( $row[ 'id' ] );
}
}
return $response;
}
}