-
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 all 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 |
|---|---|---|
|
|
@@ -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, $meta_value) | ||
| $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( $row_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 ], $row_object_id, $meta_key, $meta_value ); | ||
| } | ||
|
|
||
| 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( 'blog', $site_id, $meta_fields ); | ||
| } | ||
|
|
||
| /** | ||
| * Removes metadata matching criteria from a site. | ||
| * | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function does not validate that the
$columnsand$rowsarrays are not empty, or that all rows have the same number of elements as the$columnsarray. If a row has fewer or more elements than columns, thearray_combine()call on line 2584 will return false, which is then checked on line 2585. However, if$rowsor$columnsis empty, the function will generate an invalid SQL query. These edge cases should be validated and return false early.