From 50274fbc2b1c5e6e0a43ea68d2f767ec2f0b86e8 Mon Sep 17 00:00:00 2001 From: hellofromTonya Date: Wed, 2 Aug 2023 18:37:21 +0000 Subject: [PATCH] Code Modernization: Deprecate dynamic properties in WP_List_Table magic methods. The unknown use of unknown dynamic property within the `WP_List_Table` property magic methods is now deprecated. A descriptive deprecation notice is provided to alert developers to declare the property on the child class extending `WP_List_Table`. Changes in this commit: * Adds a deprecation notice to the `__get()`, `__set()`, `__isset()`, `__unset()` magic methods, i.e. to alert and inform developers when attempting to get/set/isset/unset a dynamic property. * Fixes `__get()` to explicitly returns `null` when attempting to get a dynamic property. * Removes returning the value when setting a declared property, as (a) unnecessary and (b) `__set()` should return `void` [https://www.php.net/manual/en/language.oop5.overloading.php#object.set per the PHP handbook]. * Adds unit tests for happy and unhappy paths. For backward compatibility, no changes are made to the internal declared properties listed in `$compat_fields` and accessed through the magic methods. For example: A child class uses a property named `$data` that is not declared / defined as a property on the child class. When getting its value, e.g. `$list_table->data`, the `WP_List_Table::__get()` magic method is invoked, the following deprecation notice thrown, and `null` returned: >The property `data` is not defined. Setting a dynamic (undefined) property is deprecated since version 6.4.0! Instead, define the property on the class. === Why not remove the magic methods, remove the `$compat_fields` property, and restore the properties `public`? tl;dr Backward compatibility. Several plugins, one of which has over 5M installs, add a property to the `$compat_fields` array. Removing the property would cause an `Undefined property` `Warning` (PHP 8) | `Notice` (PHP 7) to be thrown. Removing the associated code would change the functionality. === Why not limit the deprecation for PHP versions >= 8.2? tl;dr original design intent and inform The magic methods and `$compat_fields` property were added for one purpose: to continue providing external access to internal properties declared on `WP_List_Table`. They were not intended to be used for dynamic properties. Deprecating that unintended usage both alerts developers a change is needed in their child class and informs them what to change. References: * Dynamic (non-explicitly declared) properties are deprecated as of PHP 8.2 and are expected to become a fatal error in PHP 9.0. * A [https://www.youtube.com/live/vDZWepDQQVE?feature=share&t=10097 live open public working session] where these changes were discussed and agreed to. * [https://wiki.php.net/rfc/deprecate_dynamic_properties PHP RFC: Deprecate dynamic properties.] Related to #14579, #22234, #30891. Follow-up to [15491], [28493], [28521], [28524], [31146]. Props antonvlasenko, jrf, markjaquith, hellofromTonya, SergeyBiryukov, desrosj, peterwilsoncc, audrasjb, costdev, oglekler, jeffpaul. Fixes #58896. See #56034. Built from https://develop.svn.wordpress.org/trunk@56349 git-svn-id: http://core.svn.wordpress.org/trunk@55861 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-admin/includes/class-wp-list-table.php | 33 +++++++++++++++++++++-- wp-includes/version.php | 2 +- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/wp-admin/includes/class-wp-list-table.php b/wp-admin/includes/class-wp-list-table.php index b8631d17a2..c7c38a3561 100644 --- a/wp-admin/includes/class-wp-list-table.php +++ b/wp-admin/includes/class-wp-list-table.php @@ -176,6 +176,7 @@ class WP_List_Table { * Makes private properties readable for backward compatibility. * * @since 4.0.0 + * @since 6.4.0 Getting a dynamic property is deprecated. * * @param string $name Property to get. * @return mixed Property. @@ -184,27 +185,42 @@ class WP_List_Table { if ( in_array( $name, $this->compat_fields, true ) ) { return $this->$name; } + + trigger_error( + "The property `{$name}` is not defined. Getting a dynamic (undefined) property is " . + 'deprecated since version 6.4.0! Instead, define the property on the class.', + E_USER_DEPRECATED + ); + return null; } /** * Makes private properties settable for backward compatibility. * * @since 4.0.0 + * @since 6.4.0 Setting a dynamic property is deprecated. * * @param string $name Property to check if set. * @param mixed $value Property value. - * @return mixed Newly-set property. */ public function __set( $name, $value ) { if ( in_array( $name, $this->compat_fields, true ) ) { - return $this->$name = $value; + $this->$name = $value; + return; } + + trigger_error( + "The property `{$name}` is not defined. Setting a dynamic (undefined) property is " . + 'deprecated since version 6.4.0! Instead, define the property on the class.', + E_USER_DEPRECATED + ); } /** * Makes private properties checkable for backward compatibility. * * @since 4.0.0 + * @since 6.4.0 Checking a dynamic property is deprecated. * * @param string $name Property to check if set. * @return bool Whether the property is a back-compat property and it is set. @@ -214,6 +230,11 @@ class WP_List_Table { return isset( $this->$name ); } + trigger_error( + "The property `{$name}` is not defined. Checking `isset()` on a dynamic (undefined) property " . + 'is deprecated since version 6.4.0! Instead, define the property on the class.', + E_USER_DEPRECATED + ); return false; } @@ -221,13 +242,21 @@ class WP_List_Table { * Makes private properties un-settable for backward compatibility. * * @since 4.0.0 + * @since 6.4.0 Unsetting a dynamic property is deprecated. * * @param string $name Property to unset. */ public function __unset( $name ) { if ( in_array( $name, $this->compat_fields, true ) ) { unset( $this->$name ); + return; } + + trigger_error( + "A property `{$name}` is not defined. Unsetting a dynamic (undefined) property is " . + 'deprecated since version 6.4.0! Instead, define the property on the class.', + E_USER_DEPRECATED + ); } /** diff --git a/wp-includes/version.php b/wp-includes/version.php index 15c01c77e6..faf79696a8 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -16,7 +16,7 @@ * * @global string $wp_version */ -$wp_version = '6.4-alpha-56348'; +$wp_version = '6.4-alpha-56349'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.