Ticket #34848: 34848.6.diff
File 34848.6.diff, 12.6 KB (added by , 6 years ago) |
---|
-
src/wp-includes/meta.php
diff --git src/wp-includes/meta.php src/wp-includes/meta.php index 010822fdc8..fbed19d189 100644
function add_metadata( $meta_type, $object_id, $meta_key, $meta_value, $unique = 132 132 return $mid; 133 133 } 134 134 135 /** 136 * Add multiple metadatas for the specified object. Similar to calling add_metadata for each metadata individually, 137 * and is only applicable for unique meta data. If a meta key already exists for an object it will not be stored. 138 * 139 * @since x.x.x 140 * 141 * @global wpdb $wpdb WordPress database abstraction object. 142 * 143 * @param string $meta_type Type of object metadata is for (e.g., comment, post, or user) 144 * @param int $object_id ID of the object metadata is for 145 * @param array $meta_data Metadata as a key/value pair array. Values must be serializable if non-scalar. 146 * @return int|false The meta ID on success, false on failure. 147 */ 148 function add_metadatas( $meta_type, $object_id, $meta_data ) { 149 global $wpdb; 150 151 if ( ! $meta_type || ! is_numeric( $object_id ) || ! is_array( $meta_data ) ) { 152 return false; 153 } 154 155 $object_id = absint( $object_id ); 156 if ( ! $object_id ) { 157 return false; 158 } 159 160 $table = _get_meta_table( $meta_type ); 161 if ( ! $table ) { 162 return false; 163 } 164 165 $column = sanitize_key( $meta_type . '_id' ); 166 167 /** 168 * Filters whether to add metadata of a specific type. 169 * 170 * The dynamic portion of the hook, `$meta_type`, refers to the meta 171 * object type (comment, post, or user). Returning a non-null value 172 * will effectively short-circuit the function. 173 * 174 * @since 3.1.0 175 * 176 * @param null|bool $check Whether to allow adding metadata for the given type. 177 * @param int $object_id Object ID. 178 * @param array $meta_data Meta data, an array of meta keys and meta datas, meta values must be serializable 179 * if non-scalar. 180 */ 181 $check = apply_filters( "add_{$meta_type}_metadatas", null, $object_id, $meta_data ); 182 if ( null !== $check ) { 183 return $check; 184 } 185 186 $_meta_data = array(); 187 foreach ( $meta_data as $key => $value ) { 188 $check = apply_filters( "add_{$meta_type}_metadata", null, $object_id, $key, $value ); 189 if ( null !== $check ) 190 continue; 191 192 if ( 0 == absint( $wpdb->get_var( 193 $wpdb->prepare( "SELECT COUNT(*) FROM $table WHERE meta_key = %s AND $column = %d", $key, $object_id ) 194 ) ) ) { 195 $key = wp_unslash( $key ); 196 $value = wp_unslash( sanitize_meta( $key, $value, $meta_type ) ); 197 198 $_meta_data[ $key ] = maybe_serialize( $value ); 199 200 /** 201 * Fires immediately before meta of a specific type is added. 202 * 203 * The dynamic portion of the hook, `$meta_type`, refers to the meta 204 * object type (comment, post, or user). 205 * 206 * @since 3.1.0 207 * 208 * @param int $object_id Object ID. 209 * @param string $meta_key Meta key. 210 * @param mixed $meta_value Meta value. 211 */ 212 do_action( "add_{$meta_type}_meta", $object_id, $key, $value ); 213 214 } 215 } 216 217 $rows = array(); 218 if ( ! empty( $_meta_data ) ) { 219 $sql = "INSERT INTO {$table} ({$column}, meta_key, meta_value) VALUES "; 220 221 $comma = false; 222 foreach ( $_meta_data as $key => $value ) { 223 if ( true == $comma ) { 224 $sql .= ','; 225 } 226 227 $sql = $wpdb->prepare( $sql . " (%d, %s, %s)", $object_id, $key, $value ); 228 $comma = true; 229 } 230 } 231 232 $result = $wpdb->query( $sql ); 233 234 if ( ! $result ) { 235 return false; 236 } 237 238 wp_cache_delete($object_id, $meta_type . '_meta'); 239 240 return true; 241 } 242 135 243 /** 136 244 * Update metadata for the specified object. If no value already exists for the specified object 137 245 * ID and metadata key, the metadata will be added. … … function delete_metadata( $meta_type, $object_id, $meta_key, $meta_value = '', $ 462 566 return true; 463 567 } 464 568 569 /** 570 * Delete metadatas for the specified object. 571 * 572 * @since x.x.x 573 * 574 * @global wpdb $wpdb WordPress database abstraction object. 575 * 576 * @param string $meta_type Type of object metadata is for (e.g., comment, post, or user) 577 * @param int $object_id ID of the object metadata is for 578 * @param array $meta_keys Metadata keys to be deleted. 579 * @return bool True on successful delete, false on failure. 580 */ 581 function delete_metadatas( $meta_type, $object_id, $meta_keys ) { 582 global $wpdb; 583 584 if ( ! $meta_type || ! is_numeric( $object_id ) && ! is_array( $meta_keys ) ) { 585 return false; 586 } 587 588 $object_id = absint( $object_id ); 589 if ( ! $object_id ) { 590 return false; 591 } 592 593 $table = _get_meta_table( $meta_type ); 594 if ( ! $table ) { 595 return false; 596 } 597 598 $type_column = sanitize_key( $meta_type . '_id' ); 599 $id_column = 'user' == $meta_type ? 'umeta_id' : 'meta_id'; 600 // expected_slashed ($meta_key) 601 $meta_key = array_map( 'wp_unslash', $meta_keys ); 602 603 /** 604 * Filters whether to delete metadata of a specific type. 605 * 606 * The dynamic portion of the hook, `$meta_type`, refers to the meta 607 * object type (comment, post, or user). Returning a non-null value 608 * will effectively short-circuit the function. 609 * 610 * @since x.x.x 611 * 612 * @param null|bool $delete Whether to allow metadata deletion of the given type. 613 * @param int $object_id Object ID. 614 * @param array $meta_keys Meta keys. 615 */ 616 $check = apply_filters( "delete_{$meta_type}_metadatas", null, $object_id, $meta_keys ); 617 if ( null !== $check ) { 618 return (bool) $check; 619 } 620 621 /** 622 * Fires immediately before deleting metadata of a specific type. 623 * 624 * The dynamic portion of the hook, `$meta_type`, refers to the meta 625 * object type (comment, post, or user). 626 * 627 * @since x.x.x 628 * 629 * @param int $object_id Object ID. 630 * @param string $meta_keys Meta keys. 631 */ 632 do_action( "delete_{$meta_type}_metas", $object_id, $meta_keys ); 633 $sql = $wpdb->prepare( "DELETE FROM {$table} WHERE {$type_column} = %d and meta_key IN( ", $object_id ); 634 $comma = false; 635 foreach ( $meta_keys as $meta_key ) { 636 if ( true == $comma ) { 637 $sql .= ', '; 638 } 465 639 640 $sql = $wpdb->prepare( $sql . " %s", $meta_key ); 641 $comma = true; 642 } 643 $sql .= " )"; 644 $count = $wpdb->query( $sql ); 645 646 if ( ! $count ) { 647 return false; 648 } 649 wp_cache_delete($object_id, $meta_type . '_meta'); 650 651 /** 652 * Fires immediately after deleting metadata of a specific type. 653 * 654 * The dynamic portion of the hook name, `$meta_type`, refers to the meta 655 * object type (comment, post, or user). 656 * 657 * @since x.x.x 658 * 659 * @param int $object_id Object ID. 660 * @param string $meta_keys Meta key. 661 */ 662 do_action( "deleted_{$meta_type}_metas", $object_id, $meta_keys ); 663 664 return true; 665 } 666 466 667 /** 467 668 * Retrieve metadata for the specified object. -
src/wp-includes/post.php
* diff --git src/wp-includes/post.php src/wp-includes/post.php index 45fb3573b8..77419a7f3d 100644
function add_post_meta( $post_id, $meta_key, $meta_value, $unique = false ) { 1823 1823 return $added; 1824 1824 } 1825 1825 1826 /** 1827 * Add meta datas to a post. 1828 * 1829 * Post meta data is called "Custom Fields" on the Administration Screen. 1830 * 1831 * @since x.x.x 1832 * 1833 * @param int $post_id Post ID. 1834 * @param array $meta_data Metadata as a key/value pair array. Values must be serializable if non-scalar. 1835 * @return bool Was the data inserted 1836 */ 1837 function add_post_metas( $post_id, $meta_data ) { 1838 // Make sure meta is added to the post, not a revision. 1839 if ( $the_post = wp_is_post_revision( $post_id ) ) { 1840 $post_id = $the_post; 1841 } 1842 1843 $added = add_metadatas( 'post', $post_id, $meta_data ); 1844 if ( $added ) { 1845 wp_cache_set( 'last_changed', microtime(), 'posts' ); 1846 } 1847 return $added; 1848 } 1849 1826 1850 /** 1827 1851 * Remove metadata matching criteria from a post. 1828 1852 * … … function delete_post_meta( $post_id, $meta_key, $meta_value = '' ) { 1851 1875 return $deleted; 1852 1876 } 1853 1877 1878 /** 1879 * Remove metadatas matching criteria from a post. 1880 * 1881 * @since x.x.x 1882 * 1883 * @param int $post_id Post ID. 1884 * @param array $meta_keys Meta keys that should be deleted. 1885 * @return bool True on success, false on failure. 1886 */ 1887 function delete_post_metas( $post_id, $meta_keys ) { 1888 // Make sure meta is added to the post, not a revision. 1889 if ( $the_post = wp_is_post_revision( $post_id ) ) { 1890 $post_id = $the_post; 1891 } 1892 1893 $deleted = delete_metadatas( 'post', $post_id, $meta_keys ); 1894 if ( $deleted ) { 1895 wp_cache_set( 'last_changed', microtime(), 'posts' ); 1896 } 1897 return $deleted; 1898 } 1899 1854 1900 /** 1855 1901 * Retrieve post meta field for a post. 1856 1902 * … … function update_post_meta( $post_id, $meta_key, $meta_value, $prev_value = '' ) 1900 1946 return $updated; 1901 1947 } 1902 1948 1949 /** 1950 * Update metadatas on a post. This is done by deleting all the post meta and then re-inserting it. 1951 * 1952 * To update post meta another way it would require two calls of update_post_meta 1953 * Each update_post_meta call creates 1 select and 1 update mysql query 1954 * 2 update_post_meta calls creates 2 select and 2 update queries 1955 * update_post_metas creates 1 delete query, 1 insert query, and 1 select for every post meta being added 1956 * 1957 * Updating X metas: 1958 * update_post_meta = X selects, X updates 1959 * update_post_metas = X selects, 1 delete, 1 insert 1960 * 1961 * The benefits of update_post_metas grows the more post metas being updated. 1962 * 1963 * Example: Updating 22 address metas on a post 1964 * update_post_meta = 22 selects, 22 updates 1965 * update_post_metas = 22 selects, 1 delete, 1 insert 1966 * 1967 * @since x.x.x 1968 * 1969 * @param int $post_id Post ID. 1970 * @param array $meta_data Metadata as a key/value pair array. Values must be serializable if non-scalar. 1971 * @return int|bool Meta ID if the key didn't exist, true on successful update, false on failure. 1972 */ 1973 function update_post_metas( $post_id, $meta_data ) { 1974 // Make sure meta is added to the post, not a revision. 1975 if ( $the_post = wp_is_post_revision( $post_id ) ) { 1976 $post_id = $the_post; 1977 } 1978 1979 delete_post_metas( $post_id, array_keys( $meta_data ) ); 1980 1981 $updated = add_post_metas( $post_id, $meta_data ); 1982 if ( $updated ) { 1983 wp_cache_set( 'last_changed', microtime(), 'posts' ); 1984 } 1985 return $updated; 1986 } 1987 1903 1988 /** 1904 1989 * Delete everything from post meta matching meta key. 1905 1990 * -
new file tests/phpunit/tests/meta/BulkMetadata.php
diff --git tests/phpunit/tests/meta/BulkMetadata.php tests/phpunit/tests/meta/BulkMetadata.php new file mode 100644 index 0000000000..f39ded42df
- + 1 <?php 2 3 /** 4 * @group meta 5 * @covers ::update_metadata 6 */ 7 class Tests_Meta_BulkMetadata extends WP_UnitTestCase { 8 9 /** 10 * @ticket 34848 11 */ 12 public function test_adding_bulk_metadata() { 13 add_post_metas( 123, array( 14 'foo' => 'bar', 15 'bar' => 'foo', 16 'array' => array( 17 'foobar' => 'barfoo' 18 ) 19 ) ); 20 21 $foo = get_post_meta( 123, 'foo', true ); 22 $this->assertSame( $foo, 'bar' ); 23 24 $bar = get_post_meta( 123, 'bar', true ); 25 $this->assertSame( $bar, 'foo' ); 26 27 $array = get_post_meta( 123, 'array', true ); 28 $this->assertSame( $array, array( 29 'foobar' => 'barfoo' 30 ) ); 31 } 32 33 /** 34 * @ticket 34848 35 */ 36 public function test_updating_bulk_metadata() { 37 add_post_metas( 123, array( 38 'foo' => 'bar', 39 'bar' => 'foo', 40 'array' => array( 41 'foobar' => 'barfoo' 42 ) 43 ) ); 44 45 $foo = get_post_meta( 123, 'foo', true ); 46 $this->assertSame( $foo, 'bar' ); 47 48 $bar = get_post_meta( 123, 'bar', true ); 49 $this->assertSame( $bar, 'foo' ); 50 51 $array = get_post_meta( 123, 'array', true ); 52 $this->assertSame( $array, array( 53 'foobar' => 'barfoo' 54 ) ); 55 56 update_post_metas( 123, array( 57 'foo' => 'foo', 58 'bar' => 'bar', 59 'array' => array( 60 'foobar' => 'foobar' 61 ) 62 ) ); 63 64 $foo = get_post_meta( 123, 'foo', true ); 65 $this->assertSame( $foo, 'foo' ); 66 67 $bar = get_post_meta( 123, 'bar', true ); 68 $this->assertSame( $bar, 'bar' ); 69 70 $array = get_post_meta( 123, 'array', true ); 71 $this->assertSame( $array, array( 72 'foobar' => 'foobar' 73 ) ); 74 } 75 76 /** 77 * @ticket 34848 78 */ 79 public function test_deleting_bulk_metadata() { 80 add_post_metas( 123, array( 81 'foo' => 'bar', 82 'bar' => 'foo', 83 'array' => array( 84 'foobar' => 'barfoo' 85 ) 86 ) ); 87 88 $foo = get_post_meta( 123, 'foo', true ); 89 $this->assertSame( $foo, 'bar' ); 90 91 $bar = get_post_meta( 123, 'bar', true ); 92 $this->assertSame( $bar, 'foo' ); 93 94 $array = get_post_meta( 123, 'array', true ); 95 $this->assertSame( $array, array( 96 'foobar' => 'barfoo' 97 ) ); 98 99 delete_post_metas( 123, array( 100 'foo', 101 'bar', 102 'array' 103 ) ); 104 105 $foo = get_post_meta( 123, 'foo', true ); 106 $this->assertSame( $foo, '' ); 107 108 $bar = get_post_meta( 123, 'bar', true ); 109 $this->assertSame( $bar, '' ); 110 111 $array = get_post_meta( 123, 'array', true ); 112 $this->assertSame( $array, '' ); 113 } 114 115 }