__group__ ticket summary owner _component _version priority severity milestone type _status workflow _created modified _description _reporter Tickets Awaiting Review 60787 get_registered_meta_keys() should allow for late registration to improve performance Options, Meta APIs normal normal Awaiting Review enhancement new has-patch 2024-03-15T22:50:45Z 2024-03-27T15:40:31Z "For a site with many custom post types, custom taxonomies, and tons of custom fields -- the burden of register_meta() can become heavy especially when using a plugin like Advanced Custom Fields, Pods, and others. But we shouldn't have to register every single field on every single page load regardless of whether it's needed. That just drains performance on a given site and requires needless DB/transient/cache requests. The introduction of things like the Block Bindings API rely on fields registered through the REST API. You can register fields with the REST API during the `rest_api_init` action (which yeah, you pretty much have to register everything all at once) but at least it's not every page load. With the Block Bindings API rendering on the front of the site, this requires you having run your fields through `register_meta()` on any given page that might have that field bound. Related dev tutorial: https://developer.wordpress.org/news/2024/02/20/introducing-block-bindings-part-1-connecting-custom-fields/ **Proposed solution:** Run an action at the top of `get_registered_meta_keys()` so a plugin can run `register_meta()` ONLY at the time of that data being needed at the code level." sc0ttkclark Unpatched Bugs 59871 Prime further options in `wp_load_core_site_options()` Options, Meta APIs normal normal Future Release defect (bug) new 2023-11-10T02:00:57Z 2024-01-11T17:43:33Z "In Multisite, individual database queries are made to query a number of commonly used options. On each request: * WPLANG * nonce_key * nonce_salt On each authenticated request: * auth_key * auth_salt The *_(salt|key) requests are only made if the constant is not defined or uses the default phrase `put your unique phrase here`. Follow up to #56913." peterwilsoncc Tickets Awaiting Review 59705 get_metadata_raw() will return false when unserialize() fails Options, Meta APIs 5.8 normal normal Awaiting Review defect (bug) new 2023-10-23T11:16:15Z 2023-10-23T11:16:15Z "The return value of get_metadata_raw() is documented as follows: > * False for an invalid `$object_id` (non-numeric, zero, or negative value), > * or if `$meta_type` is not specified. Source: https://github.com/WordPress/wordpress-develop/blob/trunk/src/wp-includes/meta.php#L596:L597 However, if your metadata contains serialized data that is incorrect for some reason, maybe_unserialize() will (also) return `false`. Source: https://github.com/WordPress/wordpress-develop/blob/trunk/src/wp-includes/meta.php#L661 E.g. `a:2:{s:3:""foo"";b:1;}` is invalid due to it expecting 2 entries, but only 1 is present. History check; It seems to have been made a lot more precise (but missing this minor case): * https://core.trac.wordpress.org/ticket/51797 * https://github.com/WordPress/wordpress-develop/commit/3bb06ce10b8ddac22091803b2e85832ed3ca3b1b" igorsch Unpatched Bugs 59361 update_post_meta() strict checks can cause false negatives Options, Meta APIs normal normal Future Release defect (bug) new needs-unit-tests 2023-09-15T07:47:12Z 2023-09-15T07:47:12Z "Follow up: #22192 {{{ add_post_meta( $post_id, 'key', 1 ); update_post_meta( $post_id, 'key', 1 ); }}} The update should not work, because they are the same. However, the meta meta cache will have ""1"" as a string, and then it will strict compare it to 1 as an integer. Thus, an unnecessary update will run. It is quite common to use integers and booleans directly into these functions. They should be smart enough to recognize that ""1"" == 1 == true and ""0"" == 0 == false, and that any numeric string is also equal to a properly cast integer. The new changes need unit tests. Ticket from which this was spun: #22189, saving navigation menus is slow. cc. @flixos90 @spacedmonkey @joemcgill" mukesh27 Tickets Awaiting Review 59246 update_option returns true, even when the value didn't change, potentially adding back old data Options, Meta APIs normal normal Awaiting Review defect (bug) new has-patch 2023-08-30T07:44:20Z 2024-02-07T17:56:21Z "`update_option` will inconsistently return true/false, depending on whether another update option call is made in the meantime. While this isn't a problem per se, it creates inconsistent and unexpected behavior. ``` $a = get_option( 'a' ); $b = get_option( 'b' ); sleep( 5 ); // placeholder for code that takes some time $b = '2'; update_option( 'b', $b ); update_option( 'a', $a ); // $a didn't change, so it shouldn't update but return false - but it will update and return true ``` Request 2: ``` $a = get_option( 'a' ); $b = get_option( 'b' ); $a = '7'; $b = '3'; update_option( 'b', $b ); update_option( 'a', $a ); ``` Result: Option 'a' will have a value of 1 instead of 7. Why does this happen? `update_option` uses `get_option` to get the $old_value - however the $old_value might in fact be a NEW value that was added in the meantime by another request. This leads to unexpected behavior of `update_option` if called with unmodified data - since `update_option` sometimes behaves seemingly atomically, while in reality it doesn't - but most devs are not aware of this. These are extremely hard to track down bugs for most developers. Possible solution(s): - ignore this issue, and improve documentation to make it clear that `update_option` might update an option even if the value didn't change - if the option was modified in the meantime - add an additional parameter to `update_option` for `$old_value` to have people pass it in for comparison" malthert Tickets Awaiting Review 58993 "metadata_exists() returns incorrect value when ""get_{$meta_type}_metadata"" filter returns false." Options, Meta APIs 6.2.2 normal normal Awaiting Review defect (bug) new 2023-08-07T14:58:38Z 2023-10-30T18:16:14Z "metadata_exists() applies the ""get_{$meta_type}_metadata"" filter. If the $single metadata value is false, 0, an empty string, or an empty array (see https://www.php.net/manual/en/language.types.boolean.php), then metadata_exists() will return false instead of true (ie. the metadata exists). {{{ function metadata_exists( $meta_type, $object_id, $meta_key ) { . . . $check = apply_filters( ""get_{$meta_type}_metadata"", null, $object_id, $meta_key, true, $meta_type ); if ( null !== $check ) { return (bool) $check; } }}} If any value is returned, then the metadata exists, so the code should be: {{{ function metadata_exists( $meta_type, $object_id, $meta_key ) { . . . $check = apply_filters( ""get_{$meta_type}_metadata"", null, $object_id, $meta_key, true, $meta_type ); if ( null !== $check ) { return true; } }}} js." jsmoriss Tickets Awaiting Review 58992 "get_metadata_raw() ""get_{$meta_type}_metadata"" filter can return incorrect value for $single = true" Options, Meta APIs 6.2.2 normal normal Awaiting Review defect (bug) new 2023-08-07T14:52:21Z 2023-10-30T18:10:59Z "The ""get_{$meta_type}_metadata"" filter includes the $single argument for the filter to return a single element or the complete metadata array. **If the single element happens to be an array**, and that array is returned because $single = true, then **the following code breaks the returned value** (it returns the first element instead of the array). If the array is an associative array, then it also breaks the returned value as `$check[0]` is not a valid element. {{{ $check = apply_filters( ""get_{$meta_type}_metadata"", null, $object_id, $meta_key, $single, $meta_type ); if ( null !== $check ) { if ( $single && is_array( $check ) ) { return $check[0]; } else { return $check; } } }}} Since $single is provided to the filter, the code should respect the returned value: {{{ $check = apply_filters( ""get_{$meta_type}_metadata"", null, $object_id, $meta_key, $single, $meta_type ); if ( null !== $check ) { return $check; } }}} js." jsmoriss Tickets Awaiting Review 58904 delete_expired_transients() does not delete expired transient created with a false/empty transient name Options, Meta APIs 6.3 normal normal Awaiting Review defect (bug) new 2023-07-25T19:40:24Z 2023-07-25T19:40:24Z "Due to a typo/bug in my plugin code, I found that WordPress accepts empty strings, null, and false for the $transient arg, aka: the transient name, in set_transient() function which creates transients in the options database with values of simply `_transient_` and `_transient_timeout_`. The empty string transient is not be cleaned up by the `delete_expired_transients()` routine. Related is patch #58903, though I do not feel comfortable making a patch for this issue as the fix requires has SQL calls." jeremyescott Tickets with Patches 58903 set_transient() allows invalid transient name Options, Meta APIs normal normal Future Release defect (bug) new dev-feedback 2023-07-25T19:33:17Z 2024-02-08T20:13:48Z "Due to a typo/bug in my plugin code, I found that WordPress accepts empty strings, null, and false for the `$transient` arg, aka: the transient name, in `set_transient()` function which creates transients in the options database with values of simply `_transient_` and `_transient_timeout_`. That said... the transient created with an empty string continued to work (could be set and get and deleted). Because the typo in my code referenced a variable that held the transient name but was empty, the get, set, and delete function calls worked (annoyingly). I did observer two issues... 1. In the event two developers cause the same mistake/error, their transients will collide with each other. 2. More importantly, I observed the empty string transient will not be cleaned up by the delete_expired_transients routine. (The Transients Manager plugin must use delete_expired_transients() as it could not delete the transient either.) I will submit a second ticket for this issue. Upon review of the set_transient() and add_option() code, I observed several opportunities to improve, including: - return false for empty $transient value - return false for bool, non-scalar $transient values - cast $transient as string - return false for strings with more than 172 characters These false returns will guide developers to fix issues with malformed $transient names. I have a pull request to github ready to follow this ticket." jeremyescott Tickets Awaiting Review 58761 Make the filter option_page_capability_options available when access options.php directly Options, Meta APIs normal normal Awaiting Review defect (bug) new 2023-07-08T05:43:13Z 2023-07-08T05:43:13Z "The problem is that when wp-admin/options.php is accessed directly $option_page is Empty, and the filter for option_page_capability_options is bypassed. For a requirement to prevent direct access to this page, which exposes all WordPress options, this filter is needed to modify the capability from 'manage_options' to 'do_not_allow'. For any other settings page the value of $option_page is set to something other than 'options' and would not be affected by this change. I'd also suggest the 'back compat' comment is irrelevant and could be removed (or at least better explained if it is relevant). The suggested change is from: {{{#!php session_id}"", array() );` It returns an empty value, but the value exists in DB and in cache. I tested with 3 different methods one-by-one for option `_wp_session_5c1f3b8058ca4b6cf9e637c31300bc23`: ==== 1) `get_option` `get_option( ""_wp_session_5c1f3b8058ca4b6cf9e637c31300bc23"", array() );` It returns an empty value (but sometimes it works fine) ==== 2) `wp_cache_get` `wp_cache_get( ""_wp_session_5c1f3b8058ca4b6cf9e637c31300bc23"", 'options' );` It returns correct value {{{ a:6:{s:8:""edd_cart"";s:40:""[{""id"":79377,""options"":[],""quantity"":1}]"";s:13:""edd_cart_fees"";s:0:"""";s:18:""edd_resume_payment"";s:0:"""";s:14:""cart_discounts"";s:0:"""";s:10:""edd_errors"";s:0:"""";s:12:""edd_purchase"";s:1072:""{""downloads"":[{""id"":147706,""options"":[],""quantity"":1}],""fees"":[],""subtotal"":0,""discount"":0,""tax"":""0.00"",""tax_rate"":0,""price"":0,""purchase_key"":""f7f8403a9d9edb93f9be9376d117c1f0"",""user_email"":"""",""date"":""2022-10-31 13:59:43"",""user_info"":{""id"":37847,""email"":"""",""first_name"":"""",""last_name"":"""",""discount"":""none"",""address"":[]},""post_data"":{""edd_email"":"""",""edd_first"":"""",""edd_last"":"""",""edd_agree_to_terms"":""1"",""edd-user-id"":"""",""edd_action"":""purchase"",""edd-gateway"":""manual"",""edd-process-checkout-nonce"":""911cf02037""},""cart_details"":[{""name"":"""",""id"":,""item_number"":{""id"":147706,""options"":[],""quantity"":1},""item_price"":0,""quantity"":1,""discount"":0,""subtotal"":0,""tax"":0,""fees"":[],""price"":0}],""gateway"":""manual"",""card_info"":{""card_name"":"""",""card_cvc"":"""",""card_exp_month"":"""",""card_exp_year"":"""",""card_address"":"""",""card_address_2"":"""",""card_city"":"""",""card_state"":"""",""card_country"":"""",""card_zip"":""""}}"";} }}} ''I removed some private information here.'' ==== 3) direct DB request `$wpdb->get_results('SELECT * FROM wp_options WHERE option_name = ""_wp_session_5c1f3b8058ca4b6cf9e637c31300bc23""')` It returns correct value {{{ Array ( [edd_cart] => [{""id"":79377,""options"":[],""quantity"":1}] [edd_cart_fees] => [edd_resume_payment] => [cart_discounts] => [edd_errors] => [edd_purchase] => {""downloads"":[{""id"":147706,""options"":[],""quantity"":1}],""fees"":[],""subtotal"":0,""discount"":0,""tax"":""0.00"",""tax_rate"":0,""price"":0,""purchase_key"":""f7f8403a9d9edb93f9be9376d117c1f0"",""user_email"":"""",""date"":""2022-10-31 13:59:43"",""user_info"":{""id"":37847,""email"":"""",""first_name"":"""",""last_name"":"""",""discount"":""none"",""address"":[]},""post_data"":{""edd_email"":"""",""edd_first"":"""",""edd_last"":"""",""edd_agree_to_terms"":""1"",""edd-user-id"":""37847"",""edd_action"":""purchase"",""edd-gateway"":""manual"",""edd-process-checkout-nonce"":""911cf02037""},""cart_details"":[{""name"":"""",""id"":147706,""item_number"":{""id"":147706,""options"":[],""quantity"":1},""item_price"":0,""quantity"":1,""discount"":0,""subtotal"":0,""tax"":0,""fees"":[],""price"":0}],""gateway"":""manual"",""card_info"":{""card_name"":"""",""card_cvc"":"""",""card_exp_month"":"""",""card_exp_year"":"""",""card_address"":"""",""card_address_2"":"""",""card_city"":"""",""card_state"":"""",""card_country"":"""",""card_zip"":""""}} ) }}} ''I removed some private information here.'' ---- So the problem only with function `get_option`. I checked this function as well. It selects values for `notoptions`: `$notoptions = wp_cache_get( 'notoptions', 'options' );` And if current option exists in this array – it do return {{{ if ( isset( $notoptions[ $option ] ) ) { /** * Filters the default value for an option. * * The dynamic portion of the hook name, `$option`, refers to the option name. * * @since 3.4.0 * @since 4.4.0 The `$option` parameter was added. * @since 4.7.0 The `$passed_default` parameter was added to distinguish between a `false` value and the default parameter value. * * @param mixed $default The default value to return if the option does not exist * in the database. * @param string $option Option name. * @param bool $passed_default Was `get_option()` passed a default value? */ return apply_filters( ""default_option_{$option}"", $default, $option, $passed_default ); } }}} Current option exists in this array, so it applies filter ""default_option_{$option}"", function filter_default_option. But this function check `get_registered_settings`, and there is no information about this option, so it returns empty result. That’s all information I have so far. This problem exists at least for 1 year, for this time we always update WordPress core and Plugins for latest version, and it does not any effect." planvova Tickets Awaiting Review 56821 meta_query late row lookup for performance improvement Options, Meta APIs normal normal Awaiting Review enhancement new 2022-10-13T20:46:34Z 2022-10-14T11:59:24Z "Is it possible to do a late row lookup for meta_query to make large postmeta sets run much faster? In some benchmarking I've done with load testing, queries that would take 8s to load with the current meta_query ended up loading in 500ms after implementing late row lookup. My suggestion would be to modify the get_posts function in the WP_Query class to have a flag pass through to use late lookup, like passing through `""meta_late_lookup""=>true`: {{{#!php meta_query->queries ) ) { $clauses = $this->meta_query->get_sql( 'post', $wpdb->posts, 'ID', $this ); if(isset($q['meta_query_late_lookup']) && $q['meta_query_late_lookup']){ // perform a late lookup instead of a join $clauses['where'] = ' AND ID in (SELECT post_id FROM '.$wpdb->postmeta.' WHERE 1=1 '.$clauses['where'].')'; } else { $join .= $clauses['join']; } $where .= $clauses['where']; } }}} At the moment, this can be accomplished with a filter like so: {{{#!php ' AND ID in (SELECT post_id FROM '.$meta_table.' WHERE 1=1 '.$sql['where'].')'); return $sql; } }}} " brmoore252 Tickets Awaiting Review 56752 Add get_post_metadata filters by $meta_key Options, Meta APIs normal normal Awaiting Review defect (bug) new 2022-10-06T23:18:56Z 2022-10-12T18:24:06Z "`get_metadata_raw()` applies `get_{$meta_type}_metadata` filters, which means that when trying to filter a single meta key, this function will be executed for EVERY meta key and require a condition that checks for the correct meta key to filter. It would be a great idea to have `get_{$meta_key}_metadata` filters. Since `$meta_key` is some generic string, though, it cannot be used directly, and must be adapted first to suit a PHP function name by replacing any non-alphanumeric character with an underscore." galbaras Candidates for Closure 56548 Introduce `get_option` action Options, Meta APIs normal normal Awaiting Review enhancement new needs-unit-tests 2022-09-11T19:00:11Z 2022-09-11T20:14:00Z "There has been the `option_{$option}` filter for a long time, and it makes sense that this filter should be used to tweak options when reading them. However, there is sometimes a need for running certain logic for when an option is being read. For example, the WordPress performance team is currently working on a feature to optimize the autoloaded options list. For such purposes, we would like to add a new `get_option` action: * The reasoning for making it an action is to not falsely encourage developers to think they could use this to filter an option value (which would be excessive since it would be running for every option read). * The action would get parameters for the option name, the value, and whether the value is based on the default (rather than being looked up from the database). * The action name would be aligned with the existing actions `add_option`, `update_option`, and `delete_option`. * It would be documented so that it should only be used for special cases (similar to e.g. the `all` filter)." flixos90 Tickets Awaiting Review 56326 get_metadata_raw doesn't unserialize when retrieving all meta_keys for a post_id Options, Meta APIs 6.0 normal major Awaiting Review defect (bug) new 2022-08-02T22:43:42Z 2022-08-02T22:43:42Z "(Preface: this is a bug report for WP Core, not BuddyPress - I'm just sharing the following details for context/reproducibility). I'm working with BuddyPress and bbPress, which creates a meta_key ""_bbp_group_ids"" for the forum post when you associate that forum with a buddypress group. The meta_value for this key is an array, which gets serialized by update_post_meta(). When I retrieve all meta_keys for that forum post, it returns an array, but the _bbp_group_ids key has a value of something like ""a:1:{i:0;i:58;}"" When I use xdebug to step through the code, the problem seems to start here in [https://core.trac.wordpress.org/browser/tags/6.0/src/wp-includes/meta.php#L641 get_metadata_raw()]. If the data is in the wp_cache, it then just retrieves and returns that on [https://core.trac.wordpress.org/browser/tags/6.0/src/wp-includes/meta.php#L653 line 653] If it isn't in the cache (such as when I clear it manually in my code to test this), it goes through the motions, eventually ending up here in [https://core.trac.wordpress.org/browser/tags/6.0/src/wp-includes/meta.php#L1172 update_meta_cache()], where it retrieves the data from the database, but then doesn't run maybe_unserialize before setting the cache. Then, we're back to where we were before - with [https://core.trac.wordpress.org/browser/tags/6.0/src/wp-includes/meta.php#L656 line 656 of get_metadata_raw()] just returning whatever is in the cache. It only runs maybe_unserialize if a single meta_key is being requested. So, some sort of looping, maybe_unserialize mechanism has to be either added to update_meta_cache() or to get_metadata_raw(). Of course, people are probably aware of this foible and have thus probably created workarounds to deal with receiving serialized post_meta data... So, I leave it to you guys to figure out how to best address this. " nickchomey Tickets Awaiting Review 56047 test for pre_option_{$option} filter pbearne Options, Meta APIs normal normal Awaiting Review defect (bug) assigned has-patch 2022-06-22T21:54:25Z 2022-06-22T22:07:12Z pbearne Tickets Awaiting Review 55969 The function set_transient should have the autoload argument Options, Meta APIs 6.0 normal normal Awaiting Review enhancement new 2022-06-12T14:28:53Z 2023-11-26T23:10:03Z "The function set_transient should have an argument to decide if a specific transient should be autoloaded or not so. At the moment every transient that is set with the function set_transient is autoloaded. Not all the transients have the need to be autoloaded. For example, many times transients that are used only in the backend don't need the autoload, but they slow down the frontend in some cases." giuse Tickets with Patches 55952 add_option() racy behaviour Options, Meta APIs normal normal Future Release defect (bug) new has-patch 2022-06-09T00:15:52Z 2022-10-07T21:57:27Z "If two or more processes try to add an option via `add_option()` at the same time with both the same value, the following calls to `get_option()` may return `false` as if the option wasn't set. This happens for example if two processes A and B: both reach past the check in https://github.com/WordPress/wordpress-develop/blob/6.0/src/wp-includes/option.php#L622-L624 before any of the two performs the `INSERT`. In this scenario, the first process which gets to execute the `INSERT` will return `true` and will have the correct value in its object cache. The other process's `add_option()` will return `false` and it's object cache will continue to believe the option doesn't exists. https://github.com/WordPress/wordpress-develop/blob/6.0/src/wp-includes/option.php#L640-L641 https://github.com/WordPress/wordpress-develop/blob/6.0/src/wp-includes/wp-db.php#L2116-L2131 https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html#:~:text=0%20if%20an%20existing%20row%20is%20set%20to%20its%20current%20values You can find attached a plugin designed for testing this race condition. " karl94 Tickets Awaiting Review 55889 Allow specifying multiple keys as an array in meta and option retrieval functions. Options, Meta APIs normal normal Awaiting Review feature request new 2022-06-01T08:00:27Z 2022-06-01T12:24:44Z "Allow specifying multiple keys as an array in meta and option retrieval functions like get_option and get_post_meta. Currently when we have to get multiple meta values from multiple keys we have to use get_post_meta without mentioning the key to retrieve everything or make multiple calls to the function for each key. It will be really helpfull and a lot more efficient if one can specify the keys in the function call as follows get_post_meta(post_id, array('key_1, 'key_2'...)) Same applies to get_option." namith.jawahar Tickets Awaiting Review 55600 Can't save registered post meta field of type string that equals registered default value via REST API Options, Meta APIs normal normal Awaiting Review defect (bug) new 2022-04-21T13:47:24Z 2022-04-21T13:47:24Z "== Current behaviour Currently if you register a post meta key as string and set a default value: {{{ register_post_meta( 'my_cpt, 'my_meta', [ 'show_in_rest' => true, 'single' => true, 'type' => 'string', 'default' => 'foo' ] ); }}} and then save the default value it is not actually being written to the database. If you save any other type, e.g. a boolean {{{ register_post_meta( 'my_cpt, 'my_meta', [ 'show_in_rest' => true, 'single' => true, 'type' => 'boolean', 'default' => true ] ); }}} it is being written to the database. Also not saving via the REST API, but via `update_metadata()` works for strings. == What seems to happen The problem seems to happen like this: - Post meta is only saved if it differs from the currently stored value. - So before saving each field the new value is compared with the stored value. - When doing so the assumption is (rightfully) that all stored data is a string since that is how post meta is stored in the DB. - If the key doesn't exist though, the comparison happens with the default value. - The default value though isn't necessarily a string, but is handled as such in the strict equality check. - So the strict equality check fails on anything but a string field. **-> String fields can't save the default value, anything else can.** == How did it come to this? I am not absolutely sure what is actually the intended behavior, but I assume if there is nothing stored in the DB the value should be saved, even if it equals the default. I assume this because the behavior of `update_metadata()` [https://core.trac.wordpress.org/changeset/48402 got changed] to only consider DB data, not default values for the comparison by retrieving the stored data using `get_metadata_raw()` instead of `get_metadata()`. `WP_REST_Meta_Fields` duplicates some of the checks in `update_metadata()` ([https://github.com/WordPress/wordpress-develop/blob/14d9ca8da64688f799695eb9683e6ac8166cd4ee/src/wp-includes/rest-api/fields/class-wp-rest-meta-fields.php#L382 even explicitly states that in a comment]) but `WP_REST_Meta_Fields::update_meta_value()` (and some other places in that class) didn't get the change to use `get_metadata_raw()` instead of `get_metadata()`. I assume this got overlooked when introducing the default metadata values in https://core.trac.wordpress.org/changeset/48402 It seems that replacing get_metadata with get_metadata_raw in that class should fix the issue, but I haven't found time yet to prepare a patch, so I thought I'd at least document the issue for now to see if someone else finds time for a fix before me." kraftner Tickets Awaiting Review 55584 Settings API autoload hook Options, Meta APIs normal normal Awaiting Review enhancement new dev-feedback 2022-04-18T04:56:49Z 2023-08-31T17:43:17Z "Currently all settings registered via Settings API is forced to enable autoload, There is no hook to replace this. Lets imagine just for example: 1. all wordpress plugins is using this to register their settings data. but not delete this value during uninstall. 2. Average wodpress admin install then uninstall 50 plugins in their lifetime. 3. Average autoloaded setting is 100kb per plugin there will be 5mb autoloaded options which not used anymore. that event is per pageload. Just imagine that. " hir88en Tickets Awaiting Review 55553 update_blog_option should accept autoload parameter Options, Meta APIs 5.9.3 normal normal Awaiting Review enhancement new dev-feedback 2022-04-10T21:22:46Z 2024-01-31T21:27:10Z The function update_blog_option doesn't accept any autoload parameter, even though it calls the function update_option that accepts an autoload parameter. giuse Tickets Awaiting Review 54805 When on the /wp-admin/network/site-settings.php network settings page, calling the update_option() always add the setting Options, Meta APIs 5.8.3 normal minor Awaiting Review defect (bug) new 2022-01-13T00:03:48Z 2022-01-13T00:03:48Z "When on the network settings (/wp-admin/network/site-settings.php), the udpate_option() used to update the changed settings always adds the settings whenever the form is submitted. So instead of firing the ""update_option"" action hook after the settings are updated, it still fires the **add_option** action hook every time! Obviously, this should give an error but because there's a bailer when adding option using **ON DUPLICATE KEY UPDATE**, no error is shown." zenithcity Tickets Awaiting Review 54212 Add hooks to get/update/add_option functions Options, Meta APIs 5.8.1 normal normal Awaiting Review feature request new 2021-10-03T04:47:44Z 2023-10-29T06:11:44Z "It would be great if there were hooks in option saving/updating functions so that it would be possible to override usage of `serialize` in favour of `json_encode` when storing option value in DB. `serialize` gives a lot of problems with site URL when moving from one domain to another. I spent about two days already trying to replace site URL after moving the website from local to prod environment. The problem is that my prod website's domain name has couple more characters than my local domain, thus when replaced, the PHP-serialized values in DB become invalid so it breaks the entire website for me. I tried many different tools already, as well as the official `wp search-replace` CLI tool, but it also breaks the website completely, I start getting a lot of SQL-related errors. Please add away to replace that ugly serialize with json!" nik7n Tickets Awaiting Review 54006 Wp Multisite Get, Add, Update and Delete Site Meta Issue. Options, Meta APIs 5.8 normal normal Awaiting Review defect (bug) new dev-feedback 2021-08-25T16:26:30Z 2021-08-27T14:21:30Z "Just working on some code to help with WP Multisite integration... I have noticed that the `add_site_meta` function is currently not working. I had a look through the functions in wp-includes/ms-site.php and found that the first parameter in the 'add_metadata' function called by add_site_meta (line 1012) is 'blog'. I figured since you changed the blogmeta table to sitemeta that something might be amiss. If the metadata is added thus: add_metadata( 'site', 1, 'test_site_feta', 'cheese', false ); All appears to work okay, however this does not; add_metadata( 'blog', 1, 'test_site_feta', 'cheese', false ); Think its a bug...until I had a closer look I had to use MySQL queries to add the site meta. " leeml Unpatched Enhancements 52887 Docs: Clarify why register_meta is necessary Shital Patel* Options, Meta APIs normal minor Future Release enhancement accepted 2021-03-22T19:46:18Z 2021-05-26T22:13:43Z When I was reading register_meta documentation I was confused why register_meta is necessary and where it is used, so I added some clarification. ribaricplusplus Candidates for Closure 52798 delete_option() does not clear cache if option is missing in database. Options, Meta APIs 2.1 normal minor Awaiting Review defect (bug) new dev-feedback 2021-03-12T19:31:51Z 2021-07-19T02:10:10Z "It's an old one, but this is the mirror of #25015. If, for some reason, an object does not exist in the database, but does exist in persistent object cache, calling `delete_option()` will fail and the cached option will continue to exist: {{{ wp> get_option( 'test-option' ); => bool(false) wp> update_option( 'test-option', 'example', false ); => bool(true) wp> get_option( 'test-option' ); => string(7) ""example"" wp> global $wpdb; wp> $wpdb->get_results( 'SELECT * FROM wp_options WHERE option_name=""test-option""' ); => array(1) { [0]=> object(stdClass)#1977 (4) { [""option_id""]=> string(3) ""121"" [""option_name""]=> string(11) ""test-option"" [""option_value""]=> string(7) ""example"" [""autoload""]=> string(2) ""no"" } } wp> $wpdb->delete( $wpdb->options, array( 'option_name' => 'test-option' ) ); => int(1) wp> $wpdb->get_results( 'SELECT * FROM wp_options WHERE option_name=""test-option""' ); => array(0) { } wp> get_option( 'test-option' ); => string(7) ""example"" wp> delete_option( 'test-option' ); => bool(false) wp> get_option( 'test-option' ); => string(7) ""example"" }}} I know what you're thinking, ""Don't ever delete directly on the database."" But recently when I ran into this, manual deletion wasn't the cause. More than likely it was some sort of race condition between distributed database or cache servers, or other arcane edge cases. The end result though was that the cache and database were out of sync and subsequent automated `delete_option()` calls were silently failing to clear the cache. The easiest solution would be to move the cache deletion before the database check: {{{ diff --git a/src/wp-includes/option.php b/src/wp-includes/option.php index 8692db7199..2f4a000ca1 100644 --- a/src/wp-includes/option.php +++ b/src/wp-includes/option.php @@ -648,6 +648,18 @@ function delete_option( $option ) { wp_protect_special_option( $option ); + if ( ! wp_installing() ) { + if ( 'yes' === $row->autoload ) { + $alloptions = wp_load_alloptions( true ); + if ( is_array( $alloptions ) && isset( $alloptions[ $option ] ) ) { + unset( $alloptions[ $option ] ); + wp_cache_set( 'alloptions', $alloptions, 'options' ); + } + } else { + wp_cache_delete( $option, 'options' ); + } + } + // Get the ID, if no ID then return. $row = $wpdb->get_row( $wpdb->prepare( ""SELECT autoload FROM $wpdb->options WHERE option_name = %s"", $option ) ); if ( is_null( $row ) ) { @@ -665,18 +677,6 @@ function delete_option( $option ) { $result = $wpdb->delete( $wpdb->options, array( 'option_name' => $option ) ); - if ( ! wp_installing() ) { - if ( 'yes' === $row->autoload ) { - $alloptions = wp_load_alloptions( true ); - if ( is_array( $alloptions ) && isset( $alloptions[ $option ] ) ) { - unset( $alloptions[ $option ] ); - wp_cache_set( 'alloptions', $alloptions, 'options' ); - } - } else { - wp_cache_delete( $option, 'options' ); - } - } - if ( $result ) { /** }}} but that's also before the `delete_option` hook. Instead, the cache purging logic block could be duplicated right before returning `false`: {{{ diff --git a/src/wp-includes/option.php b/src/wp-includes/option.php index 8692db7199..ab0a3f79f2 100644 --- a/src/wp-includes/option.php +++ b/src/wp-includes/option.php @@ -651,6 +651,19 @@ function delete_option( $option ) { // Get the ID, if no ID then return. $row = $wpdb->get_row( $wpdb->prepare( ""SELECT autoload FROM $wpdb->options WHERE option_name = %s"", $option ) ); if ( is_null( $row ) ) { + + if ( ! wp_installing() ) { + if ( 'yes' === $row->autoload ) { + $alloptions = wp_load_alloptions( true ); + if ( is_array( $alloptions ) && isset( $alloptions[ $option ] ) ) { + unset( $alloptions[ $option ] ); + wp_cache_set( 'alloptions', $alloptions, 'options' ); + } + } else { + wp_cache_delete( $option, 'options' ); + } + } + return false; } }}} but that's not very clean, with that much duplicate code. I'm also open to suggestions if this is even a ""core"" bug, or if it should be the responsibility of the theme/plugin code to make sure the option cache is properly cleared?" emrikol Slated for Next Release 52723 Admin options.php default value to NULL for option_value may lead to MySQL Integrity constraint violation error, potential other bugs Options, Meta APIs 2.7 normal normal 6.6 defect (bug) new needs-unit-tests 2021-03-05T14:26:35Z 2024-02-27T12:01:48Z "It looks like `wp-admin/options.php` set a `null` value by default for any unchecked option: https://core.trac.wordpress.org/browser/trunk/src/wp-admin/options.php#L306 Now, this leads to execute queries like this by `update_option`: UPDATE `wp_options` SET `option_value` = NULL WHERE `option_name` = 'default_pingback_flag' Which is wrong, given the schema explicitly set `option_value` to `NOT NULL`: https://core.trac.wordpress.org/browser/trunk/src/wp-admin/includes/schema.php#L144 This would trigger an integrity constraint violation error by MySQL when in (default) strict mode: Error! SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'option_value' cannot be null To get around this (and for other reasons too, I presume), WordPress currently tries to disable any MySQL strict mode in the `$wpdb` class, with the effect that MySQL silently ""fix"" the error itself: https://core.trac.wordpress.org/browser/trunk/src/wp-includes/wp-db.php#L567 https://core.trac.wordpress.org/browser/trunk/src/wp-includes/wp-db.php#L826 But **not every environment support this**, so there are people out there who cannot save options and they are confused about the reason why, for example: https://www.reddit.com/r/Wordpress/comments/l61rvs/cannot_disable_avatars/ https://wordpress.org/support/topic/discussion-comment-settings-saved-changes-are-not-taking-effect-at-all/ https://wordpress.org/support/topic/wordpress-database-error-column-option_value-cannot-be-null/ A simple solution would be to set a different default value (`0` or even an empty string) in `wp-admin/options.php` and, ''better yet'', **cast any `NULL` value to the same different default value in both `update_option` and `add_option`**. Please note that, without a fix, **this bug may also lead to other nasty side effects**. As a quick fix/test, I successful got around this with this simple filter: {{{#!php ""; echo ''; wp_nonce_field( ""$option_group-options"" ); } }}} It seems a common fix for this on the internet is to pass the 'option_page' value instead. https://wordpress.stackexchange.com/questions/376785/wordpress-error-options-page-setting-not-found-in-the-allowed-options-list if the argument name could be changed to $option_group and the docBlock updated accordingly, that would correct the issue without breaking existing implementations {{{#!php ""; echo ''; wp_nonce_field( ""$option_page-options"" ); } }}} " pe01b6 Tickets Awaiting Review 52360 speed up update_meta_cache with easy fix Options, Meta APIs normal normal Awaiting Review enhancement new 2021-01-25T14:02:57Z 2022-02-15T19:15:09Z "wp-includes/meta.php:1061 {{{#!php get_results( ""SELECT $column, meta_key, meta_value FROM $table WHERE $column IN ($id_list) ORDER BY $id_column ASC"", ARRAY_A ); }}} in this request should avoid ""ORDER BY $id_column ASC"" to speed up this query (at least 3 times faster)" vladislavdavarashvili Tickets Awaiting Review 52345 Transient with expiration never expires when storing expiration failed Options, Meta APIs 2.8 normal normal Awaiting Review defect (bug) new has-patch 2021-01-22T18:09:58Z 2023-06-06T07:45:55Z "When storing a transient that has a timeout with the `set_transient()` function, there is a possibility that storing the transient timeout will fail. When you then try to get the transient with the `get_transient()` function, WordPress just returns it, which basically makes it behave like a transient with no expiration. You can simulate the behaviour using this code: {{{#!php query( $wpdb->prepare( ""SELECT * FROM "". ($site_wide ? $wpdb->base_prefix : $wpdb->prefix). ""options WHERE option_name ='%s' LIMIT 1"", $option_name ) ); } }}} " ttodua Tickets Awaiting Review 50678 Transient: save object with protected attributes will fail Options, Meta APIs 5.3 normal normal Awaiting Review defect (bug) new 2020-07-16T11:16:22Z 2020-07-16T11:16:22Z "When I save a custom object with protected attributes no value is set into database. I think it's because php's serialize function use null bytes (\0) when serializing protected properties. MySql does not complain so function returns true like everthing is normal. See this stack overflow [https://stackoverflow.com/questions/62915246/wordpress-save-object-with-protected-attributes-to-transient-will-fail post]. I'm using: - WordPress 5.3.4 - MySql Ver 15.1 Distrib 10.3.22-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2. - PHP Version 7.3.19-1~deb10u1" mxlq Candidates for Closure 50181 Second params of get_option() not used Options, Meta APIs 5.4.1 normal normal Awaiting Review defect (bug) new dev-feedback 2020-05-15T15:50:44Z 2020-05-18T10:08:43Z "Hello In a develp=opment I have something like {{{ $options = get_option( 'my_option', array() ); foreach ( $options as $option ) { // doing things } }}} The option stored seems to be not unserializable. So when going through https://github.com/WordPress/WordPress/blob/master/wp-includes/option.php#L152 + unserialize() which return false on error the second parameter is not used and we got a Warning. We're not testing `$options` thinking with the second param setted to `array()` will allways return an array... " sebastienserre Tickets Awaiting Review 49948 Site Meta: Adding additional useful functions Options, Meta APIs 5.5 normal minor Awaiting Review enhancement new has-patch 2020-04-18T15:01:46Z 2020-08-04T16:34:55Z "There are useful functions for post meta such as `get_post_custom()`, `get_post_custom_keys()` and `get_post_custom_values()`. These functions do not exist for site meta but they would be useful. I've added `get_site_custom()`, `get_site_custom_keys()` and `get_site_custom_values()` to ms-site.php and created a PR to the GitHub repo. " mikeyhoward1977 Tickets Awaiting Review 49705 Sanitizing input for parameterized queries + update_meta_cache Options, Meta APIs 5.3.2 normal minor Awaiting Review defect (bug) new 2020-03-26T13:52:36Z 2021-05-25T06:13:37Z "**So, should we just pass anything we get straight to the database?** There are definitely things you can check about user input, but this is highly context-dependent. Because sanitization is ill-defined and mis-used, I prefer to call this validation. I checked the WordPress core function which is not sanitized even this is one of the most used function in across the WordPress. In below code get_result with no prepare statement. I don;t know the reason why? {{{ $meta_list = $wpdb->get_results( ""SELECT $column, meta_key, meta_value FROM $table WHERE $column IN ($id_list) ORDER BY $id_column ASC"", ARRAY_A ); }}} This function should be something like this: {{{ $id_list_sanity = implode( ', ', array_fill( 0, count( $id_list ), '%d' ) ); $meta_list = $wpdb->get_results( $wpdb->prepare( "" SELECT $column, meta_key, meta_value FROM $table WHERE $column IN ($id_list_sanity) ORDER BY $id_column DESC"" ,$id_list),ARRAY_A ); }}} Function Name: update_meta_cache File: wp-includes/meta.php Line: #825 " classicalrehan Candidates for Closure 49432 Need of maximum character limit for Site Title Options, Meta APIs low minor Awaiting Review defect (bug) new close 2020-02-14T11:03:40Z 2021-12-14T21:49:41Z "1. There should be a maximum limit of characters for setting up the site title in Admin Dashboard -> Settings -> General. The limit should also be there at time of site setup. 2. Currently, the site title has no limit of characters. This may break the site UI on the frontend. 3. Site title allows to add spaces only, but gets saved as empty." sharduld Tickets Awaiting Review 48855 Updating transient to remove expiration fails Options, Meta APIs 5.3 normal normal Awaiting Review defect (bug) new 2019-12-02T19:50:42Z 2019-12-03T14:09:21Z "When updating a transient using the set_transient method, it fails to update the transient's expiration date. Looking at the code, it appears it's only looking for the expiration and deleting it if a new expiration date is specified. This renders it impossible to switch a transient from having an expiration date to not having one. ex. code: {{{#!php 'custom_prefix_require_update_plugins', 'type' => 'boolean', 'single' => true, 'show_in_rest' => true, ]; register_meta( 'post', '_custom_post_meta_one', $args ); $args = [ 'auth_callback' => 'custom_prefix_require_non_existing_cap', 'type' => 'boolean', 'single' => true, 'show_in_rest' => true, ]; register_meta( 'post', '_custom_post_meta_two', $args ); } add_action( 'init', 'custom_register_post_meta' ); function custom_prefix_require_update_plugins() { if ( current_user_can( 'update_plugins' ) ) { return true; } else { return false; } } function custom_prefix_require_non_existing_cap() { if ( current_user_can( 'this_cap_does_not_exist' ) ) { return true; } else { return false; } } }}} 4. Edit a post or page. Make a change to the post content and click “Publish” or “Update” to confirm that changes work as expected. 5. In the browser console, display the post meta exposed to the REST API by pasting this command and typing enter: {{{ wp.data.select( 'core/editor' ).getEditedPostAttribute( 'meta' ); }}} You should see an object that includes your new custom meta: {_custom_post_meta_one: false, _custom_post_meta_two: false} 6. Update _custom_post_meta_one to 'true' with this command (this persists the data to the Redux store, but not the database): {{{ wp.data.dispatch( 'core/editor' ).editPost( { meta: { _custom_post_meta_one : true } } ); }}} Note that this is just a simplified test case. It emulates a plugin or theme updating meta via the WP API, without having to install a plugin or theme that uses custom post meta and Gutenberg. 7. Click Update in the post editor to save your post meta changes to the database. You'll see **“Updating failed. Error message: Sorry, you are not allowed to edit the _custom_post_meta_two custom field.”.** The thing is, _custom_post_meta_two wasn't actually updated or changed by the user, yet their lack of permissions for _custom_post_meta_two is preventing them from updating _custom_post_meta_one. I looked at doing a comparison check prior to saving for the saved value vs the new value, but because the saved value is always a string when coming from the database, you can't do strict checking, which could be problematic. So I am not sure what the fix needs to be here. " johnstonphilip Unpatched Enhancements 48393 Fix from #38903 prevents options autoload parameter update SergeyBiryukov* Options, Meta APIs normal major Future Release enhancement accepted dev-feedback 2019-10-22T07:46:00Z 2023-08-28T21:00:43Z "This is a follow-up to #38903. 3 years ago fix for not * If the new and old values are the same, no need to update. * But this condition does not check if method call intention was to update autoload field of the option. Currently the issue can be resolved by force update options when update_option method is called with autoload != null and check * If the new and old values are the same, no need to update. * should be skipped." anonymized_16833402 Candidates for Closure 47278 General settings page allows html tag. Options, Meta APIs 5.2 normal normal Awaiting Review defect (bug) new reporter-feedback 2019-05-15T11:38:45Z 2019-05-15T20:07:55Z In the General Settings page, when we add HTML tags into the text fields. It allows admin to save those settings with HTML tags. Please see the screenshot link: [https://prnt.sc/nout9b] parthsanghvi Tickets Awaiting Review 47166 When option gmt_offset is blank, wordpress will give a 500 error Options, Meta APIs 5.1.1 normal minor Awaiting Review defect (bug) new 2019-05-07T11:05:16Z 2019-05-07T11:05:16Z "If for any reason the gmt_offset option is """", wordpress will give a type error: A non-numeric value encountered in /wp-includes/functions.php on line 70 and 162 This can then only be solved by editing the database or reinstalling wordpress as the settings page cannot be loaded. If a default value would be set (e.g. 0), the user can fix the problem in the settings page. " silvanthus Tickets Awaiting Review 46705 "Harden WP core against ""update option"" endpoint vulnerabilities" Options, Meta APIs 5.2 normal normal Awaiting Review feature request new 2019-03-28T19:46:36Z 2019-11-25T11:01:24Z "A fairly frequent problem is plugins failing to perform nonce and permission checks on endpoints servicing their admin pages. Following discovery of such a vulnerability it is usually very straightforward for an attacker to perform a large scale attack defacing or establishing persistent administrative access by modifying the options `siteurl`, `default_role`, `users_can_register`, and likely more. I propose that all updates to these selected critical options in a web context warrant validating there has been a nonce verification and the current user has the capability to manage_options. This would force an attacker to follow a more difficult exploit path, potentially preventing large scale exploitation of these issues. The goal I have in mind here is not to be bulletproof, just to defend against a seemingly common bug class." tsewlliw Tickets Needing Feedback 46660 PHP Warning: Countable Error in update_metadata() Options, Meta APIs normal normal Future Release defect (bug) reopened reporter-feedback 2019-03-26T16:07:33Z 2019-05-27T05:38:24Z "i have updated to the latest wordpress and php 7.3 but somehow i get this error over and over again {{{ PHP Warning: count(): Parameter must be an array or an object that implements Countable in /srv/users/.../apps/.../public/wp-includes/meta.php on line 210: // Compare existing value to new value if no prev value given and the key exists only once. if ( empty( $prev_value ) ) { $old_value = get_metadata( $meta_type, $object_id, $meta_key ); if ( count( $old_value ) == 1 ) { if ( $old_value[0] === $meta_value ) { return false; } } } }}}" betimademi Tickets Awaiting Review 46314 JSON strings in postmeta issue Options, Meta APIs 5.2 normal normal Awaiting Review enhancement new 2019-02-22T11:02:38Z 2019-02-22T13:44:07Z "Using and storing data as JSON is becoming more and more widely used. Also in the course of the increased future use of JavaScript for the WordPress admin area. JSON strings could be part of an serialized array in the postmeta database value. Unfortunately update_post_metadata() removes all backslashes and may destroyes JSON string syntax if protected quotes are included in the JSON string. In general all stored backslashes in postmeta will removed whether from a JSON string or part of an code example value etc. update_post_metadata() should not change the value at all. This is what to expect from this and any other function that takes a value to store that value in the database. update_post_metadata() is used by many plugins and themes without providing wp_slash() to the value before. Is there a chance to solve that problem? Cheers Johann " Jonua Tickets Awaiting Review 45505 get_post_custom() doesn't pull values Options, Meta APIs 5.0 normal normal Awaiting Review defect (bug) new 2018-12-06T21:37:29Z 2018-12-06T22:07:14Z "When you are on a post or page and change the content and reload, so that the autosave post pops up at the top, the get_post_custom() values in custom metaboxes aren't being pulled in. get_post_meta() values however still works in that scenario." dryane Tickets Awaiting Review 45353 Homepage title none static homepage when static blog page is set Options, Meta APIs 4.9.8 normal normal Awaiting Review defect (bug) new 2018-11-14T16:28:58Z 2020-12-22T18:56:19Z "Hi I have issue with the title of teh page in the browser tab. When i use a seo plugin and i have a static blog page set and a non static homepage the none static home page show the static blog page title in the browser tab. I have tested this with wp 20-17 and various other themes and they all have the same issue. I tried AIOSEO and YOAST SEO and even if i enter the title for the nin static homepage i get the title for the static blog page. I reported to both plugin builders and they sais i had to be at wordpress core team. You can read all details here. https://github.com/Yoast/wordpress-seo/issues/11548 1) static blog page none static home page. When Index.php is called is_home = true is_front_page=false 2) static home page none static blog page. When front_page.php is called is_home = false is_front_page=true 3) none static home page and none static blog page (set it to ""your latest posts""). When Index.php is called is_home = true is_front_page=true; Exactly as it should be, But only in case 1) the browser tab has the wrong title ! Please advice how to resolve this issue as the none static home page is not equal to the static homepage and can have different content then the static blog page. It all depends on the theme used if the theme is also pulling the default page content and or has a setting for adding content into the non static home page. One can easily detect the homepage id.... for the none static homepage it is 0 https://github.com/Yoast/wordpress-seo/issues/11548#issuecomment-438643740 is_home() should only be true in case 3) and not in case a static blog page is used and a none static home page. I would like to get this resolved. Please advice. Thanks" BackuPs Candidates for Closure 45273 get_postmeta: Inconsistent behavior of the 'single'-argument Options, Meta APIs normal normal Awaiting Review defect (bug) new dev-feedback 2018-11-03T19:29:48Z 2019-01-16T22:58:54Z "The phpdoc of the ''get_postmeta''-function in meta.php mentions that the ''single''-argument has no effect if ''meta_key'' is not specified. This is not true when the ''get_{$meta_type}_metadata''-filter is used. If this filter returns an array and ''single'' is true only the first item of the array is returned. This not the expected behavior when ''meta_key'' is empty. In my opinion this part: {{{#!php $check = apply_filters( ""get_{$meta_type}_metadata"", null, $object_id, $meta_key, $single ); if ( null !== $check ) { if ( $single && is_array( $check ) ) { return $check[0]; } else { return $check; } } }}} should be replace by: {{{#!php $check = apply_filters( ""get_{$meta_type}_metadata"", null, $object_id, $meta_key, $single ); if ( null !== $check ) { if ( $meta_key && $single && is_array( $check ) ) { return $check[0]; } else { return $check; } } }}} (Notice how I added {{{$meta_key && }}}) NOTE: This is a breaking change in the rare occasion that ''get_{$meta_type}_metadata''-filter is used in combination with an empty ''meta_key'' and ''single'' == true. If a fix is not desired; phpdoc must be changed to document this inconsistent behavior. " josk79 Tickets Awaiting Review 45078 null is being set on a NOT NULL options_value column in the options table. Options, Meta APIs normal normal Awaiting Review defect (bug) new has-patch 2018-10-11T07:01:48Z 2020-01-05T21:50:59Z "The {{{options}}} table doesn't allow a NULL value in the {{{options_value}}} column. https://core.trac.wordpress.org/browser/trunk/src/wp-admin/includes/schema.php#L144 But, if an option is unchecked, it is set to null by default here: https://core.trac.wordpress.org/browser/trunk/src/wp-admin/options.php#L275 This throws a {{{Column ‘option_value’ cannot be null}}} error if strict mode({{{STRICT_TRANS_TABLES}}}) is enabled in the database. If strict mode isn't enabled, MySQL converts the null value to a default value, in this case, an empty string, before adding it to the {{{options}}} table. If you are not using strict mode, then whenever you insert an “incorrect” value into a column, such as a NULL into a NOT NULL column or a too-large numeric value into a numeric column, MySQL sets the column to the “best possible value” instead of producing an error https://dev.mysql.com/doc/refman/5.7/en/constraint-invalid-data.html The proposed fix changes the default value from null to an empty string(following MySQL). This will prevent the error being thrown when strict mode is enabled and otherwise won't alter the values inserted into the {{{option_value}}} column." wpshades Tickets Awaiting Review 44977 Transient fill fail delete to itself if it's timeout option is missing Options, Meta APIs normal normal Awaiting Review defect (bug) new 2018-09-21T11:25:44Z 2018-09-23T12:47:02Z "Just faced this issue - for some reason, the transient was not deleting itself. While checking the DB, the option with the transient was there, while the timeout option was missing (probably a glitch while saving to DB). Now, if you check get_transient() in option.php (quick link https://core.trac.wordpress.org/browser/tags/4.9.8/src/wp-includes/option.php#L0 ) you can see that these are deleted only if both exist and both pass the test: {{{ [...] if ( false !== $timeout && $timeout < time() ) { DELETING TRANSIENT} [...] }}} Otherwise transient will hang... forever. This should be tuned up so it also checks that these options exist, and delete transient if timeout is absolete." nlozovan Tickets Awaiting Review 44659 Display custom fields Options, Meta APIs normal normal Awaiting Review feature request new 2018-07-27T23:10:34Z 2019-01-16T06:40:52Z "There should be an option to display custom field data without having to acquire a plugin, rely on a theme supporting it, or hack a theme; surely this can be achieved in core, programmatically. Options could/should include (in order of importance): Global Admin settings to: 1. Enable/disable the display of raw custom field data in a post 2. Option to rewrite outputted field data (add wrapper) that may include HTML 3. Specify where in a post, the field is output, depending of available hooks 4. Specify optional regex validation 5. Specify optional data regex replacement on output 6. Specify which options above, are returned via the API to other plugins 7. Specify optional CSS for any classes and IDs added in (2) above. 8. Specify whether a custom field should be a requirement/optional 9. Specify where the custom field box should appear on the post edit page 10. Option to rewrite outputted field data using PHP snippet Even implementing only items 1-3 would provide a powerful and flexible way to manage meta data, and provide WP v5 with a significant improvement over earlier versions." iantresman Tickets Awaiting Review 44459 Options added to the Permalinks admin page do not get saved Options, Meta APIs normal normal Awaiting Review defect (bug) new 2018-06-25T17:23:39Z 2018-06-26T16:10:24Z "When a new option with matching field is registered to show on the Permalink admin page, it will show there just fine but the setting will never be saved to the database. This seems due to the fact that wp-admin/options-permalink.php submits to itself, not to options.php To reproduce: 1. Register a test option to the permalink group: {{{#!php function register_test_base_setting() { $args = array( 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field' ); register_setting( 'permalink', 'test_base', $args ); } add_action( 'admin_init', 'register_test_base_setting' ); }}} 2. Add settings field to the permalink group, at the optional section: {{{#!php function add_test_base_settings_field() { add_settings_field( 'test_base', 'Test base', 'test_base_settings_field', 'permalink', 'optional', array( 'label_for' => 'test_base' ) ); } add_action('admin_init', 'add_test_base_settings_field' ); function test_base_settings_field( $args ) { global $blog_prefix; $test_base = get_option( 'test_base' ); echo $blog_prefix; ?>"" class=""regular-text code"" /> Permalinks and try to set a value and save the setting. What is expected: the setting gets (a) passed to the sanitize callback and then (b) saved to the DB. What happens: nothing of these two. There is really no point of the `do_settings_fields('permalink', 'optional')` and `do_settings_sections('permalink')` in wp-admin/options-permalink.php if options added though these hooks will never get treated. " RavanH Tickets with Patches 44387 Add support for site meta in `register_meta()` Options, Meta APIs 5.1 normal normal Future Release enhancement new needs-unit-tests 2018-06-17T13:36:33Z 2019-09-20T23:23:10Z "#38323 adds subtype handling to `register_meta()`. These efforts include introducing a function `get_object_subtype()` which returns the object subtype of a given type and ID combination. For the initial merge, this only includes the single site types ""post"", ""term"", ""comment"" and ""user"". Since [42836], sites in a multisite also support metadata, so they should receive subtype support as well. Since sites do not actually use subtypes at this point, we basically only need to add a clause which checks whether a site with the given ID exists, and if so, return the type identifier. The tricky part into which we need to put some thought is the naming: Sites have been historically called ""blogs"", and WordPress core aims to get rid of the legacy naming in its APIs (and only the database schema remains untouched). For example, there are wrapper functions like `get_site_meta()`, but they actually call the low-level meta functions like `get_metadata( 'blog', ... )` because those are tightly coupled to the DB schema. Since registering site meta would be new, we should consider actually naming the type ""site"" here, and then only internally handling the ""blog"" part of it. However, this may introduce unexpected inconsistencies with other areas, so we need to investigate whether this is a wise choice or not. I'd generally argue the simplest solution would be to introduce `register_site_meta()` and `unregister_site_meta()` and otherwise keep the ""blog"" name (which would be consistent with the way existing site meta wrappers work) - however we decided wrappers should only be introduced for object types that use subtypes, so here with sites, developers would actually need to call `register_meta( 'blog', ... )` themselves which would be sub-optimal. Let's discuss." flixos90 Tickets Awaiting Review 44238 Add protected param to register meta Options, Meta APIs 3.1.3 normal normal Awaiting Review enhancement new has-patch 2018-05-26T12:17:19Z 2019-02-24T23:05:09Z "It has been possible for developers to make meta keys protected / not protected since 3.2.0, when the is_protected_meta filter was added. By default all meta keys that start with an underscore as seen as protected, all those this overriden by the filter. There should be a way to a meta key as protected while using register_meta function. This would make the register meta function, a point of truth for all meta keys / meta type, where a state, type and access are defined in one place. " spacedmonkey Tickets Needing Feedback 44042 Hook for ‘delete_option’ behaviour required Options, Meta APIs 1.2 normal normal Future Release enhancement new dev-feedback 2018-05-11T07:45:45Z 2022-06-02T13:51:37Z "Hi, I posted this about one month ago in the wordpress support forum: [https://wordpress.org/support/topic/hook-for-delete_option-behaviour-required/] I did not receive any answers there but referred to this forum, so I post it here again:\\ Hi, I would need to prevent and change the deletion of certain options by the WP core function ‘delete_option’. There is a hook {{{ do_action( 'delete_option', $option ); }}} available here: [https://core.trac.wordpress.org/browser/tags/4.9.4/src/wp-includes/option.php#L532]\\ But this does neither provide a way to exit the delete_option function before the option is deleted nor to change the option name to be deleted. In fact this existing hook seems to be pretty useless. Therefore I would need a filter in the first line of the delete_option core function like {{{ $option = apply_filters( 'delete_option_name', $option ); }}} . Or change the line 535 from {{{ $option = trim( $option ); }}} to {{{ $option = trim( apply_filters( 'delete_option_name', $option )); }}} Any chances to get this into core immediately?\\ Thx, Robert " RobertoDonPedro Tickets Awaiting Review 43818 Invalidate query caches less aggressively by using a `last_changed` key specific to metadata Options, Meta APIs normal normal Awaiting Review enhancement new needs-unit-tests 2018-04-20T08:13:55Z 2018-04-20T08:13:55Z "Currently, the meta implementations for posts, terms, comments and sites (in multisite) invalidate all respective query caches when any value is changed (via setting the `last_changed` key). This is a really aggressive method of cache invalidation and causes in query caches being too frequently invalidated, resulting in lots of unnecessary cache misses. Most queries (or at least many queries) do not make use of meta queries, and those should stay unaffected by when a meta value changes. Therefore I suggest introducing a specific `meta_last_changed` cache key, and have the meta functions set that one instead of the generic `last_changed`. In the query classes, we can then check if a meta query is present, and only then make use of the `meta_last_changed` key - otherwise we can ignore it and use the regular `last_changed` key. Regarding the initial implementation, we should think about whether we would wanna roll this out to all the above object types immediately, or whether we should rather start with an object type less popular for metadata (i.e. ''not'' posts). Related to this is #43813." flixos90 Tickets Awaiting Review 43704 pre_option_{$option} filter is case sensitive although options are not. Options, Meta APIs 4.9.5 normal normal Awaiting Review defect (bug) new 2018-04-05T18:38:44Z 2018-04-08T01:53:12Z "I noticed the filter ""pre_option_{$option}"" for myOption wouldn't filter get_option('MYOption') for example, yet get_option(name) and MySql in general does not seem to care what case the option is. Perhaps it should also do pre_option_(strtolower($option)) when necessary? Was there a reason this particular filter is case-sensitive?" programmin Tickets Needing Feedback 43598 site-options notoption only queried and never set in not multisite wordpress installs SergeyBiryukov Options, Meta APIs 4.9.5 normal normal Future Release enhancement reviewing dev-feedback 2018-03-21T10:08:34Z 2019-09-23T23:15:04Z "We have notoptions mechanism that works well. WordPress core does also query $network_id:notoptions regardless of multiste. However, such option is set only in multisite installs. As a result, if you are not running multisite, you are only querying for $network_id:notoptions and you never set it. It beats the idea of notoptions - we read it, but we never set it - what's the point? Possible solutions: - read $network_id:notoptions only in multisite installs - set $network_id:notoptions also in not multisite installs" Grzegorz.Janoszka Tickets Awaiting Review 43451 Disallow objects as meta values Options, Meta APIs 4.9.2 normal normal Awaiting Review feature request new 2018-03-01T13:01:21Z 2018-03-01T14:13:31Z "OK, I know this is probably going to be closed before anyone even reads it, but I recon it's worth to at least try and spark a discussion. As probably many people know at this point meta functions do not like backslashes. For some reason (probably db related) meta and option add / update functions run all values through `stripslashes_deep`, which means they expect the input values to be slashed. Actually this ""requirement"" seems to be undocumented even though it's here since version 3.something, why, that's beyond me. So, imagine you're a noobie WordPress developer and for some reason you have a backslash in a string you want to persist (happens more often than one might think), so you go ahead and run the following code: {{{#!php $value = 'hello \world'; update_user_meta(get_current_user_id(), '_test', $value); $meta = get_user_meta(get_current_user_id(), '_test', true); var_dump($value, $meta); }}} You save `hello \world` and expect to get `hello \world` back, but surprise surprise, the backslash is gone. So you start scratching your head, dig through stackoverflow or the source and you discover `$meta_value = wp_unslash($meta_value);`. You think this isn't right, but who are you to argue with software that's here for more than 10 years already. So, now, you are a bit more ""experienced"" and know you need to run all your values through `wp_slash` **before** you pass it to the meta functions. Then one day you need to save an array, you read through the docs which doesn't seem to forbid it, so you glance at the source and see `$meta_value = maybe_serialize( $meta_value );` - YES! - you say, you can pass basically anything and WordPress will take care of the serialization, awesome! So, now you run: {{{#!php $value = [ 'hello' => 'again \world' ]; update_user_meta(get_current_user_id(), '_test', wp_slash($value)); $meta = get_user_meta(get_current_user_id(), '_test', true); var_dump($value, $meta); }}} Which results in the same input you gave it, now that you know you need to slash everything. You weren't sure `wp_slash` could actually handle arrays, but it does, so life's good! Later on you mature even more and decide you want to save whole objects now. You know about serialization, so no worries here, right? You adapt your previous code and try to run the following: {{{#!php $value = new \stdClass(); $value->hello = 'world \again'; update_user_meta(get_current_user_id(), '_test', wp_slash($value)); $meta = get_user_meta(get_current_user_id(), '_test', true); var_dump($value, $meta); }}} ...and you get `Warning: addslashes() expects parameter 1 to be string, object given in`. Turns out `wp_slash` can't handle objects :| Alright, maybe you don't need it, so you remove it aaand the slash is gone. Then you look at the code and realize now the slash is gone even from your original object! What the... So trying to store an object as a meta value is not only not gonna work properly, but it's also going to mess with your original object! So, what then? Serialize it into a string before and after? OK, you serialize the object so it's just a string now, then run it through `wp_slash` to fix the slashes issue and then give it to the meta function: {{{#!php $value = new \stdClass(); $value->hello = 'world \again'; update_user_meta(get_current_user_id(), '_test', wp_slash(serialize($value))); $meta = unserialize(get_user_meta(get_current_user_id(), '_test', true)); var_dump($value, $meta); }}} Whew, finally everything works just fine, even though you're not absolutely sure you've covered all possible cases making sure nothing can ever go wrong again. ---- So, can anyone elaborate on this a bit more? Why are slashes such a big problem when it comes to options and meta, shouldn't the value just be converted to a string and then treated as a black box all the way up to when it needs to go in the database? Why does object serialization cause so much trouble? You can't seriously expect users to be aware that their objects are going to be deepslashed to death, values of properties modified to god-knows how deep, and be okay with it. If meta functions can't handle objects, just don't allow objects, shift the responsibility to the user, but be blunt about it. Don't say, //it's okay, we're gonna take care of serialization for you//, then strip the slashes off of properties of deep objects which might not even be part of WordPress whatsoever. This is a debugging nightmare. Lastly I would like to apologize for my tone, but I've dealt with this issue for years now. There are bug reports opened 7 years ago that still haven't been resolved properly. If nothing else it's really surprising to me that we're at 4.9.4 and such a mundane activity (persisting objects in meta) can cause so much trouble. Is it just me having these issues? Does no one else serialize stuff?" tonybogdanov Candidates for Closure 43360 Third parameter for get_option function to return default value instead of empty string Options, Meta APIs 4.9.4 normal normal Awaiting Review enhancement new close 2018-02-19T21:47:16Z 2022-05-26T10:20:04Z "`get_option($option, $default = false)` function returns empty string if the required field exist but doesn't contain any value e.g. NULL or empty string. For example, there is an option field 'test' exist in the option table but without any value(NULL or empty). Now `get_option('test', 'Hello World')` function will return an empty string as it is; from the database but developer may be expecting ""Hello World"" in return. To avoid this situation third parameter may be introduced for `get_option()` function which will decide to return NULL/empty-string or default value. Here is my proposed solution `get_option( $option, $default = false, $return_null = true)` Now calling `get_option('test', 'Hello World', false)` function for above problem will return default value which is '''Hello World'''. wp-includes\options.php file requires little changes to address the above enhancement." farhan.noor Candidates for Closure 43209 REST API should take settings errors into account Options, Meta APIs normal normal Awaiting Review enhancement new dev-feedback 2018-02-01T23:59:10Z 2018-02-01T23:59:10Z "The `WP_REST_Settings_Controller` should notify the client when updating a setting fails due to an invalid value provided per the setting's `sanitize_callback` (should actually be validation, see related #43208). Currently this goes completely unnoticed. While `update_option()` doesn't return any information like that, it may be possible to use the information passed to `add_settings_error()` in case of a validity issue, and forward that to the client by returning a `WP_Error` with the message." flixos90 Candidates for Closure 43208 Separate setting validation from sanitization Options, Meta APIs normal normal Awaiting Review enhancement new needs-unit-tests 2018-02-01T23:45:12Z 2020-11-06T23:12:25Z "As widely known, validation is different from sanitization. A value should first be validated and then be sanitized. Historically, WordPress has been mixing these two responsibilities in the `sanitize_option()` function, however it is easily possible to add an extra layer on top of that which maintains full backward-compatibility. Newer parts of core, such as the Customizer and the REST API, have been dealing with this in a better way, keeping the two separate. We can achieve the same for options themselves too. I suggest introducing a `validate_option_{$option}` filter that works somewhat similar like the `customize_validate_{$setting_id}` filter used in the Customizer. It passes an empty `WP_Error` object that can be added to. In addition to allow separate validation from sanitization, it also makes handling of validation easier, since it can then automatically set the value to the previous value and call `add_settings_error()`, passing any error messages set, which matches current core behavior." flixos90 Tickets Awaiting Review 43069 Docs: improve documentation for register_meta() function Options, Meta APIs 4.9.1 normal normal Awaiting Review defect (bug) new has-patch 2018-01-11T16:23:29Z 2018-01-11T16:33:40Z "The documentation for the `register_meta()` function would benefit from additional clarity to help developers recognize that the `$object_type` parameter does not mean custom post type and the implications that registering the meta field applies to all objects of a type. Within that method there are also missing default values and optional markers in the docblock as well as a backwards compatibility comment that could be more specific and useful in an inline comment. https://developer.wordpress.org/reference/functions/register_meta/" terriann Slated for Next Release 42441 Disable autoload for large options flixos90 Options, Meta APIs normal normal 6.6 enhancement reviewing commit 2017-11-06T02:20:50Z 2024-03-27T15:52:51Z "A frequent issue I encounter with WordPress sites is extreme slowdown due to a huge option that is being autoloaded. Sometimes this is some sort of cache option that a careless plugin has let be autoloaded, and has grown to tens of megabytes. Having an option this large be autoloaded not only slows downs the options loading query (when that option may not be required on every load), but on sites with object caching, it causes a lot of wear and tear on the alloptions cache. Combine a large option with a frequently updated option and you have a recipe for a very sluggish site. We should consider preventing options from being autoloaded if they grow to a certain size. Off the top of my head, 100kb sounds like a reasonable upper bounds. We could monitor option settings/updates and peek at the size of the option going in. If it's above a certain (filterable) bounds, we can force autoload to be off." markjaquith Tickets Needing Feedback 42193 Select text in readonly textarea on focus Options, Meta APIs 4.9 normal normal Future Release enhancement new has-patch 2017-10-12T09:30:03Z 2018-09-17T16:59:54Z "[[Image(https://ibin.co/3dVwFgRPo6d1.png)]] It would be better if the text is selected when the user clicks (focus) on a read-only textarea, especially when it's meant to be copied, for example in the Network Setup section, a user has to copy-paste in the wp-config.php or the .htaccess file." NomNom99 Candidates for Closure 42012 Do not switch roles and capabilities when accessing options through `*_blog_option()` Options, Meta APIs normal normal Awaiting Review enhancement new dev-feedback 2017-09-27T21:51:32Z 2021-08-03T11:42:38Z "[41625] has outsourced the functionality to switch the current user's capabilities and available roles when sites are being switched, instead this now happens in `wp_switch_roles_and_user()` which is hooked into the `switch_blog` action. When accessing `get_blog_option()`, `add_blog_option()`, `update_blog_option()` or `delete_blog_option()`, it should be safe to always unhook the function temporarily (see `WP_Roles::get_roles_data()` for an example where it already happens manually in core) to improve performance, in some cases significantly. Roles and capabilities are not needed when accessing options, however we need to be careful and think about what plugins are possibly doing here. Let's discuss whether this can happen automatically in core or whether it should be left to developers." flixos90 Tickets Awaiting Review 41769 Custom function to display all values of a custom field (meta_key) Options, Meta APIs normal normal Awaiting Review feature request new 2017-08-31T13:25:35Z 2017-09-01T16:06:45Z "If possible, add an extra function where we can list all values of a certain custom field (meta_key). All functions I've found so far is only post id related (e.g get_post_custom_values, etc). While any developer can build this themselves, I do think other wp users could benefit from it as well if it's simly part of the core. Thanks." mireillesan Tickets Awaiting Review 41604 REST API: Attempting to create or update a non-existent setting doesn't return an error response Options, Meta APIs normal normal Awaiting Review defect (bug) new 2017-08-10T16:35:44Z 2017-08-10T16:37:07Z "Attempting to create a new setting via a POST request to `/wp/v2/settings` returns a 200 response, despite the request having been invalid. The same goes for attempting to update a non-existent setting with a PUT request. I would have expected maybe a 400 from such requests. The internal logic in `WP_REST_Settings_Controller` routes the request through the `update_item()` method, treats it as a setting update, and silently ignores the problem. " johnbillion Tickets Awaiting Review 41105 Fire action hook after updating option group. Options, Meta APIs 4.9 normal normal Awaiting Review enhancement new has-patch 2017-06-20T19:45:35Z 2017-06-20T19:50:52Z "This suggestion affects the Settings API. There are hooks that fire after updating a single option, but not when a group of options is updated. Options updated via the Settings API are handled by /wp-admin/options.php, which after updating them does a redirection to the previous page, not firing any hook beside the shutdown action hook. In fact, the shutdown hook could be used for the same purpose but it would require some more extra checks. Basically the hook would allow to perform some action that is required after all options in that group are updated." mdifelice Tickets Awaiting Review 41099 update_option return value ambiguous Options, Meta APIs 4.8 normal normal Awaiting Review enhancement new 2017-06-19T20:58:45Z 2019-04-15T16:37:15Z "WordPress 4.8 The return value 'false' does not allow for differentiating if there was an error saving or if the option value already exists and is the same as the new value. Consider this scenario: a plugin sends option values via AJAX to be updated. The AJAX function returns the return value of 'update_option' which determines the feedback provided to the user, such as a 'success' or 'failure' message. Rather than returning 'false' if an option already exists and is the same as the new option, I suggest returning NULL. In this way the return value of 'update_option' can be checked as follows: {{{#!php if ( is_null( update_option( $option, $value, $autoload) ) ) { ... } // option exists and value is the same as existing option value if ( false === update_option( $option, $value, $autoload) ) { ... } // an error occured when saving the option if ( update_option( $option, $value, $autoload) ) { ... } // option updated successfully }}} The 'update_option' function would need line 308 changed from: {{{#!php return false; }}} to: {{{#!php return NULL; }}} " cloughit Tickets Awaiting Review 40642 Add new filter to populate_options Options, Meta APIs 1.5 normal normal Awaiting Review enhancement new dev-feedback 2017-05-02T20:05:34Z 2017-05-02T20:12:33Z The populate_options is used in the install of WordPress, both single and multisite. When creating options, it loops around an array of default options. Adding a filter to this array, would allow for new settings to be populated on install. spacedmonkey Tickets Awaiting Review 40523 populate_options doesn't use correct add_options actions Options, Meta APIs 1.5 normal normal Awaiting Review enhancement new dev-feedback 2017-04-21T23:17:27Z 2017-05-02T20:15:25Z populate_options is a special function, used to populate default option in the options table. To populate the options table, a single (and large) insert is used. Because the add_option isn't used, it means none of that functions actions are run. spacedmonkey Tickets Awaiting Review 40369 Mail server settings page (options-writing.php) has no validation Options, Meta APIs 4.7.3 normal normal Awaiting Review defect (bug) new has-patch 2017-04-05T10:55:59Z 2017-04-05T10:58:35Z "wp-admin > options-writing.php 1. Accepts everything. No character type restriction 2. Page gets submitted with anything entered in PORT textbox 3. Setting gets saved without values entered in Login name and Pass word boxes 4. Pass word box should now show actual characters!" subrataemfluence Tickets Awaiting Review 40353 Site URL and Home URL inputs are not properly validating loru88 Options, Meta APIs normal normal Awaiting Review defect (bug) assigned has-patch 2017-04-04T12:33:11Z 2020-04-08T20:34:50Z "In wp-admin/options-general.php > General settings the URLs not properly validating. I tried the following with WordPress address (URL) input: http://local.mysite. com http://local.my?site.com http://local.my*site.com In all three cases WP saves the entry and then the page breaks! A proper handling is required." subrataemfluence Tickets Awaiting Review 40115 Duplicate Custom Fields are created Options, Meta APIs 4.7.3 normal normal Awaiting Review defect (bug) new has-patch 2017-03-12T09:16:44Z 2017-03-15T09:25:56Z "Duplicate custom fields are created when populating multiple custom fields at once. Steps to reproduce: * Create a New Post * Add a custom field ""custom_1"" with a value ""test1"" * Add a custom field ""custom_2"" with a value ""test2"" * Save Draft ...you will now see the ""custom_2"" field repeated twice (both with a value of ""test2""), so ought to delete one." ChrisBAshton Candidates for Closure 40012 Only add_metadata if no matching value Options, Meta APIs 2.9 normal normal Awaiting Review defect (bug) new dev-feedback 2017-03-02T02:04:43Z 2017-03-02T02:58:15Z "`add_metadata()` has a `$unique` parameter, but it only looks for a unique `meta_key` for the given object ID. I have a need to add meta-data with the same `meta_key` but different values, and only if that `meta_value` isn't already present with the same key. To do this now, requires: * Getting all meta-data for the ID by `meta_key` * Checking those array-values for my value * Bailing if it's already present, or... * Proceeding with `$unique` set to `false` It'd be lovely if `add_metadata()` either: * Accepted strings like `key`, `value` for the `$unique` parameter, to switch up the check * Added a second parameter for unique value in addition to a unique key" johnjamesjacoby Tickets Awaiting Review 39706 Add $unique param to add_{$meta_type}_meta actions Options, Meta APIs normal normal Awaiting Review enhancement new 2017-01-26T17:11:05Z 2017-01-26T17:16:36Z "The hooks `add_{$meta_type}_meta` and similar provide context about `$object_id`, `$meta_key`, `$_meta_value` and such, but do not tell whether the meta data added or updated is supposed to be `$unique`. Adding this information could be helpful. My use case for instance is propagating meta data across posts." barryceelen Tickets Awaiting Review 39286 Standardizing actions and filters for adding, getting, setting, updating, and deleting options and transients Options, Meta APIs normal normal Awaiting Review enhancement new 2016-12-14T21:46:09Z 2022-07-21T14:33:56Z "== The Problem == In a nutshell, the problem is that there is no standardization of hooks surrounding the options and transient APIs and the hooks presently available are inconsistent in their terminology. === Issue 1: Add Option === When adding an option to the database, there are presently 3 hook available: * `add_option` * `add_option_{$option}` * `added_option` There are two main points of confusion: * The first point of confusion is that `add_option` is fired before the option is added to the database, but `add_option_{$option}` is fired after the option is added. * The second is that prior to the option being added to the database, there is a hook available that will fire anytime an option is added, while there are two hooks fired after the option is added. There is no hook available prior to the option being added to the database that fires for the specific `$option`. These same two issues are present for updating and deleting options. === Issue 2: Get Option === When getting an option from the database, there are only two hooks fired: * `pre_option_{$option}` * `option_{$option}` The first is fired before the option is getted from the database and the second after. The problems are that: * Unlike adding, updating, and deleting, there is no verb in this hook to tell what is being done * There are no hooks that fire for every option getted from the database === Issue 3: Delete Transient === Transients are sort of like options. Without an external object cache, WordPress stores them in the options table of the database. It would make sense that the hooks available for transients are consistent with those available for options. If we look at deleting a transient, there are two hooks available: * `delete_transient_{$transient}` * `deleted_transient` ( The same issues are present with site transients. ) Remembering issue 1 above, there are presently three hooks available when deleting and option. * `delete_option` * `delete_option_{$option}` * `deleted_option` There are a couple issues: * There is no hook present that will fire every time a transient is deleted, either before or after * The `delete_transient_{$transient}` is fired BEFORE the transient is deleted in contrast with the `delete_option_{$option}` hook which is fired AFTER the option is deleted. === Issue 4: Pre === Prior to getting and setting transients, the hooks all start with `pre_`. But this prefix is used inconsistently throughout. * It is not used prior to deleting the transient * It is used prior to getting an option, but not prior to adding, updating or deleting == Proposal == === Structure of hooks === I would like to propose that there be four hooks for each action: two before and two after, one general and one specific. The general structure would look like so: {{{ ""pre_{present-tense-verb}_{noun}"" ""pre_{present-tense-verb}_{noun}_{$variable}"" [verb noun] ""{past-tense-verb}_{noun}_{$variable}"" ""{past-tense-verb}_{noun}"" }}} So for instance, adding an option would look like: {{{ ""pre_add_option"" ""pre_add_option_{$variable}"" [add option] ""added_option_{$variable}"" ""added_option"" }}} === Type of hook === Prior to adding, setting, or updating options/transients, the hooks should be a filter to allow changing of the option/transient prior to writing to the database. After adding, setting, or updating the hooks should be an action since the write has already occurred. Both prior and after getting an option/transient, the hook should be a filter. I'm not sure the use case for filtering the option before running the query, but that's what's presently done. Before and after the option is deleted the hook should be an action as there's no need to change the value of the option since it's being deleted anyway. === Deprecating hooks === There are several hooks no present that don't fit the proposed structure above. I suggest these hooks continue to work for backward compatibility, but that they be deprecated. === See also === [https://docs.google.com/document/d/1Zl7SuBJTWY8oWvWP6p4QuDmOCowuuqKHtmnmmlhasBI Google Doc] showing all the new and deprecated hooks == Related Tickets == * #37928 * #37929 * #37930 " NathanAtmoz Tickets Awaiting Review 38931 `update_option()` race condition with non-autoloaded options Options, Meta APIs 3.7 normal normal Awaiting Review defect (bug) new has-patch 2016-11-24T13:31:55Z 2022-06-09T00:26:55Z "Starting back in [25664] there's a race condition with object caches where `get_option()` will return a value, but `update_option()` will refuse to update it. This is kind-of-related to `alloptions`, but affects non-autoloaded options (which are not in `alloptions`, but in their own cache). Consider the following scenario: {{{ Process 1: Fetch option_a. Fills local cache. Process 2: Update option_a. Process 1: Delete option_a. Process 2: Update DB. Process 1: Delete from DB. Delete from remote cache. Process 2: Update remote cache. ... Process 5: Fetch option_a. Fills local cache from remote cache. Process 5: Update option_a. FAIL. DB doesn't have option. abort. cache not updated. ... (repeat process 5 above many times) Process 10: Get option_a (Still the value that Process 2 set in cache, even though it's not in the DB) Process 10: Update option_a (Doing the same as Process 5 now). FAIL. }}} Seems very racey and unlikely, but I've seen it happen on WordPress.org at least twice in the last few weeks when we update Jetpack (which makes heavy usage of the options table, and is loaded on most WordPress.org requests). When it happens, `get_option()` will continue to return a stale value from the cache that no longer exists in the DB and `update_option()` will fail to update the option as long as it exists in cache. If a plugin is performing an operation to update the stale option often, it can cause a huge load spike on the database server of never-ending failing `UPDATE` queries. The only way to 'fix' it is to create the DB row manually, or flush the object cache key. The patch attached attempts to perform an `add_option()` in the case of the `update_option()` DB query failing. This isn't exactly a new behaviour for options - `add_option()` will effectively perform an `update_option()` in the event the option you're trying to add already exists (through it using `INSERT .. ON DUPLICATE KEY UPDATE..`), doing it in reverse doesn't seem that out of the question." dd32 Candidates for Closure 38896 avatar_settings help text may not be accurate if avatar_defaults is filtered Options, Meta APIs normal normal Awaiting Review enhancement new dev-feedback 2016-11-21T22:04:36Z 2019-03-19T00:49:20Z "The string says: {{{ For users without a custom avatar of their own, you can either display a generic logo or a generated one based on their email address. }}} But, I have a need to remove generated Gravatars entirely using the `avatar_defaults` filter, which makes this text misleading. In addition, this text is not wrapped in any defining HTML, making it impossible to reliably target with CSS or JS even." johnjamesjacoby Unpatched Enhancements 38734 Dogfood the Settings API Options, Meta APIs 2.7 normal normal Future Release enhancement assigned 2016-11-09T16:56:42Z 2022-03-21T22:34:05Z "WordPress has had a [https://codex.wordpress.org/Settings_API Settings API] for eight years, but the core settings screens in WordPress don't use it. Instead, these screens use hardcoded sections and fields, which means it's impossible for a plugin to remove sections or fields without removing the entire screen. There's a new [https://make.wordpress.org/core/tag/fields-api/ Fields API] in development but this doesn't mean the core settings screens shouldn't be improved in the meantime by switching to the Settings API. I think the best approach for this is to address one screen at a time, starting with General Settings, and go from there. If anyone thinks this change should not be made, speak now or forever hold your peace. Related: #9296, #15691, #18801, #32396" johnbillion Candidates for Closure 38690 Introduce classes for settings Options, Meta APIs normal normal Awaiting Review enhancement new dev-feedback 2016-11-07T08:53:14Z 2019-03-26T13:14:34Z "Let's add classes surrounding settings to provide a better structure for dealing with them. It will also allow us to get rid of some globals if we are in a position to remove them (in terms of BC). Here is what I have in mind: * A `WP_Settings` class should be introduced that contains `get()`, `update()`, `add()` and `delete()` methods. This will mostly be copy-paste from the related functions. The functions themselves will become wrappers. * A `WP_Settings_Registry` will be introduced. It should contain all methods that handle registered settings (mostly introduced in 4.7). Again, the functions would become wrappers. We could get rid of the `$wp_registered_settings` global here and store these in a class property instead. * The `WP_Settings_Registry` instance will be contained by the `WP_Settings` instance as a public property. * A function `wp_settings()` will be introduced to access the `WP_Settings` instance or generate it if it does not exist yet. I'm not sure yet how to store the instance: The easy way is a global, but I was wondering where we're at with plans like a `WP::get( 'settings' )` so that we could do it differently. Anyway, let's assume a global first. I think it would be a good pattern to build the class in a flexible way, so that the registry instance and database instance are passed to the class constructor. The following is how I would envision the `wp_settings()` function: {{{ function wp_settings() { global $wp_settings; if ( ! isset( $wp_settings ) ) { $wp_settings = new WP_Settings( new WP_Settings_Registry(), $GLOBALS['wpdb'] ); } return $wp_settings; } }}} I think once we agree on an approach, we should do something similar for metadata. But let's have the discussion in here first and open the other ticket afterwards." flixos90 Candidates for Closure 38203 Remove `absint` on object IDs in `delete_metadata`, etc Options, Meta APIs 2.9 normal normal Awaiting Review defect (bug) new dev-feedback 2016-10-01T06:40:14Z 2017-04-19T02:50:43Z "Absint is run on the object ID in the functions called with a meta key: `delete_metadata()`, `get_metadata()`, `add_metadata()`, `update_metadata()` and `metadata_exists()`. This leads to unexpected behavior in the event a negative or floating object ID is passed. Related #37746, #37738, #33372." peterwilsoncc Tickets Awaiting Review 37929 Add `pre_delete_option` filter Options, Meta APIs normal normal Awaiting Review enhancement new has-patch 2016-09-03T07:15:29Z 2017-04-21T18:48:57Z "`get_option()` and `update_option()` already have filters to short-circuit their respective processes, so I think a similar filter should be added to `delete_option()` as well. Related: #37928" flixos90 Tickets Awaiting Review 37928 add `pre_add_option` filter Options, Meta APIs normal normal Awaiting Review enhancement new has-patch 2016-09-03T07:13:16Z 2024-01-07T02:55:53Z `get_option()` and `update_option()` already have filters to short-circuit their respective processes, so I think a similar filter should be added to `add_option()` as well. flixos90 Unpatched Enhancements 37702 Accept array of IDs in `delete_metadata_by_mid` Options, Meta APIs normal normal Future Release enhancement new needs-unit-tests 2016-08-18T01:23:21Z 2019-12-13T19:00:51Z "When deleting meta data in bulk (for example when an object is deleted), improve performance of meta deletion by accepting an array for `delete_metadata_by_mid` and related functions. Related #37671." peterwilsoncc Tickets Awaiting Review 37635 BUG in get_option Options, Meta APIs normal normal Awaiting Review defect (bug) new 2016-08-11T08:11:58Z 2020-12-17T23:11:48Z "in wp_options, i had saved this large serialized string: http://pastebin.com/raw/hxwETuHX however, when i run `get_option(""option_name"")` it returns false... i have spent time and found out, that it's because that get_option tries to unserialize it and return the result, but it have problems while unserializing. then i decided to manually grab the value and unserialize by hand.. and i succeeded! {{{#!php $raw_data=$wpdb->get_var(""Select option_value from wp_options Where option_name='option_name'""); unserialize(Serialized_Fixer($raw_data)); function Serialized_Fixer($serialized_string){ // securities if ( !preg_match('/^[aOs]:/', $serialized_string) ) return $serialized_string; if ( @unserialize($serialized_string) !== false ) return $serialized_string; return preg_replace_callback( '/s\:(\d+)\:\""(.*?)\"";/s', function ($matches){ return 's:'.strlen($matches[2]).':""'.$matches[2].'"";'; }, $serialized_string ) ; } }}} and that worked! this is seriously a bug of WP! please fix it! thanks!" tazotodua Unpatched Enhancements 37579 Inconsistent names for `update_(network_)option` actions Options, Meta APIs 4.5.3 normal normal enhancement new 2016-08-05T03:11:39Z 2019-06-04T21:02:49Z "I noticed that there seems to be some inconsistency in the hook naming convention, regarding the setting, deleting, and updating of options and transients. It would be nice if all the hooks indicated when in the function they were occurring, and matched the others (see the list below). For example, if all hooks that occurred before the action were prefixed with `pre_`, and all hooks occurring after were in the past tense: `added_`, `deleted_`, `updated_`. I'm not sure how this was allowed to happen to begin with, so if I'm missing something, please inform and then close this ticket... but if it's simply a result of sloppiness, cleanup should be performed (volunteering myself). Here is the list of the actions that are performed (in `wp-includes/options.php`), grouped by when the action fires (before or after): == BEFORE == - `update_option` - `add_option` - `delete_option` - `delete_transient_{$transient}` - `set_transient_{$transient}` - `pre_delete_site_option_{$option}` - `delete_site_transient_{$transient}` == AFTER == - `add_site_option_{$option}` - `add_site_option` - `add_option_{$option}` - `added_option` - `setted_transient` - `set_site_transient_{$transient}` - `setted_site_transient` - `update_site_option_{$option}` - `update_site_option` - `update_option_{$option}` - `updated_option` - `delete_site_option_{$option}` - `delete_site_option` - `delete_option_{$option}` - `deleted_option` - `deleted_transient` - `deleted_site_transient`" crstauf Tickets with Patches 37355 remove_settings_section() counterpart to add_settings_section() Options, Meta APIs 4.6 normal normal enhancement new has-patch 2016-07-13T13:52:18Z 2019-06-04T21:01:29Z "The settings API allows for settings sections to be added, but not removed. To remove section you have to do the following {{{#!php get_results( ""SELECT * FROM $wpdb->options ORDER BY option_name"" ); }}} " aoculi Tickets with Patches 35379 update_network_option changes stored option value if sanitize_option detects error jeremyfelt Options, Meta APIs 3.0 normal normal Future Release defect (bug) assigned has-patch 2016-01-08T23:48:50Z 2017-09-05T16:57:14Z "If you make a call like {{{ update_network_option( null, ""admin_email"", ""this.is.not.an.email.address"" ); }}} then the value of the `admin_email` ''network'' option will be changed to the value of the `admin_email` ''site'' option in the database. Expected behaviour would be that the option value in the database is not changed. The reason is that `update_network_option` calls {{{ sanitize_option( ""admin_email"", ""this.is.not.an.email.address"" ); }}} and writes its return value to the database. However, `sanitize_option` will return the value of `get_option( ""admin_email"" )`, instead of `get_network_option( null, ""admin_email"" )`. See [https://core.trac.wordpress.org/browser/tags/4.4/src/wp-includes/formatting.php#L3863 lines 3863ff. in formatting.php]." thomaswm Tickets with Patches 34848 Add support for updating post meta in bulk chriscct7 Options, Meta APIs normal normal Future Release enhancement assigned close 2015-12-04T19:43:48Z 2023-08-29T15:59:31Z "A limiting factor in performance of inserting posts into the database is postmeta. I've been running a patch locally which adds functions for adding postmeta in one function call instead of calling add_post_meta multiple times over and over. add_post_meta creates a single SQL insert query, when adding 20 post metas that is 20 SQL inserts all run separately. This can be greatly improved by combining these into a single SQL insert. There is a problem where updating meta in bulk would likely be impossible or very painful. At the very least I have not been able to find a way to do this. Deleting I haven't developed a function but I imagine it would be fairly easy. {{{#!php /** * Add metadatas to a post. * * @since x.x.x * * @param int $post_id Post ID. * @param string $meta_data Metadata as an key/value pair array * * @return bool Was the data inserted */ function add_post_metas( $post_id, $meta_data ) { // Make sure meta is added to the post, not a revision. if ( $the_post = wp_is_post_revision($post_id) ) $post_id = $the_post; return add_metadatas('post', $post_id, $meta_data); } /** * Add multiple metadatas for the specified object. Similar to calling add_metadata for each metadata individually, * and is only applicable for unique meta data. If a meta key already exists for an object it will not be stored. * * @since x.x.x * * @global wpdb $wpdb WordPress database abstraction object. * * @param string $meta_type Type of object metadata is for (e.g., comment, post, or user) * @param int $object_id ID of the object metadata is for * @param array $meta_data Metadata as an key/value pair array * * @return bool If the metadata was stored successfully. */ function add_metadatas($meta_type, $object_id, $meta_data) { global $wpdb; if ( ! $meta_type || ! is_array( $meta_data ) || ! is_numeric( $object_id ) ) { return false; } $object_id = absint( $object_id ); if ( ! $object_id ) { return false; } $table = _get_meta_table( $meta_type ); if ( ! $table ) { return false; } $column = sanitize_key($meta_type . '_id'); /** * Filter whether to add metadatas of a specific type. * * The dynamic portion of the hook, `$meta_type`, refers to the meta * object type (comment, post, or user). Returning a non-null value * will effectively short-circuit the function. * * @since x.x.x * * @param null|bool $check Whether to allow adding metadata for the given type. * @param int $object_id Object ID. * @param string $meta_key Meta key. * @param mixed $meta_value Meta value. Must be serializable if non-scalar. * @param bool $unique Whether the specified meta key should be unique * for the object. Optional. Default false. */ $check = apply_filters( ""add_{$meta_type}_metadatas"", null, $object_id, $meta_data ); if ( null !== $check ) return $check; $_meta_data = array(); foreach( $meta_data as $key => $value ) { if ( 0 == absint( $wpdb->get_var( $wpdb->prepare( ""SELECT COUNT(*) FROM $table WHERE meta_key = %s AND $column = %d"", $key, $object_id ) ) ) ) { $key = wp_unslash( $key ); $value = wp_unslash( sanitize_meta( $key, $value, $meta_type ) ); $_meta_data[ $key ] = maybe_serialize( $value ); /** * Fires immediately before meta of a specific type is added. * * The dynamic portion of the hook, `$meta_type`, refers to the meta * object type (comment, post, or user). * * @since 3.1.0 * * @param int $object_id Object ID. * @param string $meta_key Meta key. * @param mixed $meta_value Meta value. */ do_action( ""add_{$meta_type}_meta"", $object_id, $key, $value ); } } $rows = array(); if( ! empty( $_meta_data ) ) { $sql = ""INSERT INTO {$table} ({$column}, meta_key, meta_value) VALUES ""; $comma = false; foreach( $_meta_data as $key => $value ) { if( true == $comma ) { $sql .= ','; } $sql .= ""({$object_id}, '{$key}', '{$value}')""; $comma = true; } } $result = $wpdb->query( $sql ); if ( ! $result ) return false; wp_cache_delete($object_id, $meta_type . '_meta'); return true; } }}} " patrickgarman Tickets with Patches 34405 Retrieval of meta value that is an array. Options, Meta APIs 4.3.1 normal normal defect (bug) reviewing has-patch 2015-10-23T00:10:52Z 2020-09-20T13:02:22Z "Simply using $post->meta_value automatically runs get_post_meta(). This happens in [https://core.trac.wordpress.org/browser/tags/4.3.1/src/wp-includes/post.php#L748] (post.php line 748). That value then goes into sanitize_post_field() [https://core.trac.wordpress.org/browser/tags/4.3.1/src/wp-includes/post.php#L751] (post.php line 751). The value then gets modified at [https://core.trac.wordpress.org/browser/tags/4.3.1/src/wp-includes/post.php#L2215] (post.php line 2251) through esc_attr(). Codex entry for [https://codex.wordpress.org/Function_Reference/esc_attr] (esc_attr()) shows that the only parameter that should be sent is a string. This process works for strings. However, if our meta value is an array, we get a PHP notice (Notice: Array to string conversion in /var/www/html/wp/wp-includes/formatting.php on line 959). Then returns a sting(5) 'Array' instead of the actual array. I think that the best option may be to edit esc_attr() or the subsequent function wp_check_invalid_utf8() to allow for arrays to be passed to them. Alternatively the quick dirty fix would be to not send an array into sanitize_post_field." alexwbaumann Tickets Awaiting Review 34322 set_transient and get_transient don't seem to be working for some users since WP 4.3 Options, Meta APIs 4.3 normal normal Awaiting Review defect (bug) new 2015-10-16T04:07:34Z 2017-04-06T17:08:22Z "I'm the developer of a social media plugin which relies on the WordPress set_transient and get_transient functions to temporarily cache data in the user's database. Since the WordPress 4.3 update, we've had reports of the cache not clearing automatically as it should, meaning that the transients aren't expiring correctly in the database. This seems to only be happening on some servers as I haven't been able to replicate the issue on my own test site, but have confirmed it on user sites, and looks like it could be related to [https://make.wordpress.org/core/2015/07/30/get_transient-is-now-more-strict-in-4-3/ this thread]. The same problem seems to be happening to other developers of similar plugins, and I've had some users report that other unrelated WordPress plugins they're using are also not automatically updating either any more, which I'm assuming is caused by the same issue. I've been able to confirm the problem on user sites by using a page template containing the following basic code. I've commented it to explain what it does and can provide a Facebook Access Token privately if needed, although I included a link on how to obtain your own. The transient set using the script below should expire every 30 minutes and then the script should check the URL again for new data, but it doesn't unless I delete the transient manually. {{{ '; //Show the date the data was last updated from Facebook echo 'Last updated: ' . json_decode( json_encode($transient) )->headers->date; } else { //No transient in the database - get the data from Facebook $facebook_data = wp_remote_get( $url ); //Cache the data in the database set_transient( 'test_transient_expiration', $facebook_data, 1800 ); echo 'Got the data from the URL
'; //Show the date the data was last updated from Facebook echo 'Last updated: ' . json_decode( json_encode($facebook_data) )->headers->date; } ?> }}} I was in two minds whether to report this as a bug as I've never reported one before, however it definitely seems like this could be a bug as the above code should work, but doesn't on some user's sites. I use code very similar to the above in my plugin and nothing has been changed in that code, but users started reporting an issue shortly after the WordPress 4.3 update was released. Through reading the change logs for the 4.3 update I know some changes were made to transients and so I'm wondering if that's what caused this problem. Sorry for the long post! John" smashballoon Unpatched Bugs 33977 set_transient('settings_errors', get_settings_errors(), 30); and multi user @ wp-admin/options.php Options, Meta APIs 4.3.1 normal normal defect (bug) new 2015-09-23T13:37:52Z 2019-06-04T20:51:48Z " {{{ #!div style=""font-size: 80%"" Code highlighting: {{{#!php /** * Handle settings errors and return to options page */ // If no settings errors were registered add a general 'updated' message. if ( !count( get_settings_errors() ) ) add_settings_error('general', 'settings_updated', __('Settings saved.'), 'updated'); set_transient('settings_errors', get_settings_errors(), 30); /** * Redirect back to the settings page that was submitted */ $goback = add_query_arg( 'settings-updated', 'true', wp_get_referer() ); wp_redirect( $goback ); exit; }}} }}} I see the code above in wp-admin/options.php since the key 'settings_errors' is not binding to a user, Is there a chance than one user's error message may be shown on another user's page?" coldwinds Unpatched Enhancements 33884 Move meta functions to their own files Options, Meta APIs 4.4 normal normal enhancement new 2015-09-15T17:51:10Z 2019-06-04T20:51:37Z "All the meta functions should be in their own file. Like this. post-meta.php comment-meta.php user-meta.php Related tickets: #10142 #28290" spacedmonkey Tickets with Patches 33561 get_transient() will always return the value of a broken transient Options, Meta APIs 4.3 normal normal defect (bug) new needs-unit-tests 2015-08-26T17:48:47Z 2019-06-04T20:51:26Z "In 4.2: 1. Create the transient 2. Delete its timeout 3. Call get_transient() FALSE is returned In 4.3: 1. Create the transient 2. Delete its timeout 3. Call get_transient() the value of a broken transient gets returned indefinitely See: [33110] and #30380 Note that a transient can get broken for a number of reasons and not necessary through intentionally deleting its timeout. " deconf Tickets with Patches 33551 Settings API: Filter sections and fields before displaying them obenland Options, Meta APIs 2.7 normal normal enhancement assigned needs-docs 2015-08-26T06:08:48Z 2019-11-27T18:26:09Z "Once a section or settings field was added, there is currently no good way to remove it or change the order they are displayed in. It would be good to add filters in `do_settings_section()` and `do_settings_fields()` to allow for that to happen. We could also think about providing convenience functions to use in a callback to those filters, along the lines of `remove_option_whitelist()`." obenland Tickets Awaiting Review 32565 Adding an underscore prefix meta key with a meta value provides an incorrect error message SergeyBiryukov Options, Meta APIs 4.3 normal normal Awaiting Review defect (bug) assigned has-patch 2015-06-04T13:16:08Z 2022-07-18T19:54:25Z "To reproduce this, use the custom fields section in a post to add a custom field. Add a hidden field (prefix the custom field name with an underscore) and type any value. The error returned is ""Please provide a custom field value."" which is not what the issue is, the issue is that we are trying to add a protected meta key. I've included a fix which I don't particularly like. Perhaps add_meta should return a WP_Error object with the correct error. This would be easy enough to do, but I'm not familiar enough with add_meta(), I'm not sure what this could break. I changed this in all three places the issue could occur, but I'm not sure this is needed. During troubleshooting it was obvious that the issue originates from line 1198. The other two occurrences could be line 1193 and 1281. Hope this helps, Daniel" danielpataki Tickets Needing Feedback 32202 Add support for options page locking (settings API concurrency) Options, Meta APIs 3.6 normal normal enhancement new dev-feedback 2015-04-30T01:18:48Z 2021-08-26T21:18:12Z "If two users access an options page at the same time, the user who saves last will have their settings stick, while the user who saves first will have their settings lost. This is because options pages lack any access concurrency checking. In #31436 we propose to handle conflicts in concurrent Customizer sessions by adding locking to individual controls so that users can't override each others' values. The same functionality is needed for options pages generated generated via the Settings API. At the most basic level, locking could be implemented to block a user from accessing an options page if someone else is already there, presenting the user with the same takeover screen as shown for post locking. A more sophisticated approach would be to allow multiple users to edit an options page at once, either by syncing values across the sessions via Heartbeat, or by disabling a field entirely for other users when one user starts editing it. In this way, the disabled field would not be included when the other users submit the form. This may not work in all cases, however. Another approach, less sophisticated and not using Heartbeat at all, would be to introduce a persistent counter for saves to a given admin page. This would serve as a revision number, and the revision could be included with each settings form. If the submitted form has a setting number that is not the same as what is currently stored, then this would indicate there is a potential conflict and the user could be presented with a screen to resolve any differences." westonruter Unpatched Bugs 31277 Many WP Dashboard-only transients for 'browser version' set to autoload=yes in wp_options Options, Meta APIs 4.1 normal normal defect (bug) new 2015-02-09T23:21:43Z 2019-06-04T20:49:09Z "I've been recently optimizing WP for speed and for various reasons (mostly because it's buggy as hell), we're forced to run without W3TC's object cache on a busy site. Because of that, when wp_options gets bloated, especially with values that have autoload=yes, and every thread ends up transferring that much more data, overall performance decreases, and db traffic goes up. Transients are typically (with few exceptions) added as autoload=no. This keeps performance in check. However, there's one notable exception, and on our server, it's 120 rows all dedicated to a single transient, with over 30KB of data in total that gets transferred for no reason. That transient is `""browser_"" . $key`, and it's only used by `wp_check_browser_version()` in `wp-admin/includes/dashboard.php`. There's no reason at all for it to use autoload=yes." archon810 Tickets with Patches 31094 Attempt to cache notoptions in database to save queries for non-existent options Options, Meta APIs normal normal enhancement new needs-unit-tests 2015-01-21T23:23:18Z 2019-06-04T20:48:51Z "Coming from #31061, @boone suggested this might be worth exploring, so I took a first pass at it. Idea is to save nonexistent options in options table as `notoptions_cache`. This seems to be working nicely so far. Non existent queries get cached, and gets refreshed when they are added or updated. I am considering the following moving forward: 1) Upon `delete_option()` call, we can add that option to `notoptions_cache` right away but I can imagine cases where we wouldn't want that, so I believe letting it get added on `get_option()` is a better choice 2) Implement it for Multisite functions - Should we? Chances are anyone who is running a multisite is already using a persistent object cache backend. Thoughts? 3) If `object-cache.php` is dropped in, so `notoptions` cache is now maintained over there persistently, all good. But when its moved out, it will try to use the `notoptions_cache` inside option table which may not be accurate anymore, so we need to delete it the moment a persistent object cache backend gets involved. Thoughts? Anything else I should consider?" ashfame Unpatched Enhancements 30995 Pass meta_id when retrieving multiple metas Options, Meta APIs 2.9 normal normal enhancement new needs-unit-tests 2015-01-12T20:18:50Z 2019-06-04T20:48:39Z "Hello. In some (edge?) cases we would need a unique identifier when we retrieve metas. For example, `get_post_custom_values( '_yolo', $post->ID )` will return: {{{ Array ( [0] => foo [1] => bar ) }}} while the following, with the `meta_id` as array key, would be helpful imho: {{{ Array ( [1022] => foo [1029] => bar ) }}} The modification is trivial in `update_meta_cache()`, and some other functions would only need something like `metas[0]` => `reset( metas )`." GregLone Unpatched Enhancements 29786 read_post_meta should be a meta capability Options, Meta APIs normal normal enhancement new 2014-09-29T11:19:31Z 2019-06-04T20:47:44Z "Right now, we have `edit_post_meta`, `delete_post_meta`, and `add_post_meta`. In order to be able to expose metadata publicly, we need to be able to check if we can access individual keys. `is_protected_meta` only controls whether it's prefixed and should default to being protected (by default, prefixed with `_`). This isn't adequate to check for read permission on a key, because it's not filterable." rmccue Tickets with Patches 29299 Plural forms not available for some strings SergeyBiryukov Options, Meta APIs normal normal Future Release defect (bug) reviewing dev-feedback 2014-08-21T09:55:42Z 2020-02-06T19:46:51Z "There are several strings which do not allow specific plurals in Settings - Reading. `` `` It looks strange when somebody inserts for example number 4 and our plural form is translated only for number 5. Best solution would be probably some kind of string ""Number of posts on page"" (without ending ""posts"" string). But I am not sure about it... See: https://core.trac.wordpress.org/browser/trunk/src/wp-admin/options-reading.php#L126" pavelevap Tickets with Patches 29082 Pass $meta_id into sanitize_meta() and subsequently into the filter for register_meta callback chriscct7 Options, Meta APIs 3.3 normal normal enhancement reviewing has-patch 2014-08-01T09:59:57Z 2019-06-04T20:47:28Z "To use Post Type based sanitization for specific meta keys, currently register_meta adds the filter but while the 'auth' filter gets access to the Post ID, the 'sanitize' filter does not. We would need to add $object_id in the cases of add/update_metadata, and in the case of update_metadata_by_mid we'd need to pass the Post ID into that function as well, which would then pass along to sanitize_meta() usage. Is anyone against this proposal? If so, a patch can be drawn up." sc0ttkclark Tickets Awaiting Review 28701 Deleted option is not deleted if value was ever null Options, Meta APIs 2.2 normal normal Awaiting Review defect (bug) new needs-unit-tests 2014-07-01T04:15:03Z 2021-02-16T10:34:38Z "If an autoloaded option ever contains `null`, it will cease to be autoloaded after this. It will then be stored in the individual option cache (`wp_cache_get('optname', 'options')`), rather than the autoloaded options. The autoloaded option cache will then contain `optname` with the value `null` (and `isset(null) === false`). Typically, this would be fine, but `delete_option` checks the database autoload value directly. It then only attempts to delete this from the autoload options cache (which again fails because of an isset check). After deleting, the value is still stored in the object cache (!!!), causing it to return a value despite not existing in the database. As far as I can tell, this has existed since r4855 (WP 2.2). ---- To reproduce (requires external object cache to be enabled): {{{ // Add the option with initial value set to null add_option( 'testingkey', null ); // Update to real value update_option( 'testingkey', 'realvalue' ); // Delete the option completely delete_option( 'testingkey' ); // Check the value var_dump( get_option( 'testingkey', 'default' ) ); }}} Expected result: {{{ string(7) ""default"" }}} Actual result: {{{ string(9) ""realvalue"" }}}" rmccue Unpatched Bugs 28454 Inconsistent front page option behavior Options, Meta APIs 3.4 normal normal defect (bug) new 2014-06-04T16:44:57Z 2019-06-04T20:47:09Z "'''Correct/expected behaviour:''' If you change your settings in ''Settings'' > ''Reading'' > ''Front page displays'' as follows: ''From:'' A static page (select below) -- Front page: home -- Posts page: blog ''To:'' Your latest posts then the `Show_on_front` setting is correctly changed to `posts` and the `Page_on_front` setting correctly gets reset to `0`. '''Incorrect behaviour:''' If instead you change the same settings from ''Appearance'' > ''Customize'', the `Show_on_front` setting is correctly changed to `posts`, but the `Page_on_front` setting is not reset and remains set to the previous setting's page ID. '''Testing done:''' I replicated this behaviour with several themes, including twenty fourteen, with all plugins deactivated. '''Why this is a problem:''' This is inconsistent and may cause errors--e.g. if a theme or plugin author checks the `Page_on_front` setting without also checking the `Show_on_front` setting. This is how I encountered it, in Polylang; plugin author had to work around it; details here: http://wordpress.org/support/topic/wrong-front-page-showing-in-appearance-customize-with-polylang-loaded). '''Solution (indicative; I'm not an expert):''' Re-use the ""Settings > Reading > Front page displays"" code in the ""Appearance > Customize"" functions. " ElectricFeet Tickets with Patches 27421 Escape madness in meta API Options, Meta APIs 3.8.1 normal normal defect (bug) reopened has-patch 2014-03-15T16:20:46Z 2019-06-04T20:46:10Z "I was trying to come up with a reasonably sane wrapper around the WP meta API so as to no longer need to call it directly, and I'm somewhat bemused by the slashing insanity in there... As I read through the code: - get_post_meta() expects key and value to be unslashed - add_post_meta(), update_post_meta() and delete_post_meta() expect key and value to be slashed - WP uses wp_unslash() to strip slashes in add_metadata(), update_metadata(), and delete_metadata() - the codex suggests to use wp_slash() to add slashes before storing data This could all work in the best of worlds, but then: 1. the codex is mysteriously silent on the need to slash keys as well 2. wp_unslash() will dutifully unslash objects, but wp_slash() doesn't slash them to begin with 3. wp_slash() and wp_unslash() would not be able to slash private variables (short of using Reflection, perhaps) even if they wanted to 4. wp_slash() and wp_unslash() will not bother processing array keys that could have been sent from e.g. a POST request. Admittedly, it's not every day where $_REQUEST keys are inserted as is the database, so there's likely little room for SQL injections with respect to that last point, and array keys are typically without slashes, leaving little room for quirky keys that lose their slashes while getting stored. Still, I'm left scratching my head as to if/when we'll actually allow objects to get stored using the meta API without running the risk of seeing their data unslashed at arbitrary points in time." Denis-de-Bernardy Tickets Needing Feedback 26895 Deprecate recently_edited option Options, Meta APIs 3.8 normal minor enhancement new dev-feedback 2014-01-21T08:33:53Z 2019-06-04T20:45:22Z "recently_edited option is being set when a plugin or a theme file is edited by the builtin Editor. A search, in the WordPress 3.8 source code, tells me that the option is never being read. I suggest that we deprecate that option and replace it by an action where plugins can hook and get the value of the edited file." yani.iliev Tickets with Patches 24726 New filter hook for get_metadata() Options, Meta APIs normal normal enhancement new has-patch 2013-07-11T14:04:35Z 2019-06-04T20:44:32Z The `get_metadata()` function has one filter hook: `get_{$meta_type}_metadata`. While this filter can be used to override or short-circuit the return of `get_metadata()`, it can't easily be used to filter the meta value. In the options API, `get_option()` has two hooks: `pre_option_$option` and `option_$option`. The `get_{$meta_type}_metadata` corresponds to the former, but it would be useful to have something similar to `option_$option` that will filter the actual meta value. Maybe `get_{$meta_type}_metadata-{$meta_key}`? JD55 Unpatched Enhancements 23616 General Handler for Whitelisted Options' Submissions Options, Meta APIs normal normal feature request new 2013-02-26T03:06:55Z 2019-06-04T20:43:51Z As stated over on #18285 WordPress should move away from posting to options.php. In order to do that, the Settings API needs a general purpose function that can be safely called on all Settings Pages that can handle posts to itself (generally referred to as 'take_action' in various places) and can handle what options.php currently does. WraithKenny Unpatched Bugs 22192 update_option() strict checks can cause false negatives joemcgill Options, Meta APIs normal normal Future Release defect (bug) assigned needs-unit-tests 2012-10-15T03:19:23Z 2023-10-16T21:22:18Z "Given this: {{{ add_option( $option_name, 1 ); update_option( $option_name, 1 ); }}} The update should not work, because they are the same. However, the meta cache will have ""1"" as a string, and then it will strict compare it to 1 as an integer. Thus, an unnecessary update will run. It is quite common to use integers and booleans directly into these functions. They should be smart enough to recognize that ""1"" == 1 == true and ""0"" == 0 == false, and that any numeric string is also equal to a properly cast integer. The new changes need unit tests. Ticket from which this was spun: #22189, saving navigation menus is slow." nacin Tickets Needing Feedback 21989 update_option() calls sanitize_option() twice when option does not exist Options, Meta APIs normal normal Future Release defect (bug) new dev-feedback 2012-09-25T05:04:34Z 2024-02-22T06:16:56Z " I just spent several hours tracking down an issue when using the Settings API where `sanitize_option()` is called twice which is unnecessary execution especially if sanitization includes calling an external API for username/password authorization ''(this was how another developer set it up for a plugin I was debugging.)'' What happens is that a call to `update_option()` will call `sanitize_option()` and then if the option wasn't previously in the options table `update_option()` will delegate to `add_option()` which calls `santize_option()` a second time. This would normally be easy to workaround by first calling `get_option()` and testing for `false` and calling `add_option()` instead of `update_option()` if `false`, but not when the Settings API chooses how to call it. I've looked at the problem and can envision several different ways to solve it such but don't know which the core developers would choose ''(or if they'd choose yet another option I haven't envisioned)'' so I didn't submit a patch: - Adding a 3rd parameter `$mode` to `sanitize_option()` that identifies the mode ''('add', 'edit', default = 'unknown')'' and thus allow the hook to ignore one of the options ''(this would be more backward compatible but would put the onus on the developer to know to do this)'', - Adding a 5th parameter `$bypass_sanitize` to `add_option()` defaulted to `false` that is only passed as `true` in `update_option()` allowing `update_option()` to disable the call to `sanitize_option()` found in `add_option()` ''(this would be less backward compatible and hacky, but seemless to the developer)'' - Adding a 3rd parameter `$bypass_sanitize` to `update_option()` defaulted to `false` that is only passed as `true` from `/wp-admin/options.php` allowing `update_option()` to bypass the call to `sanitize_option()` if an `add_option()` will happen ''(this would be less backward compatible and hacky, but seemless to the developer)'' - Have `/wp-admin/options.php` test for no pre-existing option and then call `add_option()` or `update_option()`, respectively ''(this would be seemless to the developer but less backward compatible and not hacky, and it wouldn't handle the general case.)'' So is this worth fixing to save other users and developers debugging time, and to reduce the chance of subtle errors in new code? If yes, how best to approach?" MikeSchinkel Unpatched Enhancements 21546 Site Settings page is a hot mess Options, Meta APIs 3.0 normal normal enhancement reopened 2012-08-10T21:44:07Z 2019-06-04T20:43:21Z "I found out just how bad this page is when debugging an issue related to {{{WPLANG}}}. {{{WPLANG}}} is an option for a blog in your network (overrides {{{WPLANG}}} in {{{wp-config.php}}}), but if you delete the option on purpose or accidentally, there is no way of restoring it in the admin. Site Settings just loads your options table and POSTs back to itself. The only reference to the original options map (the defaults) is in schema, which WP has zero access to outside of upgrade. I have abstracted the default options and the default ""fat"" options into functions in {{{ms.php}}}. Also, when loading your Site Settings options - if a default option is missing, I display it in the admin so you can save it (it is populated with its default value). I have also streamlined and condensed some code that was happening in and around {{{populate_options()}}}" wonderboymusic Tickets Needing Feedback 21432 Deprecate *_blog_option() Options, Meta APIs 3.4.1 normal normal Future Release defect (bug) assigned dev-feedback 2012-07-31T21:53:06Z 2017-06-26T17:58:41Z "Deprecate get_blog_option(), add_blog_option(), update_blog_option(), and delete_blog_option(). The regular *_option() functions wrapped with switch_to_blog() and restore_current_blog() should be used instead. Previous discussion: http://core.trac.wordpress.org/ticket/21270#comment:11" ryan Tickets Needing Feedback 20853 get_post_custom show directly serialized data from the post_meta arrays. Options, Meta APIs 1.5 normal normal defect (bug) assigned dev-feedback 2012-06-06T05:39:23Z 2019-06-04T20:43:13Z "get_post_custom show directly serialized data from the post_meta arrays. For example: If I save a data with: {{{ update_post_meta( $post_id, 'camp', array( 'some' => $var, 'thing' => $var_2 ) ); }}} When I use get_post_meta(); : {{{ $var_get = get_post_meta($post_id, 'camp', true); echo $var_get['some']; // Fine.. Print: $var content. }}} but, when I use get_post_custom() : {{{ $var = get_post_custom($post_id); echo $var['some']; Metod, (Not work because ""Returns a multidimensional array"" with all values, and 0 is the first or the unique value). echo $var['some'][0]; /* Metod, >:( , Not work. Print: a:2:{i:some;s:4:""this"";i:thing;s:7:""content"";} */ }}} Instead of display ""array"", and can not handle sub arrays." shadowhck Tickets with Patches 18801 Accessibility Enhancements to Settings API joedolson* Options, Meta APIs 3.2.1 high normal Future Release enhancement accepted has-patch 2011-09-28T14:59:44Z 2023-03-24T15:16:10Z "I've only started working with the Settings API, but right off the bat I noticed two fairly major, but should be not too difficult to fix, accessibility issues. 1) The label/input field pairs are missing the HTML