Merged in feature/MAW-855-import-code-into-aws (pull request #2)
code import from pantheon * code import from pantheon
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
namespace Yoast\WP\Lib;
|
||||
|
||||
use JsonSerializable;
|
||||
use ReturnTypeWillChange;
|
||||
|
||||
/**
|
||||
* Make Model compatible with WordPress.
|
||||
@@ -87,6 +88,13 @@ class Model implements JsonSerializable {
|
||||
*/
|
||||
protected $int_columns = [];
|
||||
|
||||
/**
|
||||
* Which columns contain float values.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $float_columns = [];
|
||||
|
||||
/**
|
||||
* Hacks around the Model to provide WordPress prefix to tables.
|
||||
*
|
||||
@@ -154,20 +162,22 @@ class Model implements JsonSerializable {
|
||||
* class or the property does not exist, returns the default
|
||||
* value supplied as the third argument (which defaults to null).
|
||||
*
|
||||
* @param string $class_name The target class name.
|
||||
* @param string $property The property to get the value for.
|
||||
* @param string|null $default Default value when property does not exist.
|
||||
* @param string $class_name The target class name.
|
||||
* @param string $property The property to get the value for.
|
||||
* @param mixed|null $default_value Default value when property does not exist.
|
||||
*
|
||||
* @return string The value of the property.
|
||||
* @return mixed|null The value of the property.
|
||||
*/
|
||||
protected static function get_static_property( $class_name, $property, $default = null ) {
|
||||
protected static function get_static_property( $class_name, $property, $default_value = null ) {
|
||||
if ( ! \class_exists( $class_name ) || ! \property_exists( $class_name, $property ) ) {
|
||||
return $default;
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
$properties = \get_class_vars( $class_name );
|
||||
if ( ! isset( $class_name::${$property} ) ) {
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
return $properties[ $property ];
|
||||
return $class_name::${$property};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -392,7 +402,7 @@ class Model implements JsonSerializable {
|
||||
$associated_table_name = static::get_table_name_for_class( static::$auto_prefix_models . $associated_class_name );
|
||||
$foreign_key_name = static::build_foreign_key_name( $foreign_key_name, $associated_table_name );
|
||||
$associated_object_id = $this->{$foreign_key_name};
|
||||
$desired_record = null;
|
||||
|
||||
if ( $foreign_key_name_in_associated_models_table === null ) {
|
||||
/*
|
||||
* Comparison: "{$associated_table_name}.primary_key = {$associated_object_id}".
|
||||
@@ -505,6 +515,9 @@ class Model implements JsonSerializable {
|
||||
if ( $value !== null && \in_array( $property, $this->int_columns, true ) ) {
|
||||
return (int) $value;
|
||||
}
|
||||
if ( $value !== null && \in_array( $property, $this->float_columns, true ) ) {
|
||||
return (float) $value;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
@@ -524,6 +537,9 @@ class Model implements JsonSerializable {
|
||||
if ( $value !== null && \in_array( $property, $this->int_columns, true ) ) {
|
||||
$value = (string) $value;
|
||||
}
|
||||
if ( $value !== null && \in_array( $property, $this->float_columns, true ) ) {
|
||||
$value = (string) $value;
|
||||
}
|
||||
|
||||
$this->orm->set( $property, $value );
|
||||
}
|
||||
@@ -544,6 +560,7 @@ class Model implements JsonSerializable {
|
||||
*
|
||||
* @return array The data of this object.
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function jsonSerialize() {
|
||||
return $this->orm->as_array();
|
||||
}
|
||||
@@ -554,7 +571,11 @@ class Model implements JsonSerializable {
|
||||
* @return array
|
||||
*/
|
||||
public function __debugInfo() {
|
||||
return $this->orm->as_array();
|
||||
if ( $this->orm ) {
|
||||
return $this->orm->as_array();
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -641,7 +662,7 @@ class Model implements JsonSerializable {
|
||||
/**
|
||||
* Save the data associated with this model instance to the database.
|
||||
*
|
||||
* @return null Nothing.
|
||||
* @return bool True on success.
|
||||
*/
|
||||
public function save() {
|
||||
if ( $this->uses_timestamps ) {
|
||||
@@ -657,7 +678,7 @@ class Model implements JsonSerializable {
|
||||
/**
|
||||
* Delete the database row associated with this model instance.
|
||||
*
|
||||
* @return null Nothing.
|
||||
* @return bool|int Response of wpdb::query.
|
||||
*/
|
||||
public function delete() {
|
||||
return $this->orm->delete();
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Yoast\WP\Lib;
|
||||
|
||||
use ReturnTypeWillChange;
|
||||
use wpdb;
|
||||
use Yoast\WP\SEO\Config\Migration_Status;
|
||||
|
||||
@@ -1586,7 +1587,7 @@ class ORM implements \ArrayAccess {
|
||||
* Adds a HAVING ... LIKE clause to your query.
|
||||
*
|
||||
* @param string|array $column_name The table column.
|
||||
* @param null $value The value.
|
||||
* @param string|null $value The value.
|
||||
*
|
||||
* @return ORM
|
||||
*/
|
||||
@@ -1598,7 +1599,7 @@ class ORM implements \ArrayAccess {
|
||||
* Adds where HAVING ... NOT LIKE clause to your query.
|
||||
*
|
||||
* @param string|array $column_name The table column.
|
||||
* @param null $value The value.
|
||||
* @param string|null $value The value.
|
||||
*
|
||||
* @return ORM
|
||||
*/
|
||||
@@ -1610,7 +1611,7 @@ class ORM implements \ArrayAccess {
|
||||
* Adds a HAVING ... > clause to your query.
|
||||
*
|
||||
* @param string|array $column_name The table column.
|
||||
* @param null $value The value.
|
||||
* @param mixed $value The value.
|
||||
*
|
||||
* @return ORM
|
||||
*/
|
||||
@@ -1622,7 +1623,7 @@ class ORM implements \ArrayAccess {
|
||||
* Adds a HAVING ... < clause to your query.
|
||||
*
|
||||
* @param string|array $column_name The table column.
|
||||
* @param null $value The value.
|
||||
* @param mixed $value The value.
|
||||
*
|
||||
* @return ORM
|
||||
*/
|
||||
@@ -1634,7 +1635,7 @@ class ORM implements \ArrayAccess {
|
||||
* Adds a HAVING ... >= clause to your query.
|
||||
*
|
||||
* @param string|array $column_name The table column.
|
||||
* @param null $value The value. Defaults to null.
|
||||
* @param mixed $value The value. Defaults to null.
|
||||
*
|
||||
* @return ORM
|
||||
*/
|
||||
@@ -1646,7 +1647,7 @@ class ORM implements \ArrayAccess {
|
||||
* Adds a HAVING ... <= clause to your query.
|
||||
*
|
||||
* @param string|array $column_name The table column.
|
||||
* @param null $value The value.
|
||||
* @param mixed $value The value.
|
||||
*
|
||||
* @return ORM
|
||||
*/
|
||||
@@ -1658,7 +1659,7 @@ class ORM implements \ArrayAccess {
|
||||
* Adds a HAVING ... IN clause to your query.
|
||||
*
|
||||
* @param string|array $column_name The table column.
|
||||
* @param null $values The values. Defaults to null.
|
||||
* @param array|null $values The values. Defaults to null.
|
||||
*
|
||||
* @return ORM
|
||||
*/
|
||||
@@ -1670,7 +1671,7 @@ class ORM implements \ArrayAccess {
|
||||
* Adds a HAVING ... NOT IN clause to your query.
|
||||
*
|
||||
* @param string|array $column_name The table column.
|
||||
* @param null $values The values. Defaults to null.
|
||||
* @param array|null $values The values. Defaults to null.
|
||||
*
|
||||
* @return ORM
|
||||
*/
|
||||
@@ -2196,6 +2197,100 @@ class ORM implements \ArrayAccess {
|
||||
return $success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts and gathers all dirty column names from the given model instances.
|
||||
*
|
||||
* @param array $models Array of model instances to be inserted.
|
||||
*
|
||||
* @return array The distinct set of columns that are dirty in at least one of the models.
|
||||
*
|
||||
* @throws \InvalidArgumentException Instance to be inserted is not a new one.
|
||||
*/
|
||||
public function get_dirty_column_names( $models ) {
|
||||
$dirty_column_names = [];
|
||||
|
||||
foreach ( $models as $model ) {
|
||||
if ( ! $model->orm->is_new() ) {
|
||||
throw new \InvalidArgumentException( 'Instance to be inserted is not a new one' );
|
||||
}
|
||||
|
||||
// Remove any expression fields as they are already baked into the query.
|
||||
$dirty_fields = \array_diff_key( $model->orm->dirty_fields, $model->orm->expr_fields );
|
||||
$dirty_column_names = \array_merge( $dirty_column_names, $dirty_fields );
|
||||
}
|
||||
|
||||
$dirty_column_names = \array_keys( $dirty_column_names );
|
||||
|
||||
return $dirty_column_names;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts multiple rows in a single query. Expects new rows as it's a strictly insert function, not an update one.
|
||||
*
|
||||
* @example From the Indexable_Link_Builder class: $this->seo_links_repository->query()->insert_many( $links );
|
||||
*
|
||||
* @param array $models Array of model instances to be inserted.
|
||||
*
|
||||
* @return bool True for successful insert, false for failed.
|
||||
*
|
||||
* @throws \InvalidArgumentException Invalid instances to be inserted.
|
||||
* @throws \InvalidArgumentException Instance to be inserted is not a new one.
|
||||
*/
|
||||
public function insert_many( $models ) {
|
||||
// Validate the input first.
|
||||
if ( ! \is_array( $models ) ) {
|
||||
throw new \InvalidArgumentException( 'Invalid instances to be inserted' );
|
||||
}
|
||||
|
||||
if ( empty( $models ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$success = true;
|
||||
|
||||
/**
|
||||
* Filter: 'wpseo_chunk_bulked_insert_queries' - Allow filtering the chunk size of each bulked INSERT query.
|
||||
*
|
||||
* @api int The chunk size of the bulked INSERT queries.
|
||||
*/
|
||||
$chunk = \apply_filters( 'wpseo_chunk_bulk_insert_queries', 100 );
|
||||
$chunk = ! \is_int( $chunk ) ? 100 : $chunk;
|
||||
$chunk = ( $chunk <= 0 ) ? 100 : $chunk;
|
||||
|
||||
$chunked_models = \array_chunk( $models, $chunk );
|
||||
foreach ( $chunked_models as $models_chunk ) {
|
||||
$values = [];
|
||||
|
||||
// First, we'll gather all the dirty fields throughout the models to be inserted.
|
||||
$dirty_column_names = $this->get_dirty_column_names( $models_chunk );
|
||||
|
||||
// Now, we're creating all dirty fields throughout the models and
|
||||
// setting them to null if they don't exist in each model.
|
||||
foreach ( $models_chunk as $model ) {
|
||||
$model_values = [];
|
||||
|
||||
foreach ( $dirty_column_names as $dirty_column ) {
|
||||
// Set the value to null if it hasn't been set already.
|
||||
if ( ! isset( $model->orm->dirty_fields[ $dirty_column ] ) ) {
|
||||
$model->orm->dirty_fields[ $dirty_column ] = null;
|
||||
}
|
||||
|
||||
// Only register the value if it is not null.
|
||||
if ( ! is_null( $model->orm->dirty_fields[ $dirty_column ] ) ) {
|
||||
$model_values[] = $model->orm->dirty_fields[ $dirty_column ];
|
||||
}
|
||||
}
|
||||
$values = \array_merge( $values, $model_values );
|
||||
}
|
||||
|
||||
// We now have the same set of dirty columns in all our models and also gathered all values.
|
||||
$query = $this->build_insert_many( $models_chunk, $dirty_column_names );
|
||||
$success = $success && (bool) self::execute( $query, $values );
|
||||
}
|
||||
|
||||
return $success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates many records in the database.
|
||||
*
|
||||
@@ -2282,6 +2377,39 @@ class ORM implements \ArrayAccess {
|
||||
return \implode( ' ', $query );
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a bulk INSERT query.
|
||||
*
|
||||
* @param array $models Array of model instances to be inserted.
|
||||
* @param array $dirty_column_names Array of dirty fields to be used in INSERT.
|
||||
*
|
||||
* @return string The insert query.
|
||||
*/
|
||||
protected function build_insert_many( $models, $dirty_column_names ) {
|
||||
$example_model = $models[0];
|
||||
$total_placeholders = '';
|
||||
|
||||
$query = [];
|
||||
$query[] = 'INSERT INTO';
|
||||
$query[] = $this->quote_identifier( $example_model->orm->table_name );
|
||||
$field_list = \array_map( [ $this, 'quote_identifier' ], $dirty_column_names );
|
||||
$query[] = '(' . \implode( ', ', $field_list ) . ')';
|
||||
$query[] = 'VALUES';
|
||||
|
||||
// We assign placeholders per model for dirty fields that have values and NULL for dirty fields that don't.
|
||||
foreach ( $models as $model ) {
|
||||
$placeholder = [];
|
||||
foreach ( $dirty_column_names as $dirty_field ) {
|
||||
$placeholder[] = ( $model->orm->dirty_fields[ $dirty_field ] === null ) ? 'NULL' : '%s';
|
||||
}
|
||||
$placeholders = \implode( ', ', $placeholder );
|
||||
$total_placeholders .= "({$placeholders}),";
|
||||
}
|
||||
|
||||
$query[] = \rtrim( $total_placeholders, ',' );
|
||||
return \implode( ' ', $query );
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes this record from the database.
|
||||
*
|
||||
@@ -2323,46 +2451,50 @@ class ORM implements \ArrayAccess {
|
||||
/**
|
||||
* Checks whether the data has the key.
|
||||
*
|
||||
* @param mixed $key Key.
|
||||
* @param mixed $offset Key.
|
||||
*
|
||||
* @return bool Whether the data has the key.
|
||||
*/
|
||||
public function offsetExists( $key ) {
|
||||
return \array_key_exists( $key, $this->data );
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetExists( $offset ) {
|
||||
return \array_key_exists( $offset, $this->data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the value of the key.
|
||||
*
|
||||
* @param mixed $key Key.
|
||||
* @param mixed $offset Key.
|
||||
*
|
||||
* @return array|mixed|null The value.
|
||||
*/
|
||||
public function offsetGet( $key ) {
|
||||
return $this->get( $key );
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetGet( $offset ) {
|
||||
return $this->get( $offset );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the key.
|
||||
*
|
||||
* @param string|int $key Key.
|
||||
* @param mixed $value Value.
|
||||
* @param string|int $offset Key.
|
||||
* @param mixed $value Value.
|
||||
*/
|
||||
public function offsetSet( $key, $value ) {
|
||||
if ( \is_null( $key ) ) {
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetSet( $offset, $value ) {
|
||||
if ( \is_null( $offset ) ) {
|
||||
return;
|
||||
}
|
||||
$this->set( $key, $value );
|
||||
$this->set( $offset, $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the given key from the data.
|
||||
*
|
||||
* @param mixed $key Key.
|
||||
* @param mixed $offset Key.
|
||||
*/
|
||||
public function offsetUnset( $key ) {
|
||||
unset( $this->data[ $key ] );
|
||||
unset( $this->dirty_fields[ $key ] );
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetUnset( $offset ) {
|
||||
unset( $this->data[ $offset ] );
|
||||
unset( $this->dirty_fields[ $offset ] );
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user