= "meta_source_{$schema['destination']}";
$meta_select_clauses[] = "$meta_table_alias.$meta_value_column AS $meta_table_alias";
$meta_join_clauses[] = "
$meta_table $meta_table_alias ON
$meta_table_alias.$meta_entity_id_column = $source_table.$source_meta_rel_column AND
$meta_table_alias.$meta_key_column = '$meta_key'
";
$destination_select_clauses[] = "$destination_table.{$schema['destination']} as {$destination_table}_{$schema['destination']}";
}
$select_clause = implode( ', ', array_merge( $source_select_clauses, $meta_select_clauses, $destination_select_clauses ) );
$meta_join_clause = implode( ' LEFT JOIN ', $meta_join_clauses );
$where_clause = $this->get_where_clause_for_verification( $source_ids );
return "
SELECT $select_clause
FROM $source_table
LEFT JOIN $source_destination_join_clause
LEFT JOIN $meta_join_clause
WHERE $where_clause
";
}
/**
* Helper function to generate where clause for fetching data for verification.
*
* @param array $source_ids Array of IDs from source table.
*
* @return string WHERE clause.
*/
protected function get_where_clause_for_verification( $source_ids ) {
global $wpdb;
$source_primary_id_column = $this->schema_config['source']['entity']['primary_key'];
$source_table = $this->schema_config['source']['entity']['table_name'];
$source_ids_placeholder = implode( ', ', array_fill( 0, count( $source_ids ), '%d' ) );
return $wpdb->prepare(
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
"$source_table.$source_primary_id_column IN ($source_ids_placeholder)",
$source_ids
);
}
/**
* Verify data from both source and destination tables and check if they were migrated properly.
*
* @param array $collected_data Collected data in array format, should be in same structure as returned from query in `$this->build_verification_query`.
*
* @return array Array of failed IDs if any, along with columns/meta_key names.
*/
protected function verify_data( $collected_data ) {
$failed_ids = array();
foreach ( $collected_data as $row ) {
$failed_ids = $this->verify_entity_columns( $row, $failed_ids );
$failed_ids = $this->verify_meta_columns( $row, $failed_ids );
}
return $failed_ids;
}
/**
* Helper method to verify and compare core columns.
*
* @param array $row Both migrated and source data for a single row.
* @param array $failed_ids Array of failed IDs.
*
* @return array Array of failed IDs if any, along with columns/meta_key names.
*/
private function verify_entity_columns( $row, $failed_ids ) {
$primary_key_column = "{$this->schema_config['source']['entity']['table_name']}_{$this->schema_config['source']['entity']['primary_key']}";
foreach ( $this->core_column_mapping as $column_name => $schema ) {
$source_alias = "{$this->schema_config['source']['entity']['table_name']}_$column_name";
$destination_alias = "{$this->schema_config['destination']['table_name']}_{$schema['destination']}";
$row = $this->pre_process_row( $row, $schema, $source_alias, $destination_alias );
if ( $row[ $source_alias ] !== $row[ $destination_alias ] ) {
if ( ! isset( $failed_ids[ $row[ $primary_key_column ] ] ) ) {
$failed_ids[ $row[ $primary_key_column ] ] = array();
}
$failed_ids[ $row[ $primary_key_column ] ][] = array(
'column' => $column_name,
'original_value' => $row[ $source_alias ],
'new_value' => $row[ $destination_alias ],
);
}
}
return $failed_ids;
}
/**
* Helper method to verify meta columns.
*
* @param array $row Both migrated and source data for a single row.
* @param array $failed_ids Array of failed IDs.
*
* @return array Array of failed IDs if any, along with columns/meta_key names.
*/
private function verify_meta_columns( $row, $failed_ids ) {
$primary_key_column = "{$this->schema_config['source']['entity']['table_name']}_{$this->schema_config['source']['entity']['primary_key']}";
foreach ( $this->meta_column_mapping as $meta_key => $schema ) {
$meta_alias = "meta_source_{$schema['destination']}";
$destination_alias = "{$this->schema_config['destination']['table_name']}_{$schema['destination']}";
$row = $this->pre_process_row( $row, $schema, $meta_alias, $destination_alias );
if ( $row[ $meta_alias ] !== $row[ $destination_alias ] ) {
if ( ! isset( $failed_ids[ $row[ $primary_key_column ] ] ) ) {
$failed_ids[ $row[ $primary_key_column ] ] = array();
}
$failed_ids[ $row[ $primary_key_column ] ][] = array(
'column' => $meta_key,
'original_value' => $row[ $meta_alias ],
'new_value' => $row[ $destination_alias ],
);
}
}
return $failed_ids;
}
/**
* Helper method to pre-process rows to make sure we parse the correct type.
*
* @param array $row Both migrated and source data for a single row.
* @param array $schema Column schema.
* @param string $alias Name of source column.
* @param string $destination_alias Name of destination column.
*
* @return array Processed row.
*/
private function pre_process_row( $row, $schema, $alias, $destination_alias ) {
if ( in_array( $schema['type'], array( 'int', 'decimal' ), true ) ) {
$row[ $alias ] = wc_format_decimal( $row[ $alias ], false, true );
$row[ $destination_alias ] = wc_format_decimal( $row[ $destination_alias ], false, true );
}
if ( 'bool' === $schema['type'] ) {
$row[ $alias ] = wc_string_to_bool( $row[ $alias ] );
$row[ $destination_alias ] = wc_string_to_bool( $row[ $destination_alias ] );
}
if ( 'date_epoch' === $schema['type'] ) {
if ( '' === $row[ $alias ] || null === $row[ $alias ] ) {
$row[ $alias ] = null;
} else {
$row[ $alias ] = ( new \DateTime( "@{$row[ $alias ]}" ) )->format( 'Y-m-d H:i:s' );
}
if ( '0000-00-00 00:00:00' === $row[ $destination_alias ] ) {
$row[ $destination_alias ] = null;
}
}
if ( is_null( $row[ $alias ] ) ) {
$row[ $alias ] = $this->get_type_defaults( $schema['type'] );
}
return $row;
}
/**
* Helper method to get default value of a type.
*
* @param string $type Type.
*
* @return mixed Default value.
*/
private function get_type_defaults( $type ) {
switch ( $type ) {
case 'float':
case 'int':
return 0;
case 'string':
return '';
}
}
}