-
Notifications
You must be signed in to change notification settings - Fork 3.5k
#59269 Add support for adding metadata in bulk #5128
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: trunk
Are you sure you want to change the base?
Changes from 63 commits
17bcbf6
986ec52
26d8b49
7539a67
ccfd9f2
bde79b0
63ad9a0
25568cf
6628c5d
ae4d0e2
bd44522
8b20883
8636e97
fd188a7
41d4f0f
0519ff5
3412032
fcf5696
2bdfb62
ec59fbf
3b17bd6
96d3494
3561331
28f77ca
fcbae4e
764c4fe
33bbd80
b01ea4a
0403bae
c2cfd4a
60b07f9
532267b
77a2dd3
e56a4de
bf3f6c8
9c47a61
c2ae9aa
71768ab
fa73e3d
26fea60
f4fc114
41d8473
e09e8b0
db01cb1
b8429c7
18bde2a
14f6187
03697e0
7299c45
3f3e1c4
cec8a66
a142584
7cfb673
f84a39c
1d03913
54f7d51
9a11cc5
30dca5b
3a037e2
01428b9
caf0bcc
1f197a2
0b37c70
752cd68
280454f
369d2e7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -535,6 +535,7 @@ class wpdb { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @see wpdb::prepare() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @see wpdb::insert() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @see wpdb::insert_multiple() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @see wpdb::update() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @see wpdb::delete() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @see wp_set_wpdb_vars() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -2498,7 +2499,7 @@ public function remove_placeholder_escape( $query ) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Both `$data` columns and `$data` values should be "raw" (neither should be SQL escaped). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Sending a null value will cause the column to be set to NULL - the corresponding | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * format is ignored in this case. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @param string[]|string $format Optional. An array of formats to be mapped to each of the value in `$data`. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @param string[]|string $format Optional. An array of formats to be mapped to each of the values in `$data`. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * If string, that format will be used for all of the values in `$data`. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * A format is one of '%d', '%f', '%s' (integer, float, string). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * If omitted, all values in `$data` will be treated as strings unless otherwise | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -2509,6 +2510,110 @@ public function insert( $table, $data, $format = null ) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return $this->_insert_replace_helper( $table, $data, $format, 'INSERT' ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Inserts multiple rows into the table in one query. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * If the insert fails, no rows will be inserted. It's not possible for some rows | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * to be inserted and not others. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Examples: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * $wpdb->insert_multiple( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 'table', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * array( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 'column1', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 'column2', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * array( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * array( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 'column 1 value 1', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 'column 2 value 1', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * array( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 'column 1 value 2', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 'column 2 value 2', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * array( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 'column 1 value 3', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 'column 2 value 3', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * $wpdb->insert_multiple( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 'table', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * array( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 'column1', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 'column2', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * array( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * array( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 'column 1 value 1', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 1, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * array( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 'column 1 value 2', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 2, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * array( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 'column 1 value 3', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * 3, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * array( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * '%s', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * '%d', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @since x.y.z | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @param string $table Table name. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @param string[] $columns Array of column names. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @param array $rows Array of rows of values to insert. Values should be "raw" (should not be SQL escaped). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Sending a null value will cause the column to be set to NULL - the corresponding | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * format is ignored in this case. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @param string[] $format Optional. An array of formats to be mapped to each of the values in each row. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * A format is one of '%d', '%f', '%s' (integer, float, string). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * If omitted, all values in `$data` will be treated as strings unless otherwise | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * specified in wpdb::$field_types. Default empty array. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @return int|false The number of rows inserted, or false on error. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public function insert_multiple( string $table, array $columns, array $rows, array $format = array() ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $this->insert_id = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $values_sql = array(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $values = array( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $table, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| foreach ( $rows as $row ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $data = $this->process_fields( $table, array_combine( $columns, $row ), $format ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+2578
to
+2584
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $values_sql = array(); | |
| $values = array( | |
| $table, | |
| ); | |
| foreach ( $rows as $row ) { | |
| $data = $this->process_fields( $table, array_combine( $columns, $row ), $format ); | |
| // Validate that we have at least one column and one row to insert. | |
| if ( empty( $columns ) || empty( $rows ) ) { | |
| return false; | |
| } | |
| $values_sql = array(); | |
| $values = array( | |
| $table, | |
| ); | |
| foreach ( $rows as $row ) { | |
| // Each row must be an array with the same number of elements as the columns. | |
| if ( ! is_array( $row ) || count( $row ) !== count( $columns ) ) { | |
| return false; | |
| } | |
| $combined = array_combine( $columns, $row ); | |
| if ( false === $combined ) { | |
| return false; | |
| } | |
| $data = $this->process_fields( $table, $combined, $format ); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -170,6 +170,123 @@ function add_metadata( $meta_type, $object_id, $meta_key, $meta_value, $unique = | |
| return $mid; | ||
| } | ||
|
|
||
| /** | ||
| * Adds multiple items of metadata for the specified object. | ||
| * | ||
| * This function is more performant than calling `add_metadata()` multiple times because it queries the database only | ||
| * once and clears the meta cache only once. | ||
| * | ||
| * This function will always insert all of the provided metadata even if matching keys already exist. This behaviour | ||
| * matches that of add_metadata() when its `$unique` parameter is set to false. | ||
| * | ||
| * If the insert fails, no metadata will be inserted. It's not possible for a subset of the rows to be inserted. | ||
| * | ||
| * Examples: | ||
| * | ||
| * bulk_add_metadata( | ||
| * 'post', | ||
| * $post_id, | ||
| * array( | ||
| * 'meta_key_1' => 'value_1', | ||
| * 'meta_key_2' => 'value_2', | ||
|
johnbillion marked this conversation as resolved.
|
||
| * ) | ||
| * ); | ||
| * | ||
| * For historical reasons both the meta key and the meta value are expected to be "slashed" (slashes escaped) on input. | ||
| * | ||
| * @since x.y.z | ||
| * | ||
| * @global wpdb $wpdb WordPress database abstraction object. | ||
| * | ||
| * @param string $meta_type Type of object metadata is for. Accepts 'post', 'comment', 'term', 'user', | ||
| * 'blog', or any other object type with an associated meta table. | ||
| * @param int $object_id ID of the object metadata is for. | ||
| * @param array<string,mixed> $meta_fields Metadata values keyed by their meta key. Values must be serializable if non-scalar. | ||
| * @return array<string,int>|false Array of meta IDs keyed by their meta key on success, false on failure. | ||
| */ | ||
| function bulk_add_metadata( string $meta_type, int $object_id, array $meta_fields ) { | ||
| global $wpdb; | ||
|
|
||
| if ( ! $meta_type || ! $meta_fields ) { | ||
| return false; | ||
| } | ||
|
|
||
| $object_id = absint( $object_id ); | ||
| if ( ! $object_id ) { | ||
| return false; | ||
| } | ||
|
|
||
| $table = _get_meta_table( $meta_type ); | ||
| if ( ! $table ) { | ||
| return false; | ||
| } | ||
|
|
||
| $meta_subtype = get_object_subtype( $meta_type, $object_id ); | ||
| $column = sanitize_key( $meta_type . '_id' ); | ||
| $data = array(); | ||
| $return = array(); | ||
| $added_keys = array(); | ||
|
|
||
| foreach ( $meta_fields as $meta_key => $meta_value ) { | ||
| // expected_slashed ($meta_key) | ||
|
johnbillion marked this conversation as resolved.
Outdated
|
||
| $meta_key = wp_unslash( $meta_key ); | ||
| $meta_value = wp_unslash( $meta_value ); | ||
| $meta_value = sanitize_meta( $meta_key, $meta_value, $meta_type, $meta_subtype ); | ||
|
|
||
| /** This filter is documented in wp-includes/meta.php */ | ||
| $check = apply_filters( "add_{$meta_type}_metadata", null, $object_id, $meta_key, $meta_value, false ); | ||
| if ( null !== $check ) { | ||
| $return[ $meta_key ] = $check; | ||
| continue; | ||
| } | ||
|
|
||
| /** This action is documented in wp-includes/meta.php */ | ||
| do_action( "add_{$meta_type}_meta", $object_id, $meta_key, $meta_value ); | ||
|
|
||
| $added_keys[] = $meta_key; | ||
|
|
||
| $data[] = array( | ||
| $object_id, | ||
| $meta_key, | ||
| maybe_serialize( $meta_value ), | ||
| ); | ||
| } | ||
|
|
||
| // If there is no data to save, don't attempt to save it. | ||
| if ( ! $data ) { | ||
| return $return; | ||
| } | ||
|
|
||
| $inserted = $wpdb->insert_multiple( | ||
|
johnbillion marked this conversation as resolved.
|
||
| $table, | ||
| array( | ||
| $column, | ||
| 'meta_key', | ||
| 'meta_value', | ||
| ), | ||
| $data | ||
| ); | ||
|
|
||
| if ( ! $inserted ) { | ||
| return false; | ||
| } | ||
|
|
||
| $first_mid = (int) $wpdb->insert_id; | ||
| $inserted_mids = range( $first_mid, $first_mid + $inserted - 1 ); | ||
| $keyed_mids = array_combine( $added_keys, $inserted_mids ); | ||
|
Comment on lines
+246
to
+276
|
||
| $all_mids = array_merge( $return, $keyed_mids ); | ||
|
|
||
| wp_cache_delete( $object_id, $meta_type . '_meta' ); | ||
|
|
||
| foreach ( $data as $datum ) { | ||
| list( $object_id, $meta_key, $meta_value ) = $datum; | ||
| /** This action is documented in wp-includes/meta.php */ | ||
| do_action( "added_{$meta_type}_meta", $all_mids[ $meta_key ], $object_id, $meta_key, $meta_value ); | ||
|
johnbillion marked this conversation as resolved.
Outdated
|
||
| } | ||
|
|
||
| return $all_mids; | ||
| } | ||
|
|
||
| /** | ||
| * Updates metadata for the specified object. If no value already exists for the specified object | ||
| * ID and metadata key, the metadata will be added. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1043,6 +1043,34 @@ function add_site_meta( $site_id, $meta_key, $meta_value, $unique = false ) { | |
| return add_metadata( 'blog', $site_id, $meta_key, $meta_value, $unique ); | ||
| } | ||
|
|
||
| /** | ||
| * Adds multiple items of meta data to a site. | ||
| * | ||
| * This function is more performant than calling `add_site_meta()` multiple times because it queries the database | ||
| * only once and clears the meta cache only once. | ||
| * | ||
| * Examples: | ||
| * | ||
| * bulk_add_site_meta( | ||
| * $site_id, | ||
| * array( | ||
| * 'meta_key_1' => 'value_1', | ||
| * 'meta_key_2' => 'value_2', | ||
| * ) | ||
| * ); | ||
| * | ||
| * For historical reasons both the meta key and the meta value are expected to be "slashed" (slashes escaped) on input. | ||
| * | ||
| * @since x.y.z | ||
| * | ||
| * @param int $site_id Site ID. | ||
| * @param array<string,mixed> $meta_fields Metadata values keyed by their meta key. Values must be serializable if non-scalar. | ||
| * @return array<string,int>|false Array of meta IDs keyed by their meta key on success, false on failure. | ||
| */ | ||
| function bulk_add_site_meta( int $site_id, array $meta_fields ) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Site meta is weird, might be best not to make it weirder. It's intended not to accept duplicates and be interacted with via the site option functions, see https://core.trac.wordpress.org/ticket/61467
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the ticket link. This new function uses the same filters and the same cache key(s) as the existing Until https://core.trac.wordpress.org/ticket/61467 is resolved do you think it's best to not introduce a new
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'm inclined not to add the new function while the other ticket is worked out, just to avoid adding to the surface area. |
||
| return bulk_add_metadata( 'site', $site_id, $meta_fields ); | ||
|
johnbillion marked this conversation as resolved.
Outdated
|
||
| } | ||
|
|
||
| /** | ||
| * Removes metadata matching criteria from a site. | ||
| * | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.