Skip to content

Commit

Permalink
[DISCUSS] wpdb::__unset(): bug fix
Browse files Browse the repository at this point in the history
There were three properties, which were introduced in [30345](https://core.trac.wordpress.org/changeset/30345), which were protected from being overwritten (set).

That protection, however, was not extended to the `__unset()` method, leaving these properties only partially protected.
IMO this is an oversight (bug) in the initial implementation.

This commit fixes this by applying the same protection as was already given to these properties for `__set()`, to these properties in the `__unset()` method.

Includes updating the unit tests to match.

Note: this _could_ be considered a BC-break, in which case, an alternative implementation would be to throw a `_doing_it_wrong()` and to continue to unset the property when so requested.
  • Loading branch information
jrfnl committed Sep 2, 2022
1 parent 0684651 commit 17d48b8
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 7 deletions.
23 changes: 17 additions & 6 deletions src/wp-includes/class-wpdb.php
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,19 @@ class wpdb {
*/
public $error = null;

/**
* Declared private/protected properties which should remain accessible via the magic methods for BC reasons.
*
* @since 6.1.0
*
* @var array<string, bool> Key is the property name, value whether setting the property is allowed.
*/
private $compat_accessible_props = array(
'check_current_query' => false,
'col_meta' => false,
'table_charset' => false,
);

/**
* Connects to the database server and selects a database.
*
Expand Down Expand Up @@ -785,12 +798,7 @@ public function __get( $name ) {
* @param mixed $value The value to set.
*/
public function __set( $name, $value ) {
$protected_members = array(
'col_meta',
'table_charset',
'check_current_query',
);
if ( in_array( $name, $protected_members, true ) ) {
if ( isset( $this->compat_accessible_props[ $name ] ) && false === $this->compat_accessible_props[ $name ] ) {
return;
}
$this->$name = $value;
Expand All @@ -816,6 +824,9 @@ public function __isset( $name ) {
* @param string $name The private member to unset
*/
public function __unset( $name ) {
if ( isset( $this->compat_accessible_props[ $name ] ) && false === $this->compat_accessible_props[ $name ] ) {
return;
}
unset( $this->$name );
}

Expand Down
26 changes: 25 additions & 1 deletion tests/phpunit/tests/db/magicmethods.php
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,6 @@ public function test_magic_methods_declared_properties( $name, $default = null )
* @ticket 56034
*
* @dataProvider data_magic_methods_declared_settable_properties
* @dataProvider data_magic_methods_declared_non_settable_properties
*
* @param string $name Property name.
*/
Expand Down Expand Up @@ -282,6 +281,31 @@ public function test_magic_methods_declared_properties_non_settable( $name, $def
$this->assertSame( $default, $obj->$name, 'Property has been assigned a new value' );
}

/**
* Verify that select declared properties cannot be unset.
*
* Also note that as this test expects an error message, it cannot be combined with the
* test for the other magic methods.
*
* @ticket 56034
*
* @dataProvider data_magic_methods_declared_non_settable_properties
*
* @param string $name Property name.
* @param mixed $default Default value for the property.
*/
public function test_magic_unset_declared_properties_non_settable( $name, $default ) {
$obj = $this->get_clean_wpdb();

// Verify initial state. Note: each of these properties has a default value.
$this->assertTrue( isset( $obj->$name ), 'Unexpected initial state' );

// Unset the property value and verify the new state.
unset( $obj->$name );
$this->assertTrue( isset( $obj->$name ), 'Unsetting the property succeeded' );
$this->assertSame( $default, $obj->$name, 'Property has been unset' );
}

/**
* Data provider.
*
Expand Down

0 comments on commit 17d48b8

Please sign in to comment.